diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index f5770b7312d..58521697b38 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -467,8 +467,12 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. - if let_kind == LetKind::Super { - if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { + let extend_initializer = match let_kind { + LetKind::Regular => true, + LetKind::Super + if let Some(scope) = + visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) => + { // This expression was lifetime-extended by a parent let binding. E.g. // // let a = { @@ -481,7 +485,10 @@ fn resolve_local<'tcx>( // Processing of `let a` will have already decided to extend the lifetime of this // `super let` to its own var_scope. We use that scope. visitor.cx.var_parent = scope; - } else { + // Extend temporaries to live in the same scope as the parent `let`'s bindings. + true + } + LetKind::Super => { // This `super let` is not subject to lifetime extension from a parent let binding. E.g. // // identity({ super let x = temp(); &x }).method(); @@ -497,10 +504,17 @@ fn resolve_local<'tcx>( } visitor.cx.var_parent = parent; } + // Don't lifetime-extend child `super let`s or block tail expressions' temporaries in + // the initializer when this `super let` is not itself extended by a parent `let` + // (#145784). Block tail expressions are temporary drop scopes in Editions 2024 and + // later, their temps shouldn't outlive the block in e.g. `f(pin!({ &temp() }))`. + false } - } + }; - if let Some(expr) = init { + if let Some(expr) = init + && extend_initializer + { record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent); if let Some(pat) = pat { diff --git a/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr b/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr index 923c929a68d..506fc6e0965 100644 --- a/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr +++ b/tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr @@ -10,6 +10,18 @@ LL | println!("{:?}", { &temp() }); | = note: consider using a `let` binding to create a longer lived value -error: aborting due to 1 previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/format-args-temporary-scopes.rs:19:29 + | +LL | println!("{:?}{:?}", { &temp() }, ()); + | ---^^^^^--- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/format-args-temporary-scopes.rs b/tests/ui/borrowck/format-args-temporary-scopes.rs index e6223d7c551..2641058accb 100644 --- a/tests/ui/borrowck/format-args-temporary-scopes.rs +++ b/tests/ui/borrowck/format-args-temporary-scopes.rs @@ -17,4 +17,5 @@ fn main() { // arguments when provided with two or more arguments. This caused the result of `temp()` to // outlive the result of the block, making this compile. println!("{:?}{:?}", { &temp() }, ()); + //[e2024]~^ ERROR: temporary value dropped while borrowed [E0716] } diff --git a/tests/ui/drop/super-let-tail-expr-drop-order.rs b/tests/ui/drop/super-let-tail-expr-drop-order.rs index 5aa17bba21f..8ec9296ed4f 100644 --- a/tests/ui/drop/super-let-tail-expr-drop-order.rs +++ b/tests/ui/drop/super-let-tail-expr-drop-order.rs @@ -45,10 +45,10 @@ fn main() { #[cfg(e2024)] ( pin!(( - pin!({ &o.log(3) as *const LogDrop<'_> }), - drop(o.log(1)), + pin!({ &o.log(1) as *const LogDrop<'_> }), + drop(o.log(2)), )), - drop(o.log(2)), + drop(o.log(3)), ); }); @@ -69,12 +69,12 @@ fn main() { ( { super let _ = { - super let _ = { &o.log(4) as *const LogDrop<'_> }; - drop(o.log(1)) + super let _ = { &o.log(1) as *const LogDrop<'_> }; + drop(o.log(2)) }; - drop(o.log(2)) + drop(o.log(3)) }, - drop(o.log(3)), + drop(o.log(4)), ); });