Skip to content

fixes ReraiseDefect after typeless except: + finally: (cpp backend)#25777

Open
puffball1567 wants to merge 1 commit intonim-lang:develfrom
puffball1567:fix-typeless-except-null
Open

fixes ReraiseDefect after typeless except: + finally: (cpp backend)#25777
puffball1567 wants to merge 1 commit intonim-lang:develfrom
puffball1567:fix-typeless-except-null

Conversation

@puffball1567
Copy link
Copy Markdown

Bug

A bare except: followed by a finally: block raises a spurious ReraiseDefect: no exception to reraise when compiled with nim cpp:

proc test() =
  try:
    raise newException(CatchableError, "x")
  except:
    discard
  finally:
    echo "finally"

test()
echo "after"

Expected output:

finally
after

Actual output:

finally
fatal.nim(53)            sysFatal
Error: unhandled exception: no exception to reraise [ReraiseDefect]

This reproduces on every memory manager (--mm:arc, --mm:orc, --mm:refc).

Root cause

genTryCpp emits try { ... } catch (Exception* T_) { ... } followed by a finally block that ends with if (T_) std::rethrow_exception(T_);. In the typed except branches the codegen explicitly sets T_ = nullptr; once the exception is handled, so the rethrow check in the finally is a no-op.

The typeless except: branch (the if t[i].len == 1 arm) emitted only popCurrentException() and forgot to clear T_. After the handler body finished, T_ still pointed at the original exception, so the trailing if (T_) std::rethrow_exception(T_); rethrew it. By that point Nim's current-exception stack had already been popped, and the rethrow surfaced as ReraiseDefect.

Fix

Emit T_ = nullptr; at the start of the typeless except: handler body, mirroring what is already done for the typed branches. This is the same one-line treatment that fixed the analogous typed-except case for #5871.

Tests

Adds tests/exception/treraise_typeless_except_finally.nim, exercising the bug pattern on --mm:arc, --mm:orc, and --mm:refc.

Locally:

  • tests/exception/ — 43 PASS, 0 FAIL, 3 SKIP
  • new test passes on all three memory managers

Backport

Tagged [backport] in the commit message — the same bug exists in version-2-2 and the fix applies cleanly there.

Related

Independent of, but in the same family as, #25775 (also currently open). Both are silent-finally / cpp-backend exception handling fixes; they touch different lines of genTryCpp and don't conflict.

[backport]

A bare `except:` followed by a `finally:` block raises a spurious
`ReraiseDefect: no exception to reraise` when compiled with `nim cpp`:

  proc test() =
    try:
      raise newException(CatchableError, "x")
    except:
      discard
    finally:
      echo "finally"
  test()

Expected output: just `finally` and clean exit.
Actual output:
  finally
  fatal.nim(53)            sysFatal
  Error: unhandled exception: no exception to reraise [ReraiseDefect]

This reproduces on every memory manager (arc/orc/refc).

Root cause:
  `genTryCpp` emits `try { ... } catch (Exception* T_) { ... }` followed
  by a finally block that executes `if (T_) std::rethrow_exception(T_);`.
  In the *typed* except branches the codegen explicitly sets
  `T_ = nullptr;` once the exception is handled, so the rethrow check
  in the finally is a no-op.

  The typeless `except:` branch (handled by the `if t[i].len == 1`
  arm) emitted only `popCurrentException()` and forgot to clear `T_`.
  After the handler body finished, `T_` still pointed at the original
  exception, so the trailing `if (T_) std::rethrow_exception(T_);`
  rethrew it.  By that point Nim's current-exception stack had already
  been popped, and the rethrow surfaced as `ReraiseDefect`.

Fix:
  Emit `T_ = nullptr;` at the start of the typeless `except:` handler
  body, mirroring what is already done for the typed branches.  This
  is the same one-line treatment that fixed the analogous typed-except
  case for nim-lang#5871.

Adds `tests/exception/treraise_typeless_except_finally.nim`, which
runs on `--mm:arc`, `--mm:orc`, and `--mm:refc`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant