From 13f4ed0d703143be9bdf07442e8847a1bed5d398 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 11 Aug 2026 22:27:49 +0200 Subject: [PATCH] fixes #26025 (#26076) (cherry picked from commit ebfd1c50902816bfe761852044a0a4900fb0ef7c) --- compiler/semdata.nim | 7 +++++++ compiler/semstmts.nim | 17 ++++++++++++++++ compiler/semtypes.nim | 19 ++++++++++++++++++ tests/arc/tarcmisc.nim | 44 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) 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..