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
Known Workarounds
No response
Additional Information
No response
Nim Version
Description
https://nim-lang.org/docs/manual.html#exception-handling-defer-statement states that
bis either in the implicittryblock or it isn't. If it is, thenbshould be true by the timedoAssert bruns. If it isn't, thenb = trueshouldn't compile at all, becausebis not its lexical scope.Because it does compile, one can infer that the interpretation is that
bis in the implicittryblock, but in that case, thedoAssert bandb = truerun in the wrong order according to the manual.This is happening because of the presence of this
when nimvm::does not assert, i.e. runs
doAssert bandb = truein the manual-specified order.Current Output
Expected Output
Known Workarounds
No response
Additional Information
No response