1

I am aware of a similar question that was once asked, but I am still rather perplexed after reading the accepted answer (to be clear, I do not see why the compiler does not have a special case for Drop::drop, as mentioned in the comments, since it already disallows moving out of an object that implements Drop). So let me please try to reiterate on this.

Suppose we have a struct Foo that owns some resources; say, a thread that has to be joined when the object goes out of scope (this situation can happen if we are writing an asynchronous runtime):

struct Foo {
    t: JoinHandle<()>,
}

Since std::ops::Drop::drop takes &mut self, with this definition we cannot really hope to join this thread in drop, because JoinHandle::join takes self by value. Therefore, we have to resort to making this field optional:

struct Foo {
    t: Option<JoinHandle<()>>,
}

And then we can go with if let Some(t) = self.t.take() { t.join(); }. But there still seem to be some unanswered questions here:

  1. Is the drop signature hinting us that the drop method may get called several times on some objects, or that drop may not be the last method that is called on an object during its lifetime? If yes, in which scenarios can this happen? Is it correct to write self.t.unwrap() in the example above?

  2. How to achieve similar semantics without introducing the overhead of Option (which may not in all cases get covered by niche optimisation and is anyway rather verbose)?

Mike Land
  • 436
  • 4
  • 15
  • If it were `drop(self)` would you allow that function to call another member functions? What would happen if `drop(self)` would call `foo(self)`? And if it called `bar(&mut self)` after joining your thread? – rodrigo Dec 25 '22 at 13:29
  • 2
    I still don't understand what this question is asking, that is different from the linked question. – Peter Hall Dec 25 '22 at 13:30
  • Subquestion 1: no, this is explained in the linked question (it's to prevent stack-overflows). – Peter Hall Dec 25 '22 at 13:33
  • Subquestion 2: The compiler doesn't force you to use `Option` anywhere. I don't follow the question. – Peter Hall Dec 25 '22 at 13:34
  • Well, I suppose we would not want to call the destructor in `foo`. This might not be easy to implement, surely, if we consider calling the destructor a part of `foo`'s code – Mike Land Dec 25 '22 at 13:52
  • @PeterHall, you are right about the subquestion 2, tried to fix – Mike Land Dec 25 '22 at 13:53
  • 2
    Your second question can be addressed here: [How can I move a value out of the argument to Drop::drop()?](/q/53254645/2189130) Your best options are `Option` (safe but has overhead) or `ManuallyDrop` (unsafe but has no overhead). – kmdreko Dec 25 '22 at 15:01

0 Answers0