about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2024-06-17 20:51:35 +0200
committerNadrieril <nadrieril+git@gmail.com>2024-06-22 19:05:50 +0200
commitff49c3769b0ec5b1abc628e55c7547e765086e6a (patch)
treec6651ca9f64e8eabc59ee2ce248538e8e47acf95
parent7b150a161e7c90cc067c1a709a63785b5dc2a5e9 (diff)
downloadrust-ff49c3769b0ec5b1abc628e55c7547e765086e6a.tar.gz
rust-ff49c3769b0ec5b1abc628e55c7547e765086e6a.zip
Reuse `lower_let_expr` for `let .. else` lowering
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs63
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs73
2 files changed, 49 insertions, 87 deletions
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index c1d645aa42c..476969a1bd7 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -189,38 +189,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     let initializer_span = this.thir[*initializer].span;
                     let scope = (*init_scope, source_info);
-                    let failure = unpack!(
-                        block = this.in_scope(scope, *lint_level, |this| {
-                            this.declare_bindings(
-                                visibility_scope,
-                                remainder_span,
-                                pattern,
-                                None,
-                                Some((Some(&destination), initializer_span)),
-                            );
-                            this.visit_primary_bindings(
-                                pattern,
-                                UserTypeProjections::none(),
-                                &mut |this, _, _, node, span, _, _| {
-                                    this.storage_live_binding(
-                                        block,
-                                        node,
-                                        span,
-                                        OutsideGuard,
-                                        true,
-                                    );
-                                },
-                            );
-                            this.ast_let_else(
-                                block,
-                                *initializer,
-                                initializer_span,
-                                *else_block,
-                                &last_remainder_scope,
-                                pattern,
-                            )
-                        })
-                    );
+                    let failure_and_block = this.in_scope(scope, *lint_level, |this| {
+                        this.declare_bindings(
+                            visibility_scope,
+                            remainder_span,
+                            pattern,
+                            None,
+                            Some((Some(&destination), initializer_span)),
+                        );
+                        this.visit_primary_bindings(
+                            pattern,
+                            UserTypeProjections::none(),
+                            &mut |this, _, _, node, span, _, _| {
+                                this.storage_live_binding(block, node, span, OutsideGuard, true);
+                            },
+                        );
+                        let else_block_span = this.thir[*else_block].span;
+                        let (matching, failure) =
+                            this.in_if_then_scope(last_remainder_scope, else_block_span, |this| {
+                                this.lower_let_expr(
+                                    block,
+                                    *initializer,
+                                    pattern,
+                                    None,
+                                    initializer_span,
+                                    false,
+                                    true,
+                                )
+                            });
+                        matching.and(failure)
+                    });
+                    let failure = unpack!(block = failure_and_block);
                     this.cfg.goto(failure, source_info, failure_entry);
 
                     if let Some(source_scope) = visibility_scope {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 3eacd598f66..f9333a165ce 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -147,6 +147,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 Some(args.variable_source_info.scope),
                 args.variable_source_info.span,
                 args.declare_let_bindings,
+                false,
             ),
             _ => {
                 let mut block = block;
@@ -1981,48 +1982,50 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// If the bindings have already been declared, set `declare_bindings` to
-    /// `false` to avoid duplicated bindings declaration. Used for if-let guards.
+    /// `false` to avoid duplicated bindings declaration; used for if-let guards.
     pub(crate) fn lower_let_expr(
         &mut self,
         mut block: BasicBlock,
         expr_id: ExprId,
         pat: &Pat<'tcx>,
         source_scope: Option<SourceScope>,
-        span: Span,
+        scope_span: Span,
         declare_bindings: bool,
+        storages_alive: bool,
     ) -> BlockAnd<()> {
         let expr_span = self.thir[expr_id].span;
-        let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
-        let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self);
+        let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
+        let mut candidate = Candidate::new(scrutinee.clone(), pat, false, self);
         let otherwise_block = self.lower_match_tree(
             block,
+            expr_span,
+            &scrutinee,
             pat.span,
-            &expr_place_builder,
-            pat.span,
-            &mut [&mut guard_candidate],
+            &mut [&mut candidate],
             true,
         );
-        let expr_place = expr_place_builder.try_to_place(self);
-        let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
+
         self.break_for_else(otherwise_block, self.source_info(expr_span));
 
         if declare_bindings {
-            self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
+            let expr_place = scrutinee.try_to_place(self);
+            let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
+            self.declare_bindings(source_scope, pat.span.to(scope_span), pat, None, opt_expr_place);
         }
 
-        let post_guard_block = self.bind_pattern(
+        let success = self.bind_pattern(
             self.source_info(pat.span),
-            guard_candidate,
+            candidate,
             &[],
             expr_span,
             None,
-            false,
+            storages_alive,
         );
 
         // If branch coverage is enabled, record this branch.
-        self.visit_coverage_conditional_let(pat, post_guard_block, otherwise_block);
+        self.visit_coverage_conditional_let(pat, success, otherwise_block);
 
-        post_guard_block.unit()
+        success.unit()
     }
 
     /// Initializes each of the bindings from the candidate by
@@ -2469,44 +2472,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!(?locals);
         self.var_indices.insert(var_id, locals);
     }
-
-    pub(crate) fn ast_let_else(
-        &mut self,
-        mut block: BasicBlock,
-        init_id: ExprId,
-        initializer_span: Span,
-        else_block: BlockId,
-        let_else_scope: &region::Scope,
-        pattern: &Pat<'tcx>,
-    ) -> BlockAnd<BasicBlock> {
-        let else_block_span = self.thir[else_block].span;
-        let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| {
-            let scrutinee = unpack!(block = this.lower_scrutinee(block, init_id, initializer_span));
-            let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
-            let failure_block = this.lower_match_tree(
-                block,
-                initializer_span,
-                &scrutinee,
-                pattern.span,
-                &mut [&mut candidate],
-                true,
-            );
-            // This block is for the matching case
-            let matching = this.bind_pattern(
-                this.source_info(pattern.span),
-                candidate,
-                &[],
-                initializer_span,
-                None,
-                true,
-            );
-
-            // If branch coverage is enabled, record this branch.
-            this.visit_coverage_conditional_let(pattern, matching, failure_block);
-
-            this.break_for_else(failure_block, this.source_info(initializer_span));
-            matching.unit()
-        });
-        matching.and(failure)
-    }
 }