-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
should let always move, always copy, or sometimes move and sometimes copy (and in which conditions, and for which --gc flags)?
should an object passing by let argument make a move or copy?
Clarifying this matters as APIs may make assumptions that may not reflect current/future reality and break at some point.
This is not clear right now and the current compiler at least sometimes makes a move instead of a copy.
If --newruntime or --gc:arc is used, whether a move or copy is used is currently obscure
my intuition was: for let b = expr(a), if nothing can modify a after that statement, then make a move, else make a copy. However that's not what I'm observing (neither with --gc:arc nor without that flag).
Example
this came up here: #13116 (comment)
type Foo = distinct string
type Bar = ref object
foo: Foo
proc main(a: Bar)=
let b = a.foo
doAssert cast[int](a.foo.string[0].unsafeAddr) == cast[int](b.string[0].unsafeAddr)
let a = Bar(foo: "abc".Foo)
main(a)it seems to me in this case at least that the move is safe, so the assert should (and in fact does) pass, but in #13116 (comment) @Araq says:
That's a bug, finally addressed in --gc:arc, the move is unsound.
however, the assert passes even with --gc:arc or --newruntime
Additional Information
-
I'm using recent devel a33b72a
-
Let behaves differently in proc for default gc #2314 is related but different:
both--newruntimeand--gc:arcmakeletcopy (insidemodifyLet), whereas without those flagsletonly copies at global scope but moves in function scope
However in the top-level snippet of current issue, both --newruntime , --gc:arc and no flags cause let to move instead of copy (ie the assert passes)
proposal
one simple proposal is as follows:
- let and var always copy, never move
- use
byRefandbyPtr(from [superseded] ref syntax for lvalue expressions:byRef: myref=x[1].foo[2]#11824) to get guaranteed reference semantics (no copy)
the only tricky point is backward compatibility, but at least it's simple to grok