Files
Nim/tests/destructor/t23837.nim
ringabout 3617d2e077 fixes lastRead uses the when nimvm branch (#24834)
```nim
proc foo =
  var x = "1234"
  var y = x
  when nimvm:
    discard
  else:
    var s = x
    doAssert s == "1234"
  doAssert y == "1234"

static: foo()
foo()
```
`dfa` chooses the `nimvm` branch, `x` is misread as a last read and
`wasMoved`.

`injectDestructor` is used for codegen and is not used for vmgen. It's
reasonable to choose the codegen path instead of the `nimvm` path so the
code works for codegen. Though the problem is often hidden by
`cursorinference` or `optimizer`.

found in https://github.com/nim-lang/Nim/pull/24831
2025-04-02 09:29:15 +02:00

66 lines
1.1 KiB
Nim

discard """
output: '''
Deallocating OwnedString
HelloWorld
'''
matrix: "--cursorinference:on; --cursorinference:off"
target: "c"
"""
# bug #23837
{.
emit: [
"""
#include <stdlib.h>
#include <string.h>
char *allocCString() {
char *result = (char *) malloc(10 + 1);
strcpy(result, "HelloWorld");
return result;
}
"""
]
.}
proc rawWrapper(): cstring {.importc: "allocCString", cdecl.}
proc free(p: pointer) {.importc: "free", cdecl.}
# -------------------------
type OwnedString = distinct cstring
proc `=destroy`(s: OwnedString) =
free(cstring s)
echo "Deallocating OwnedString"
func `$`(s: OwnedString): string {.borrow.}
proc leakyWrapper(): string =
let ostring = rawWrapper().OwnedString
$ostring
# -------------------------
proc main() =
# destructor not called - definitely lost: 11 bytes in 1 blocks
# doesn't leak with --cursorInference:off
let s = leakyWrapper()
echo s
main()
block:
proc foo =
var x = "1234"
var y = x
when nimvm:
discard
else:
var s = x
doAssert s == "1234"
doAssert y == "1234"
static: foo()
foo()