From 82891e6850c4b10c123f7fa5fcaaade1baaded44 Mon Sep 17 00:00:00 2001 From: metagn Date: Tue, 11 Mar 2025 16:24:45 +0300 Subject: [PATCH] give hint for forward declarations with unknown raises effects (#24767) refs #24766 Detect when we track a call to a forward declaration without explicit `raises` effects, then when the `raises` check fails for the proc, give a hint that this forward declaration was tracked as potentially raising any exception. --- compiler/lineinfos.nim | 2 ++ compiler/sempass2.nim | 9 +++++++-- tests/errmsgs/tforwardraises.nim | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/errmsgs/tforwardraises.nim diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 248e843267..292a02e60e 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -110,6 +110,7 @@ type hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace", hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro", hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext", + hintUnknownRaises = "UnknownRaises", hintMsgOrigin = "MsgOrigin", # since 1.3.5 hintDeclaredLoc = "DeclaredLoc", # since 1.5.1 @@ -236,6 +237,7 @@ const hintUser: "$1", hintUserRaw: "$1", hintExtendedContext: "$1", + hintUnknownRaises: "$1 is a forward declaration without explicit .raises, assuming it can raise anything", hintMsgOrigin: "$1", hintDeclaredLoc: "$1" ] diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 6730861d81..0aa96bd6ea 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -84,6 +84,7 @@ type gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool isInnerProc: bool inEnforcedNoSideEffects: bool + unknownRaises: seq[(PSym, TLineInfo)] currOptions: TOptions optionsStack: seq[(TOptions, TNoteKinds)] config: ConfigRef @@ -639,6 +640,8 @@ proc importedFromC(n: PNode): bool = proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = let pragma = s.ast[pragmasPos] let spec = effectSpec(pragma, wRaises) + if spec.isNil and sfForward in s.flags: + tracked.unknownRaises.add (s, n.info) mergeRaises(tracked, spec, n) let tagSpec = effectSpec(pragma, wTags) @@ -1506,7 +1509,7 @@ proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool = proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg: string, hints: bool; effectPredicate: proc (g: ModuleGraph; a, b: PNode): bool {.nimcall.}; - hintsArg: PNode = nil; isForbids: bool = false) = + hintsArg: PNode = nil; isForbids: bool = false; unknownRaises: seq[(PSym, TLineInfo)] = @[]) = # check that any real exception is listed in 'spec'; mark those as used; # report any unused exception var used = initIntSet() @@ -1523,6 +1526,8 @@ proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg: pushInfoContext(g.config, spec.info) var rr = if r.kind == nkRaiseStmt: r[0] else: r while rr.kind in {nkStmtList, nkStmtListExpr} and rr.len > 0: rr = rr.lastSon + for (s, info) in unknownRaises.items: + message(g.config, info, hintUnknownRaises, s.name.s) message(g.config, r.info, if emitWarnings: warnEffect else: errGenerated, renderTree(rr) & " " & msg & typeToString(r.typ)) popInfoContext(g.config) @@ -1680,7 +1685,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) = if not isNil(raisesSpec): let useWarning = s.name.s == "=destroy" checkRaisesSpec(g, useWarning, raisesSpec, t.exc, "can raise an unlisted exception: ", - hints=on, subtypeRelation, hintsArg=s.ast[0]) + hints=on, subtypeRelation, hintsArg=s.ast[0], unknownRaises = t.unknownRaises) # after the check, use the formal spec: effects[exceptionEffects] = raisesSpec else: diff --git a/tests/errmsgs/tforwardraises.nim b/tests/errmsgs/tforwardraises.nim new file mode 100644 index 0000000000..9628f69730 --- /dev/null +++ b/tests/errmsgs/tforwardraises.nim @@ -0,0 +1,17 @@ +discard """ + action: reject + nimout: ''' +tforwardraises.nim(15, 14) Hint: n is a forward declaration without explicit .raises, assuming it can raise anything [UnknownRaises] +tforwardraises.nim(14, 26) template/generic instantiation from here +tforwardraises.nim(15, 14) Error: n(0) can raise an unlisted exception: Exception +''' +""" + +# issue #24766 + +proc n(_: int) + +proc s(_: int) {.raises: [CatchableError].} = + if false: n(0) + +proc n(_: int) = s(0)