implements rfc #435; Better effect tracking for inner routines

This commit is contained in:
ringabout
2024-06-04 22:51:47 +08:00
parent 77c04092e0
commit f75bf972a5
3 changed files with 20 additions and 2 deletions

View File

@@ -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]

View File

@@ -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

View File

@@ -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,