From 02443552c56c0b5d909ba3ddc653e686dff09d9c Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 00:02:47 +0800 Subject: [PATCH 1/3] break out to one scope higher for let-else --- compiler/rustc_mir_build/src/build/block.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6875600129a8f..c52a7b187d519 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -1,6 +1,7 @@ use crate::build::matches::ArmHasGuard; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; +use rustc_middle::middle::region::Scope; use rustc_middle::thir::*; use rustc_middle::{mir::*, ty}; use rustc_span::Span; @@ -34,10 +35,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &stmts, expr, safety_mode, + region_scope, )) }) } else { - this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode) + this.ast_block_stmts( + destination, + block, + span, + &stmts, + expr, + safety_mode, + region_scope, + ) } }) }) @@ -51,6 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { stmts: &[StmtId], expr: Option<&Expr<'tcx>>, safety_mode: BlockSafety, + region_scope: Scope, ) -> BlockAnd<()> { let this = self; @@ -73,6 +84,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; + // This scope information is kept for breaking out of the current block in case + // one let-else pattern matching fails. + let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); @@ -132,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer_span, else_block, visibility_scope, - *remainder_scope, + last_remainder_scope, remainder_span, pattern, ) @@ -178,6 +192,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(source_scope) = visibility_scope { this.source_scope = source_scope; } + last_remainder_scope = *remainder_scope; } } From e26285603ca8b83b9d06e56f74e10e3d410553ff Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:31:53 +0800 Subject: [PATCH 2/3] add test for earlier drop despite extend lifetime --- src/test/ui/let-else/let-else-temporary-lifetime.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/ui/let-else/let-else-temporary-lifetime.rs b/src/test/ui/let-else/let-else-temporary-lifetime.rs index 9c86901b97f03..07fcc16e7bbda 100644 --- a/src/test/ui/let-else/let-else-temporary-lifetime.rs +++ b/src/test/ui/let-else/let-else-temporary-lifetime.rs @@ -74,6 +74,17 @@ fn main() { }; } } + { + fn must_pass() { + let rc = Rc::new(()); + let &None = &Some(Rc::clone(&rc)) else { + Rc::try_unwrap(rc).unwrap(); + return; + }; + unreachable!(); + } + must_pass(); + } { // test let-else drops temps before else block // NOTE: this test has to be the last block in the `main` From 8467a7b33ebdb0c8641e80c9c36bb098a93a7547 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:37:30 +0800 Subject: [PATCH 3/3] provide a clearer explanation of scope breaking --- compiler/rustc_mir_build/src/build/block.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index c52a7b187d519..280b6aad12c0a 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -84,8 +84,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; - // This scope information is kept for breaking out of the current block in case + // This scope information is kept for breaking out of the parent remainder scope in case // one let-else pattern matching fails. + // By doing so, we can be sure that even temporaries that receive extended lifetime + // assignments are dropped, too. let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode);