Is it possible to control which object goes out of scope first?

Hi, so I'm having a trouble here depending on a specific order in a struct and I'd really like to get rid of that.

I'm having a struct which is invoking two other structs. However when I was implementing the Drop trait on all three of them I thought that I would need a specific order of going out of scope. However using the std::mem::drop didn't really help in that case since we need to move self and the drop method from the Drop trait provides us with mutable reference only as expected.

So if I have three structs called A, B, C what I want is when A starts to go out of scope to drop C first and then B before we finally drop A. What I did was switching places in the struct which caused a new order of dropping the objects, but as mentioned I'd like to be able to control that somehow and not rely on ordering items in a struct.

That's the stupid way of explaining what I'm trying to achieve: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=dcb33ce71b55ed17d0eb70988cacb651

There's ManuallyDrop, although its drop function is unsafe because it allows you to drop something twice or use it after dropping it, which is obviously not valid.

1 Like

Thanks for the fast answer and heads up about this library. This raises a lot of questions now. What are you referring to "use it after dropping it"?
Is this what you mean: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=614e401ba039293fa6a7b5f3b5ecce3b

I tried another approach as well, unfortunately not much of a difference: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=786447e001049bf0a8157918838e8ad2

Is it possible on some explanation why I'm getting this results?

What result did you expect?

Using a value after you dropped it (such as with inner_func) is undefined behaviour, and this means that the compiler is allowed to compile your program to do literally anything. This includes the output you're seeing (because it includes any behaviour), so don't be surprised to see that output.

That's interesting, I'll read more about that. Thank you once again!

Basically unsafe means that there are certain things you must do to avoid writing an invalid program, but the compiler can't verify them for you.

Yes I kinda figured that out as well. I came across the unsafety section to read more about it and it kinda cleared it out.
I also read a little about the MaybeUninit to use with ManuallyDrop, however I believe that in my specific case this data can't be used after dropped because this is the moment in which my program execution ends, thus I don't need to know if its init or uninit.

However, I'm still having concerns on going with unsafe lib for some reason.

What would you do(or recommend) in my case having considered that after this drop method of impl A we have nothing else to drop, therefore no other code could potentially use anything else? Would you drop it manually or go with the automatic drop?

There's no reason to use MaybeUninit here. It's a more powerful version of ManuallyDrop, but you don't need its extra capabilities. If you don't want to use unsafe, you can either order the fields correctly or use options to drop them in your desired order.

1 Like

Thanks for all suggestions, they were helpful a lot!

Rust drops struct fields in declaration order, so you don't need to do anything other than ordering the fields as desired.

I noticed this behavior earlier, that's why I created the topic to ask for a better solution. Anyways I thought that relying on exact order is not really the best thing for me and since I have nothing else to run after dropping that struct I can use freely the ManuallyDrop lib.