mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-05 15:08:44 +00:00
better type keys
This commit is contained in:
@@ -2236,60 +2236,6 @@ proc sealLoadedBackendEntities*(c: var DecodeContext) =
|
||||
for _, v in c.types:
|
||||
if v[0] != nil and v[0].state == Complete: v[0].state = Sealed
|
||||
|
||||
proc preloadLoweredDefs(c: var DecodeContext; n: var Cursor; thisModule: string;
|
||||
localSyms: var Table[string, PSym]) =
|
||||
## One pre-scan over a `.t.nif` body that fully loads EVERY inline def it
|
||||
## carries before the body is decoded: suffix-less locals into `localSyms`,
|
||||
## backend-minted `@bk` syms into `c.syms`, `@bk` types into `c.types`. These
|
||||
## transform-created entities have NO module index entry, so a later reference
|
||||
## — in the body, or inside a loaded type that `typeKey`/codegen later walks
|
||||
## (where the index-based force-load would assert) — must find them already
|
||||
## loaded. The writer emits defs before uses, so a forward walk that loads each
|
||||
## in place suffices.
|
||||
if n.kind != ParLe:
|
||||
inc n
|
||||
return
|
||||
var depth = 0
|
||||
while true:
|
||||
if n.kind == ParLe:
|
||||
if n.tagId == sdefTag:
|
||||
let nm = n.firstSon
|
||||
if nm.kind == SymbolDef:
|
||||
let symName = pool.syms[nm.symId]
|
||||
let sn = parseSymName(symName)
|
||||
if sn.module.len == 0:
|
||||
if symName notin localSyms:
|
||||
let module = moduleId(c, thisModule)
|
||||
let val = addr c.mods[module].symCounter
|
||||
inc val[]
|
||||
let sym = PSym(itemId: itemId(module.int32, val[]), kindImpl: skStub,
|
||||
name: c.cache.getIdent(sn.name), disamb: sn.count.int32,
|
||||
state: Complete)
|
||||
localSyms[symName] = sym
|
||||
inc n
|
||||
loadSymFromCursor(c, sym, n, thisModule, localSyms)
|
||||
sym.state = c.loadedState
|
||||
continue
|
||||
elif sn.module.endsWith(BackendLocalMarker):
|
||||
let sym = c.loadSymStub(nm.symId, thisModule, localSyms)
|
||||
if sym.state == Partial:
|
||||
sym.state = c.loadedState
|
||||
inc n
|
||||
loadSymFromCursor(c, sym, n, thisModule, localSyms)
|
||||
continue
|
||||
elif n.tagId == tdefTag:
|
||||
let nm = n.firstSon
|
||||
if nm.kind == SymbolDef and pool.syms[nm.symId].endsWith(BackendLocalMarker):
|
||||
discard loadTypeStub(c, n, localSyms)
|
||||
continue
|
||||
inc depth
|
||||
elif n.kind == ParRi:
|
||||
dec depth
|
||||
if depth == 0:
|
||||
inc n
|
||||
break
|
||||
inc n
|
||||
|
||||
proc resolveHookSym*(c: var DecodeContext; symId: nifstreams.SymId): PSym
|
||||
|
||||
proc repTagToOp(tagId: TagId): (bool, TTypeAttachedOp) =
|
||||
|
||||
@@ -29,7 +29,7 @@ const
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
icFormatVersion* = "16"
|
||||
icFormatVersion* = "17"
|
||||
## 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`
|
||||
|
||||
@@ -139,6 +139,25 @@ proc maybeImported(c: var Context; s: PSym; conf: ConfigRef) {.inline.} =
|
||||
if s != nil and {sfImportc, sfExportc} * s.flagsImpl != {}:
|
||||
c.symKey(s, conf)
|
||||
|
||||
proc backendTypeName(t: PType; conf: ConfigRef): string =
|
||||
## Stable cross-module identity of a backend-minted (lower-stage) type: its
|
||||
## serialized `@bk` NIF name (mirrors ast2nif.nifTypeName). A closure-env
|
||||
## object/ref minted by the `lower` stage has NO stable STRUCTURAL key — its
|
||||
## captured-field types re-resolve to different modules in the producing vs the
|
||||
## consuming process (e.g. field `x0` → `int` in the producer, → the consumer's
|
||||
## alias in the consumer) — but this name (kind + item + home-module suffix) is
|
||||
## identical in both, because the consumer loads the producer's name verbatim.
|
||||
## Keying hooks by it makes producer `setAttachedOp` and consumer `getAttachedOp`
|
||||
## agree. The trailing `@bk` (= ast2nif.BackendLocalMarker) keeps it disjoint
|
||||
## from any normal type's structural key.
|
||||
result = "`t"
|
||||
result.addInt ord(t.kind)
|
||||
result.add '.'
|
||||
result.addInt t.uniqueId.item
|
||||
result.add '.'
|
||||
result.add modname(t.uniqueId.module, conf)
|
||||
result.add "@bk"
|
||||
|
||||
proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) =
|
||||
if t == nil:
|
||||
c.m.addEmpty()
|
||||
@@ -148,6 +167,14 @@ proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef
|
||||
assert c.tl != nil
|
||||
c.tl(t)
|
||||
|
||||
if t.uniqueId.isBackendMinted:
|
||||
# Backend-minted (lower-stage) closure-env types key by their stable NIF name,
|
||||
# never by structure (which diverges across the NIF boundary). An env `ref`
|
||||
# that is itself NOT backend-minted still keys stably: it recurses here and
|
||||
# reaches its `@bk` object, which short-circuits to a stable name.
|
||||
c.m.addSymbol backendTypeName(t, conf)
|
||||
return
|
||||
|
||||
case t.kind
|
||||
of tyGenericInvocation:
|
||||
for a in t.sonsImpl:
|
||||
|
||||
Reference in New Issue
Block a user