Skip to content

Commit 3d5e1d7

Browse files
authored
Rollup merge of rust-lang#99954 - dingxiangfei2009:break-out-let-else-higher-up, r=oli-obk
let-else: break out to one scope higher for let-else ``@est31`` This PR follows up with rust-lang#99518 which is to break out to the last remainder scope. It breaks to the out-most `region_scope` of the block if the first statement is a `let-else`.
2 parents ec74ca0 + 8467a7b commit 3d5e1d7

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

compiler/rustc_mir_build/src/build/block.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::build::matches::ArmHasGuard;
22
use crate::build::ForGuard::OutsideGuard;
33
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
4+
use rustc_middle::middle::region::Scope;
45
use rustc_middle::thir::*;
56
use rustc_middle::{mir::*, ty};
67
use rustc_span::Span;
@@ -34,10 +35,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3435
&stmts,
3536
expr,
3637
safety_mode,
38+
region_scope,
3739
))
3840
})
3941
} else {
40-
this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode)
42+
this.ast_block_stmts(
43+
destination,
44+
block,
45+
span,
46+
&stmts,
47+
expr,
48+
safety_mode,
49+
region_scope,
50+
)
4151
}
4252
})
4353
})
@@ -51,6 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5161
stmts: &[StmtId],
5262
expr: Option<&Expr<'tcx>>,
5363
safety_mode: BlockSafety,
64+
region_scope: Scope,
5465
) -> BlockAnd<()> {
5566
let this = self;
5667

@@ -73,6 +84,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7384
let mut let_scope_stack = Vec::with_capacity(8);
7485
let outer_source_scope = this.source_scope;
7586
let outer_in_scope_unsafe = this.in_scope_unsafe;
87+
// This scope information is kept for breaking out of the parent remainder scope in case
88+
// one let-else pattern matching fails.
89+
// By doing so, we can be sure that even temporaries that receive extended lifetime
90+
// assignments are dropped, too.
91+
let mut last_remainder_scope = region_scope;
7692
this.update_source_scope_for_safety_mode(span, safety_mode);
7793

7894
let source_info = this.source_info(span);
@@ -132,7 +148,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
132148
initializer_span,
133149
else_block,
134150
visibility_scope,
135-
*remainder_scope,
151+
last_remainder_scope,
136152
remainder_span,
137153
pattern,
138154
)
@@ -178,6 +194,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
178194
if let Some(source_scope) = visibility_scope {
179195
this.source_scope = source_scope;
180196
}
197+
last_remainder_scope = *remainder_scope;
181198
}
182199
}
183200

src/test/ui/let-else/let-else-temporary-lifetime.rs

+11
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ fn main() {
7474
};
7575
}
7676
}
77+
{
78+
fn must_pass() {
79+
let rc = Rc::new(());
80+
let &None = &Some(Rc::clone(&rc)) else {
81+
Rc::try_unwrap(rc).unwrap();
82+
return;
83+
};
84+
unreachable!();
85+
}
86+
must_pass();
87+
}
7788
{
7889
// test let-else drops temps before else block
7990
// NOTE: this test has to be the last block in the `main`

0 commit comments

Comments
 (0)