Skip to content

let_else returns in surprising borrowck errors with impl trait #93951

Closed
@lcnr

Description

@lcnr
#![feature(let_else)]
use std::fmt::Debug;

fn foo<'a>(x: &'a str) -> Result<impl Debug + 'a, ()> {
    Ok(x)
}

fn fail() {
    let x = String::from("Hey");

    let Ok(s) = foo(&x) else { return };
}

fn ok() {
    let x = String::from("Hey");

    let s = if let Ok(s) = foo(&x) { s } else { return };
}

results in

error[E0597]: `x` does not live long enough
  --> src/main.rs:11:21
   |
11 |     let Ok(s) = foo(&x) else { return };
   |                 ----^^-
   |                 |   |
   |                 |   borrowed value does not live long enough
   |                 a temporary with access to the borrow is created here ...
12 | }
   | -
   | |
   | `x` dropped here while still borrowed
   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Result<impl Debug, ()>`
   |
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
   |
11 |     let Ok(s) = foo(&x) else { return };;
   |                                        +

I am not sure if this issue exists only in combination with impl Trait of if it can be triggered in some other ways as well, haven't managed to get this bug some other way.

cc #93628 @est31 do you know whether this behavior is known already?

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-let_elseIssues related to let-else statements (RFC 3137)T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions