diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 376821e7e9..a8550e5d7c 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -183,6 +183,12 @@ type inUncheckedAssignSection*: int importModuleLookup*: Table[int, seq[int]] # (module.ident.id, [module.id]) skipTypes*: seq[PNode] # used to skip types between passes in type section. So far only used for inheritance, sets and generic bodies. + forwardFlagUpdates*: seq[(PType, PType)] + # (owner, son) pairs whose `propagateToOwner` ran on a not yet reified + # forward type and has to be redone in the final pass + staleTypeFlags*: IntSet + # ids of the owners in `forwardFlagUpdates`; their flags are provisional + # too, so reading them makes the reader provisional in turn inTypeofContext*: int semAsgnOpr*: proc (c: PContext; n: PNode; k: TNodeKind): PNode {.nimcall.} @@ -357,6 +363,7 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = unknownIdents: initIntSet(), shadowDiscardedDefs: initIntSet(), realizedDefs: initIntSet(), + staleTypeFlags: initIntSet(), cache: graph.cache, graph: graph, signatures: initStrTable(), diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8f30374a5b..8ec7f0ab8f 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1787,6 +1787,23 @@ proc checkForMetaFields(c: PContext; n: PNode; hasError: var bool) = internalAssert c.config, false proc typeSectionFinalPass(c: PContext, n: PNode) = + # a son that still was a `tyForward` could not propagate `tfHasAsgn` and + # friends to its owner back then, see `rememberFlagUpdate`. Now that every + # forward declaration has a body, redo those propagations. They are recorded + # in declaration order rather than dependency order and an owner can itself + # be the son of another pair, so repeat until nothing changes; this + # terminates because flags are only ever added. + if c.forwardFlagUpdates.len > 0: + let updates = move c.forwardFlagUpdates + c.staleTypeFlags = initIntSet() + var changed = true + while changed: + changed = false + for (owner, elem) in updates: + let before = owner.flags + propagateToOwner(owner, elem) + if owner.flags != before: changed = true + for i in 0.. 0: c.getCurrOwner else: rectype.sym for i in 0..