Skip to content

defer in else branch of when nimvm has too-narrow scope #26050

Description

@tersec

Nim Version

Nim Compiler Version 2.2.10 [Linux: amd64]
Compiled at 2026-05-27
Copyright (c) 2006-2026 by Andreas Rumpf

active boot switches: -d:release
Nim Compiler Version 2.2.11 [Linux: amd64]
Compiled at 2026-07-27
Copyright (c) 2006-2026 by Andreas Rumpf

git hash: a0d09f01c511b40800d93e8ad23cfcf8939fffed
active boot switches: -d:release
Nim Compiler Version 2.3.1 [Linux: amd64]
Compiled at 2026-07-27
Copyright (c) 2006-2026 by Andreas Rumpf

git hash: 2d8114929450ad621a2ef0108bbf1267c45145fc
active boot switches: -d:release

Description

proc p =
  when nimvm: discard
  else:
    var b: bool
    defer: doAssert b
  b = true
p()

https://nim-lang.org/docs/manual.html#exception-handling-defer-statement states that

Instead of a try finally statement a defer statement can be used, which avoids lexical nesting and offers more flexibility in terms of scoping as shown below.

Any statements following the defer will be considered to be in an implicit try block in the current block

b is either in the implicit try block or it isn't. If it is, then b should be true by the time doAssert b runs. If it isn't, then b = true shouldn't compile at all, because b is not its lexical scope.

Because it does compile, one can infer that the interpretation is that b is in the implicit try block, but in that case, the doAssert b and b = true run in the wrong order according to the manual.

This is happening because of the presence of this when nimvm::

proc p =
  when true:
    var b: bool
    defer: doAssert b
  b = true
p()

does not assert, i.e. runs doAssert b and b = true in the manual-specified order.

Current Output

/tmp/h.nim(7)            h
/tmp/h.nim(5)            p
/tmp/nim23/lib/std/assertions.nim(45) failedAssertImpl
/tmp/nim23/lib/std/assertions.nim(40) raiseAssert
/tmp/nim23/lib/system/fatal.nim(62) sysFatal
Error: unhandled exception: /tmp/h.nim(5, 12) `b`  [AssertionDefect]
Error: execution of an external program failed: '/tmp/h'

Expected Output

Internal consistency

Known Workarounds

No response

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions