Skip to content

Let-else source expression move behavior #89688

Closed
@phaylon

Description

@phaylon

The move behavior on non-matching of expressions by feature(let_else) seems currently inconsistent with behavior of, for example, if let.

An if-let construct does not move from the matched expression if the pattern doesn't match:

fn example_if_let(value: Option<String>) {
    if let Some(inner) = value {
        println!("inner: {}", inner);
    } else {
        println!("other: {:?}", value);
    }
}

fn main() {
    example_if_let(Some("foo".into()));
    example_if_let(None);
}

compiles and prints

inner: foo
other: None

However, let-else seems to unconditionally move from the matched expression:

#![feature(let_else)]

fn example_let_else(value: Option<String>) {
    let Some(inner) = value else {
        println!("other: {:?}", value);
        return;
    };
    println!("inner: {}", inner);
}

fn main() {
    example_let_else(Some("foo".into()));
    example_let_else(None);
}

fails to compile:

error[E0382]: borrow of moved value: `value`
 --> src/main.rs:5:33
  |
3 | fn example_let_else(value: Option<String>) {
  |                     ----- move occurs because `value` has type `Option<String>`, which does not implement the `Copy` trait
4 |     let Some(inner) = value else {
  |                       ----- value moved here
5 |         println!("other: {:?}", value);
  |                                 ^^^^^ value borrowed here after move

I'm wondering if this is intentional, as it would seem to make it impossible to use the original unmatched value in an panic message (or diverge otherwise with the value or any value based on it).

rustc 1.57.0-nightly (485ced56b 2021-10-07)
binary: rustc
commit-hash: 485ced56b8753ec86936903f2a8c95e9be8996a1
commit-date: 2021-10-07
host: x86_64-unknown-linux-gnu
release: 1.57.0-nightly
LLVM version: 13.0.0

Proposed Label: F-let-else

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-let_elseIssues related to let-else statements (RFC 3137)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions