I'm wrapping C code that returns owned cstring. If I convert wrapped distinct cstring type to nim string, destructor is not called. If I return distinct cstring type, destructor is called. {. emit: [ """ char *allocCString() { char *result = malloc(10 + 1); strcpy(result, "HelloWorld"); return result; } """ ] .} proc rawWrapper(): cstring {.importc: "allocCString", cdecl.} # ------------------------- type OwnedString = distinct cstring proc `=destroy`(s: OwnedString) = dealloc(s.cstring) echo "Deallocating OwnedString" func `$`(s: OwnedString): string {.borrow.} proc idiomaticWrapper(): OwnedString = rawWrapper().OwnedString proc leakyWrapper(): string = let ostring = rawWrapper().OwnedString $ostring # ------------------------- proc main() = when true: # destructor not called - definitely lost: 11 bytes in 1 blocks # doesn't leak with --cursorInference:off let s = leakyWrapper() else: # destructor called - All heap blocks were freed -- no leaks are possible let s = idiomaticWrapper() echo s main() Run --expandArc: leakyWrapper var ostring_cursor ostring_cursor = OwnedString(rawWrapper()) result = $ostring_cursor -- end of expandArc ------------------------ Run
could you please explain what is happening here? if `$` generates a copy, why ARC is not adding destructor call?