4

I have the following code:

#[derive(Debug)]
pub enum List<'a> {
    Nil,
    Cons(i32, &'a List<'a>)
}

{
    let x = Cons(1, &Cons(2, &Nil));
    println!("{:?}", x);
}

It works fine. I don't understand why this code doesn't report any error, isn't the Cons(2, &Nil) dropped before constructing Cons(1, _) ?

Moreover, after I added an empty impl Drop for List, the above code doesn't work any more:

impl<'a> Drop for List<'a> {
    fn drop(&mut self) {

    }
}

It reports errors that borrowed value does not live long enough for Cons(2, _) and Nil.

Why is there such difference between before and after adding impl Drop ?

1 Answer 1

3

Isn't the Cons(2, &Nil) dropped before constructing Cons(1, _)?

If you bind a reference to a temporary, Rust extends the lifetime of the temporary as needed for the binding; see this answer for details.

Why is there such difference between before and after adding impl Drop?

See this comment. The extended lifetime of the temporary matches the lifetime of x in your example. When a struct containing references has no Drop implementation,

it’s permissible for reference and referent to have identical lifetimes: the reference can’t be used unsafely. Introducing a Drop impl to the situation requires the referent to strictly outlive the reference, to ensure there is a clear order in which to run drop methods.

Sign up to request clarification or add additional context in comments.

1 Comment

The answer to the first question is incorrect. In the given context there is no lifetime extension. The reason this works anyway is constant promotionNil gets promoted to a static constant, so the reference has static lifetime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.