-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clarify spec/implementation for let
: move or copy?
#13140
Comments
This is an important point to clear |
There is no difference between |
see #2314, |
Back then let x = obj.s
setLen(obj.s, 0)
echo x.len # old obj.s sequence or the updated one? What Nim tries to do here is to borrow from |
Oh and one more thing: For version the spec pretty much should say "whether a copy or a move is done is a quality of implementation issue". This has been true since a long time because |
but this seems like a bug, following code should use a move, not a copy since the last access to s is an assignment to a: template toStr(x): untyped = $cast[int](x[0].unsafeAddr)
var a = block:
let s = @[10, 11, 12]
echo s.toStr
s
echo a.toStr but instead it makes a copy: addresses are different: EDITactually I found a good workaround for this particular point, using var a = block:
var s = @[10, 11, 12]
echo s.toStr
move(s)
echo a.toStr 4489019480 |
when true: # example from https://github.com/nim-lang/Nim/issues/13771
var myGlobal = @[1,2,3,4,5]
proc foo() =
let myGlobalCopy = myGlobal # this currently does not make a copy
myGlobal[0] = 123
echo myGlobalCopy # @[123, 2, 3, 4, 5]
foo() |
Well it's what I remembered from the bug reports. I probably shouldn't have said "always". ;-) |
The spec is clear now about this. |
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 obscuremy intuition was: for
let b = expr(a)
, if nothing can modifya
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)
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:
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
--newruntime
and--gc:arc
makelet
copy (insidemodifyLet
), whereas without those flagslet
only copies at global scope but moves in function scopeHowever in the top-level snippet of current issue, both
--newruntime
,--gc:arc
and no flags causelet
to move instead of copy (ie the assert passes)proposal
one simple proposal is as follows:
byRef
andbyPtr
(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
The text was updated successfully, but these errors were encountered: