Smart drop order?

I declare a container type like so:

struct B<'a, T> (Option<&'a T>);

and I create a data type like so:

struct C(usize);

And I run this code:

fn main() {
    let mut cont = B(None);
    let data = C(3);
    cont.0 = Some(&data);
}

Then the order of variable creation and destruction is:

+ cont
+ data
- data
- cont

Which is okay since there is no need to assure the validity of the references within a struct if it's all going to be dropped anyway.
But what if we add the following:

impl<'a, T> Drop for B<'a, T> {
    fn drop(&mut self) {
        println!("B dropped");
    }
}

Then, the order doesn't work:

+ cont
+ data
- data
- cont // Error needs access to data

Playground
Why doesn't rust automatically re-adjust the drop order to this:

+ cont
+ data
- cont
- data

Please note that this is out of curiosity and am not in a situation requiring this.

1 Like

Instead of the compiler changing the drop order around (which can be undesirable from a readability/maintenance perspective, and may also lead to unsoundness in unsafe code relying on today's rules), there's a way to inform the compiler that you're not touching contained references in your Drop impl: playground. Unfortunately, this is unstable.

3 Likes

Wow that's an interesting place to fit a meta attribute, thanks for the info!