diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 1202aa0536..77c09d82cf 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -11,7 +11,11 @@ proc canRaiseDisp(p: BProc; n: PNode): bool = # we assume things like sysFatal cannot raise themselves - if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}: + if n.kind == nkSym and n.sym.kind == skMethod: + # A base method may be overridden by a branch with a wider exception set. + # Its inferred effects describe only the base body, not every vtable target. + result = true + elif n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}: result = false elif optPanics in p.config.globalOptions or (n.kind == nkSym and sfSystemModule in getModule(n.sym).flags and diff --git a/tests/method/tmethod_virtual_raise.nim b/tests/method/tmethod_virtual_raise.nim new file mode 100644 index 0000000000..6bc1575282 --- /dev/null +++ b/tests/method/tmethod_virtual_raise.nim @@ -0,0 +1,20 @@ +discard """ + output: '''caught''' +""" + +type + Base = ref object of RootObj + Child = ref object of Base + +method run(value: Base): string {.base.} = + result = "base" + +method run(value: Child): string = + raise newException(ValueError, "child") + +let value: Base = Child() +try: + discard value.run() + quit "virtual method did not raise" +except ValueError: + echo "caught"