Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why Drop trait is only executed at the end of the scope, instead of after the last use?

This is a question from rust onomicon # lifetime

The first example can compile, as x is a reference and the compiler can infer its lifetime as minimal as the last use here :println!(), so x is dropped after this line.

let mut data = vec![1, 2, 3];
let x = &data[0];
println!("{}", x);
// This is OK, x is no longer needed
data.push(4);

But the case is different when x is a struct implemented Drop trait.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#[derive(Debug)]
struct X<'a>(&'a i32);

impl Drop for X<'_> {
    fn drop(&mut self) {}
}

let mut data = vec![1, 2, 3];
let x = X(&data[0]);
println!("{:?}", x);
data.push(4);
// Here, the destructor is run and therefore this'll fail to compile.

The onomicon says in this case, drop() is only executed at the very end of a scope, so x keeps valid until the last line.

But why the compiler cannot minimize the lifetime of x to the last use? And is applying drop() just after the last use has some nontrivial side effects when x is implemented Drop trait?

>Solution :

The primary reason is that it was once defined to be like that, and now changing it isn’t possible any more because it wouldn’t be backwards-compatible and might break stuff.

Your code is easily fixable by introducing a nested scope, though, which is (to my understanding) best practices in those situations:

#[derive(Debug)]
struct X<'a>(&'a i32);

impl Drop for X<'_> {
    fn drop(&mut self) {}
}

fn main() {
    let mut data = vec![1, 2, 3];
    {
        let x = X(&data[0]);
        println!("{:?}", x);
    }
    data.push(4);
}
X(1)

Alternatively, you could drop it manually:

#[derive(Debug)]
struct X<'a>(&'a i32);

impl Drop for X<'_> {
    fn drop(&mut self) {}
}

fn main() {
    let mut data = vec![1, 2, 3];

    let x = X(&data[0]);
    println!("{:?}", x);
    drop(x);

    data.push(4);
}
X(1)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading