Skip to content

Let chain temporaries should drop before else #103248

Closed
@est31

Description

@est31

Due to #103034, now the implementation of let chains has changed, to drop temporaries created by let after the else block terminates. Prior behaviour has mirrored the pre-dropping bheaviour of if as well as bool conditionals in the let chain, while current behaviour mirrors if let. However, post-dropping is suboptimal (#103108). In particular, before #103034 this was compiling:

#![feature(let_chains)]
struct Foo<'a>(&'a mut u32);

impl<'a> Drop for Foo<'a> {
    fn drop(&mut self) {
        *self.0 = 0;
    }
}

fn main() {
    let mut foo = 0;

    // compiles fine on rustc 1.66.0-nightly (a24a020e6 2022-10-18)
    // but fails on rustc 1.66.0-nightly (4b8f43199 2022-10-19)
    if true && let Foo(0) = Foo(&mut foo) {
    } else {
        *&mut foo = 1;
    }

    // compiles fine
    let Foo(0) = Foo(&mut foo) else {
        *&mut foo = 1;
        panic!()
    };
    
    // compile error - unfortunate but might not be fixed
    if let Foo(0) = Foo(&mut foo) {
    } else {
        *&mut foo = 1;
    }
    
    if true && matches!(Foo(&mut foo), Foo(0)) { // Compiles
    } else {
        *&mut foo = 1;
    }
}

But now it doesn't compile any more. I am not adding regression labels because it hasn't affected any of my own code, and it's a nightly feature.

For if let it might not be changed any more due to backwards compatibility concerns, but for let chains there are no such concerns as it is a new feature: code is only broken when developers edit it.

@rustbot label F-let_chains

Metadata

Metadata

Assignees

No one assigned

    Labels

    F-let_chains`#![feature(let_chains)]`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions