I agree that the wrapper object based solution is the only solution for the moment, as other solutions leveraging on generics and distinct types seems to not work.
here's another take that is not calling the destructor , but it will if <https://github.com/nim-lang/Nim/issues/23394> is solved type Ownership = enum Owned Borrowed Wrapper[T; ownership: static Ownership] = distinct T proc `=destroy`[T, ownership](val: Wrapper[T, ownership]) = echo "destroying ", val # ------------------------------ type MyCString[ownership: static Ownership] = Wrapper[cstring, ownership] proc `$`(x: MyCString): string {.borrow.} proc main() = var mycstring = cast[MyCString[Owned]](alloc(11)) let str = "helloworld" copyMem(mycstring.cstring, str[0].addr, str.len) echo mycstring main() Run
