Why does Drop
’s method have signature fn drop(&mut self)
instead of fn drop(self)
? This makes it difficult to move values out of the fields e.g. self.join_handle.join()
or std::mem::drop(self.file)
(error: cannot move out of type X
, which defines the Drop
trait).
Let's look at how std::mem::drop
is implemented:
pub fn drop<T>(_x: T) { }
That's right: it's an empty function! That's because it takes advantage of move semantics to acquire ownership of its argument. If T
implements Drop
, the compiler automatically inserts a call to Drop::drop(_x)
at the end of the function. This happens to all arguments received by value (that is, in fact, all arguments whatsoever, but dropping a reference doesn't drop the referent).
Now consider what would happen if Drop::drop
took its argument by value: the compiler would try to invoke Drop::drop
on the argument within Drop::drop
— this would cause a stack overflow! And of course, you would be able to call mem::drop
on the argument, which would also try to recursively call Drop::drop
.