Skip to content

Commit 0976d6c

Browse files
committed
don't extend non-extended super let initializers' block tail temps
1 parent 9fd57df commit 0976d6c

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -467,8 +467,12 @@ fn resolve_local<'tcx>(
467467
// A, but the inner rvalues `a()` and `b()` have an extended lifetime
468468
// due to rule C.
469469

470-
if let_kind == LetKind::Super {
471-
if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) {
470+
let extend_initializer = match let_kind {
471+
LetKind::Regular => true,
472+
LetKind::Super
473+
if let Some(scope) =
474+
visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) =>
475+
{
472476
// This expression was lifetime-extended by a parent let binding. E.g.
473477
//
474478
// let a = {
@@ -481,7 +485,10 @@ fn resolve_local<'tcx>(
481485
// Processing of `let a` will have already decided to extend the lifetime of this
482486
// `super let` to its own var_scope. We use that scope.
483487
visitor.cx.var_parent = scope;
484-
} else {
488+
// Extend temporaries to live in the same scope as the parent `let`'s bindings.
489+
true
490+
}
491+
LetKind::Super => {
485492
// This `super let` is not subject to lifetime extension from a parent let binding. E.g.
486493
//
487494
// identity({ super let x = temp(); &x }).method();
@@ -497,10 +504,17 @@ fn resolve_local<'tcx>(
497504
}
498505
visitor.cx.var_parent = parent;
499506
}
507+
// Don't lifetime-extend child `super let`s or block tail expressions' temporaries in
508+
// the initializer when this `super let` is not itself extended by a parent `let`
509+
// (#145784). Block tail expressions are temporary drop scopes in Editions 2024 and
510+
// later, their temps shouldn't outlive the block in e.g. `f(pin!({ &temp() }))`.
511+
false
500512
}
501-
}
513+
};
502514

503-
if let Some(expr) = init {
515+
if let Some(expr) = init
516+
&& extend_initializer
517+
{
504518
record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent);
505519

506520
if let Some(pat) = pat {

tests/ui/borrowck/format-args-temporary-scopes.e2024.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ LL | println!("{:?}", { &temp() });
1010
|
1111
= note: consider using a `let` binding to create a longer lived value
1212

13-
error: aborting due to 1 previous error
13+
error[E0716]: temporary value dropped while borrowed
14+
--> $DIR/format-args-temporary-scopes.rs:19:29
15+
|
16+
LL | println!("{:?}{:?}", { &temp() }, ());
17+
| ---^^^^^---
18+
| | | |
19+
| | | temporary value is freed at the end of this statement
20+
| | creates a temporary value which is freed while still in use
21+
| borrow later used here
22+
|
23+
= note: consider using a `let` binding to create a longer lived value
24+
25+
error: aborting due to 2 previous errors
1426

1527
For more information about this error, try `rustc --explain E0716`.

tests/ui/borrowck/format-args-temporary-scopes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ fn main() {
1717
// arguments when provided with two or more arguments. This caused the result of `temp()` to
1818
// outlive the result of the block, making this compile.
1919
println!("{:?}{:?}", { &temp() }, ());
20+
//[e2024]~^ ERROR: temporary value dropped while borrowed [E0716]
2021
}

tests/ui/drop/super-let-tail-expr-drop-order.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ fn main() {
4545
#[cfg(e2024)]
4646
(
4747
pin!((
48-
pin!({ &o.log(3) as *const LogDrop<'_> }),
49-
drop(o.log(1)),
48+
pin!({ &o.log(1) as *const LogDrop<'_> }),
49+
drop(o.log(2)),
5050
)),
51-
drop(o.log(2)),
51+
drop(o.log(3)),
5252
);
5353
});
5454

@@ -69,12 +69,12 @@ fn main() {
6969
(
7070
{
7171
super let _ = {
72-
super let _ = { &o.log(4) as *const LogDrop<'_> };
73-
drop(o.log(1))
72+
super let _ = { &o.log(1) as *const LogDrop<'_> };
73+
drop(o.log(2))
7474
};
75-
drop(o.log(2))
75+
drop(o.log(3))
7676
},
77-
drop(o.log(3)),
77+
drop(o.log(4)),
7878
);
7979
});
8080

0 commit comments

Comments
 (0)