Skip to content

Commit 82891e6

Browse files
authored
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.
1 parent 850f327 commit 82891e6

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

compiler/lineinfos.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ type
110110
hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
111111
hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
112112
hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
113+
hintUnknownRaises = "UnknownRaises",
113114
hintMsgOrigin = "MsgOrigin", # since 1.3.5
114115
hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
115116

@@ -236,6 +237,7 @@ const
236237
hintUser: "$1",
237238
hintUserRaw: "$1",
238239
hintExtendedContext: "$1",
240+
hintUnknownRaises: "$1 is a forward declaration without explicit .raises, assuming it can raise anything",
239241
hintMsgOrigin: "$1",
240242
hintDeclaredLoc: "$1"
241243
]

compiler/sempass2.nim

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type
8484
gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool
8585
isInnerProc: bool
8686
inEnforcedNoSideEffects: bool
87+
unknownRaises: seq[(PSym, TLineInfo)]
8788
currOptions: TOptions
8889
optionsStack: seq[(TOptions, TNoteKinds)]
8990
config: ConfigRef
@@ -639,6 +640,8 @@ proc importedFromC(n: PNode): bool =
639640
proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
640641
let pragma = s.ast[pragmasPos]
641642
let spec = effectSpec(pragma, wRaises)
643+
if spec.isNil and sfForward in s.flags:
644+
tracked.unknownRaises.add (s, n.info)
642645
mergeRaises(tracked, spec, n)
643646

644647
let tagSpec = effectSpec(pragma, wTags)
@@ -1506,7 +1509,7 @@ proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool =
15061509

15071510
proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg: string, hints: bool;
15081511
effectPredicate: proc (g: ModuleGraph; a, b: PNode): bool {.nimcall.};
1509-
hintsArg: PNode = nil; isForbids: bool = false) =
1512+
hintsArg: PNode = nil; isForbids: bool = false; unknownRaises: seq[(PSym, TLineInfo)] = @[]) =
15101513
# check that any real exception is listed in 'spec'; mark those as used;
15111514
# report any unused exception
15121515
var used = initIntSet()
@@ -1523,6 +1526,8 @@ proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg:
15231526
pushInfoContext(g.config, spec.info)
15241527
var rr = if r.kind == nkRaiseStmt: r[0] else: r
15251528
while rr.kind in {nkStmtList, nkStmtListExpr} and rr.len > 0: rr = rr.lastSon
1529+
for (s, info) in unknownRaises.items:
1530+
message(g.config, info, hintUnknownRaises, s.name.s)
15261531
message(g.config, r.info, if emitWarnings: warnEffect else: errGenerated,
15271532
renderTree(rr) & " " & msg & typeToString(r.typ))
15281533
popInfoContext(g.config)
@@ -1680,7 +1685,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
16801685
if not isNil(raisesSpec):
16811686
let useWarning = s.name.s == "=destroy"
16821687
checkRaisesSpec(g, useWarning, raisesSpec, t.exc, "can raise an unlisted exception: ",
1683-
hints=on, subtypeRelation, hintsArg=s.ast[0])
1688+
hints=on, subtypeRelation, hintsArg=s.ast[0], unknownRaises = t.unknownRaises)
16841689
# after the check, use the formal spec:
16851690
effects[exceptionEffects] = raisesSpec
16861691
else:

tests/errmsgs/tforwardraises.nim

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
discard """
2+
action: reject
3+
nimout: '''
4+
tforwardraises.nim(15, 14) Hint: n is a forward declaration without explicit .raises, assuming it can raise anything [UnknownRaises]
5+
tforwardraises.nim(14, 26) template/generic instantiation from here
6+
tforwardraises.nim(15, 14) Error: n(0) can raise an unlisted exception: Exception
7+
'''
8+
"""
9+
10+
# issue #24766
11+
12+
proc n(_: int)
13+
14+
proc s(_: int) {.raises: [CatchableError].} =
15+
if false: n(0)
16+
17+
proc n(_: int) = s(0)

0 commit comments

Comments
 (0)