This commit is contained in:
Araq
2026-06-29 19:48:20 +02:00
parent 7c1108ccbe
commit a9b241ff05
10 changed files with 184 additions and 2 deletions

View File

@@ -496,8 +496,19 @@ proc writeTypeDef(w: var Writer; dest: var IcBuilder; typ: PType) =
# name in isolation (cg seeks the `.t.nif`/`.s.nif` index entry), so its
# fields must be DEFS here, not entry-deduped SymUses whose def lives
# elsewhere in the `(lowered)` entry and is never read by the seek.
#
# `emittedFieldSyms` only guards against a field being def'd twice WITHIN one
# reclist, so scope it per-reclist: a generic object and its instances SHARE one
# field PSym (same itemId) yet each instance carries a DISTINCT field type (e.g.
# `MDigest[256].data: array[32,byte]` vs `MDigest[384].data: array[48,byte]`), so
# each reclist needs its OWN typed def. A Writer-global set deduped every instance
# after the first to a typeless `SymUse` stub (nil typ/owner on load → crash in
# destructor lifting). Field NIF names are local (no module suffix, not in the
# global `c.syms`), so def'ing the same field in two reclists never collides.
inc w.inTypeReclist
let savedFieldSyms = move w.emittedFieldSyms
writeNode(w, dest, typ.nImpl)
w.emittedFieldSyms = savedFieldSyms
dec w.inTypeReclist
writeSym(w, dest, typ.ownerFieldImpl)
writeSym(w, dest, typ.symImpl)

View File

@@ -29,7 +29,7 @@ const
nimEnableCovariance* = defined(nimEnableCovariance)
icFormatVersion* = "25"
icFormatVersion* = "26"
## Version of the IC cache format (the sem-NIF module layout written by
## ast2nif.nim plus the iface/impl/edges side files). Bump it whenever
## that layout changes: `commandIc` wipes a nimcache whose `ic.version`

View File

@@ -1921,7 +1921,11 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
let strType = getSysType(c.graph, n.info, tyString)
var msgReg: TDest = c.getTemp(strType)
let fieldName = $accessExpr[1]
let msg = genFieldDefect(c.config, fieldName, disc.sym)
# Re-navigate the discriminant in the object type: under `nim ic` `disc.sym` is a
# field-use stub with a nil `owner`, which `genFieldDefect` dereferences. Look up the
# canonical discriminant field by name. Byte-neutral for non-IC (returns the same sym).
let dfield = lookupFieldAgain(accessExpr[0].typ, disc.sym)
let msg = genFieldDefect(c.config, fieldName, dfield)
let strLit = newStrNode(msg, accessExpr[1].info)
strLit.typ = strType
c.genLit(strLit, msgReg)