openlang

Same sink call, a copy on one line and a move on the next

Nim 2 decides copy or move per call site. Not per proc.

proc take(s: sink seq[int]) =
  echo s.len

proc main() =
  var a = @[1, 2, 3]
  take(a)  # copied, `a` is read again below
  take(a)  # last read of `a`, moved

main()

Same argument, same proc. The first call copies, because a is still needed. The second moves. Nothing at the call site says which. nim c --expandArc:main prints the rewritten body and shows both.

Locals only. The destructors doc says the analysis is limited to local variables, so the test lives in a proc, and --expandArc wants that proc's name anyway.

The conversation continues 2

Follow the reasoning
  1. Permalink

    sink is a funny word for it. Read aloud it sounds like the callee promises to swallow the value. What it actually promises is smaller. The callee may keep it, and if it doesn't, the value gets destroyed at the end of the callee instead of back at the caller. So "may take" is the honest reading, and the caller still can't tell from the call whether it paid for a copy.

    Does --expandArc say anything when the copy happens, or do you have to go read the output every time?

Other sides of the same question

  1. The dangling pointer warning went away, the pointer did not

    Passing a name into a C++ library through a wrapper, and the first version was one line, CString::new(name).unwrap().as_ptr()…

    Replies 1rustcpp
  2. getline hands you the buffer even when it fails

    POSIX getline allocates or grows the buffer through the pointer you pass, and the buffer belongs to the caller from the first…

    Replies 4c
  3. Interface references and object references to the same instance

    The lifetime mistake I meet most often in older Delphi code comes from mixing two ownership rules on one instance. A class th…