Reputation: 49
I'm trying to understand how Rust handles value dropping in different notations. Consider the following code:
let s = String::from("Hello, Rust!");
drop(s); // method 1
(|_| ())(s); // method 2
{ s }; // method 3
I want to better understand the ownership and scope rules that govern how values like s
are dropped in each case. Could someone clarify what's happening under the hood in these three scenarios?
I understand how the drop()
function works in general, but a detailed explanation of the internals and how it compares to the other two scenarios would be much appreciated!
Upvotes: 0
Views: 81
Reputation: 169320
Ultimately, the effect these all have on s
is identical. They all do exactly the same thing but sometimes with different underlying mechanisms:
s
gets moved somewhere else.Then, when you try to use s
you'll get an error because the value was moved.
drop(s);
moves s
into a function argument. The function then returns, and the argument goes out of scope, causing the value to be dropped.
(|_| ())(s);
does exactly the same thing, just using a closure that has exactly the same semantics as drop
. (Okay, not exactly: because the argument name is _
this indicates the value is not bound at all. That is, the value is dropped when the function is called, instead of when it returns. However, since the function body is essentially empty, this is a distinction without a difference. The distinction might be meaningful in other scenarios where we aren't just dropping a value, though.)
Note that you can also use the following closure-based mechanisms:
(move || s)();
moves s
into the closure, which is then called, returning the value, which doesn't get bound anywhere, and is therefore destroyed.move || s;
moves s
into the closure, then drops the closure without calling it. This transitively drops the value.{ s };
moves the value into the block's return value, which is not bound to any variable and therefore is dropped. Note that s;
does the same thing.
Many of these approaches can be combined together to yield yet more approaches that are more verbose and difficult to understand at first glance. For example, (move || s)();
, s;
, and { s };
all work pretty much the same way and can be combined in various ways, but this isn't really useful.
I would consider the drop(s)
approache to be idiomatic. The others would seem like typos without an accompanying comment indicating intent, at which point the additional exposition would make the idiomatic options more terse.
Upvotes: 5