From f75bf972a5d8789e2e8c05301067c4f3a0b9ee5a Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:51:47 +0800 Subject: [PATCH] implements rfc #435; Better effect tracking for inner routines --- compiler/ast.nim | 3 ++- compiler/semdata.nim | 2 ++ compiler/sempass2.nim | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 4de277ba9a..cb9567c7aa 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -331,7 +331,7 @@ type nfOpenSym # node is a captured sym but can be overriden by local symbols TNodeFlags* = set[TNodeFlag] - TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 47) + TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 48) tfVarargs, # procedure has C styled varargs # tyArray type represeting a varargs list tfNoSideEffect, # procedure type does not allow side effects @@ -403,6 +403,7 @@ type tfIsOutParam tfSendable tfImplicitStatic + tfTrackedProc # used for delayedEffects TTypeFlags* = set[TTypeFlag] diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 12930fecad..b74999b31f 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -168,6 +168,8 @@ 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. + delayedEffects*: Table[ItemId, seq[PSym]] + delayedEffectsInverted*: Table[ItemId, ItemId] TBorrowState* = enum bsNone, bsReturnNotMatch, bsNoDistinct, bsGeneric, bsNotSupported, bsMatch diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index f611ee8fe1..1f1f130df3 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1024,7 +1024,14 @@ proc trackCall(tracked: PEffects; n: PNode) = else: if laxEffects notin tracked.c.config.legacyFeatures and a.kind == nkSym and a.sym.kind in routineKinds: - propagateEffects(tracked, n, a.sym) + if tfTrackedProc in a.sym.typ.flags: + propagateEffects(tracked, n, a.sym) + else: + if a.sym.typ.itemId notin tracked.c.delayedEffects: + tracked.c.delayedEffects[a.sym.typ.itemId] = @[tracked.owner] + else: + tracked.c.delayedEffects[a.sym.typ.itemId].add tracked.owner + tracked.c.delayedEffectsInverted[tracked.owner.typ.itemId] = a.sym.typ.itemId else: mergeRaises(tracked, effectList[exceptionEffects], n) mergeTags(tracked, effectList[tagEffects], n) @@ -1728,6 +1735,14 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) = if strictNotNil in c.features and s.kind in {skProc, skFunc, skMethod, skConverter}: checkNil(s, body, g.config, c.idgen) + if s.typ.itemId notin c.delayedEffectsInverted: + s.typ.flags.incl tfTrackedProc + + if s.typ.itemId in c.delayedEffects: + for sym in c.delayedEffects[s.typ.itemId]: + trackProc(c, sym, sym.ast[bodyPos]) + # todo call track delayedEffects recursively + proc trackStmt*(c: PContext; module: PSym; n: PNode, isTopLevel: bool) = case n.kind of {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef, nkFuncDef,