Skip to content

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

Description

@nikomatsakis

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions