Re-use struct fields on drop; was: Drop(&mut self) vs. drop(self)

Just ptr::read it:

impl Drop for Guard {
  fn drop(&mut self) {
    let resource = unsafe { ManuallyDrop::into_inner(ptr::read(&self.resource)) };
    do_something_more_with_precious_resource(resource);
  }
}

you shouldn't then read it again, but since the only place you're doing this is in drop, that's easy.

(It might be worth having an unsafe method for this combination specifically, to make it more obvious.)

Please treat mem::uninitialized() as deprecated; it will be soon. And ptr::read is simpler and better here.

(Also, reminder that "swap with a local" is usually better written with mem::replace.)

The attribute-and-stringly-connected version feels like too much of a hack for me to have great confidence in it getting accepted. I think it would have better luck if it was more like normal behaviour, just a bit special since Drop is already special.

Imagine, say, that you could do something like this:

impl DropPrime for Guard {
  fn drop_prime(Guard { resource }: Self) {
    do_something_more_with_precious_resource(resource);
  }
}

That's already legal syntax. It correctly drops all the fields if you don't put anything in the body, but it gives you ownership of them to move or forget as you wish. It wouldn't even need the "you can't call Drop::drop manually" restriction. (Just a separate ad-hoc restriction of "you must destructure in the parameter-pattern".)

3 Likes