don't extend non-extended super let initializers' block tail temps

This commit is contained in:
dianne 2025-08-24 22:48:00 -07:00
parent 9fd57df639
commit 0976d6ccac
4 changed files with 40 additions and 13 deletions

View File

@ -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 {

View File

@ -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`.

View File

@ -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]
}

View File

@ -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)),
);
});