diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 89e8911975..50b33d48a1 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -186,6 +186,12 @@ type forwardFieldUpdates*: seq[(PType, PNode, PType)] # object/tuple field definitions whose default values mention forward # types and need delayed const checking + 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.} @@ -369,6 +375,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 4b9dd3e7a4..cee96cd9d9 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1837,6 +1837,24 @@ proc typeSectionFinalPass(c: PContext, n: PNode) = for (owner, field, expectedType) in c.forwardFieldUpdates: semDelayedFieldDefault(c, owner, expectedType, field) c.forwardFieldUpdates = @[] + + # 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..