Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

let _ = foo() runs the destructor at the wrong time #16526

Closed
nikomatsakis opened this issue Aug 15, 2014 · 6 comments
Closed

let _ = foo() runs the destructor at the wrong time #16526

nikomatsakis opened this issue Aug 15, 2014 · 6 comments

Comments

@nikomatsakis
Copy link
Contributor

I believe that the semantics of let _ = foo() should be that the destructor for the value returned by foo() runs at the end of the block. The reason for this is a consequence of a couple of other rules that I worked out as part of the temporary lifetime stuff.

In general, let <pat> = <rvalue> where <pat> is not a single identifier is equivalent to:

let _tmp = <rvalue>;
let <path> = _tmp;

In this case, that means that let _ = <rvalue> should be:

let _tmp = <rvalue>;
let _ = tmp;

and since the _ pattern just ignores the thing it matches against, this means that _tmp is unaffected and drops at the end of the block.

However, the following test case suggests that this is not what we do today:

struct Foo;

impl Drop for Foo {
    fn drop(&mut self) {
        println!("Hi2!");
    }
}

fn main() {
     let _ = Foo;
     println!("Hi1!");
}

This should print Hi1 and then Hi2 but in fact it prints the opposite. This is probably a hold-over from the special code that was in trans to special case the treatment of let _ vs other patterns, but I could be wrong.

cc @pcwalton @pnkfelix

@dotdash
Copy link
Contributor

dotdash commented Aug 16, 2014

This seems to originate from febd7ee.

cc @catamorphism

@dotdash
Copy link
Contributor

dotdash commented Aug 16, 2014

@nikomatsakis in #10488 you argued for the current behavior. Have semantics change since then so that the other behavior is preferable? Esp. regarding #10488 (comment) where you say that there's no equivalent and that it is an important capability.

@nikomatsakis
Copy link
Contributor Author

@dotdash I am saying that the current behavior does not reflect what I was arguing for and what I believe we agreed to.

@dotdash
Copy link
Contributor

dotdash commented Aug 18, 2014

If you treat let _ = foo() the same as

let _tmp = foo();
let _ = _tmp;

doesn't that mean that the value is actually bound? How does that fit with the "Don't bind it" semantics described in #10488? In fact code like that was given as an example for the "Bind it" semantics.

What am I missing?

@nikomatsakis
Copy link
Contributor Author

@dotdash at the time I wrote "this will depend on the precise temporary rules". What i'm saying is that the way we wound up defining the temporary rules, as I understand it, is supposed to mean that let _ = foo() lives as long as the entire block. Basically there are two independent things at play:

  1. what is the semantics of let <pat> = <rvalue> (regardless of what the pattern specifically is)
  2. what is the semantics of the _ pattern

@nikomatsakis
Copy link
Contributor Author

Actually, re-reading the code, I think I may be misremembering, and the current behavior is a logical outcome of the rules. That is, the lifetime of the temporary that is introduced is confined to the statement itself, because the pattern does not clearly take a ref.

matthiaskrgr pushed a commit to matthiaskrgr/rust that referenced this issue Feb 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants