]> git.lizzy.rs Git - rust.git/commitdiff
Also avoid creating a terminating scope in mixed chains
authorest31 <MTest31@outlook.com>
Sat, 3 Dec 2022 23:21:19 +0000 (00:21 +0100)
committerest31 <MTest31@outlook.com>
Sun, 4 Dec 2022 03:09:40 +0000 (04:09 +0100)
This avoids creation of a terminating scope in
chains that contain both && and ||, because
also there we know that a terminating scope is
not neccessary: all the chain members are already
in such terminating scopes.

Also add a mixed && / || test.

compiler/rustc_hir_analysis/src/check/region.rs
src/test/ui/drop/drop_order.rs

index 6221b1b9937984ed09e1f682b90129a1b5efbb79..b315ebad4686c37d4bac86575a991a744e2c27f0 100644 (file)
@@ -241,12 +241,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
             // scopes, meaning that temporaries cannot outlive them.
             // This ensures fixed size stacks.
             hir::ExprKind::Binary(
-                source_map::Spanned { node: outer @ hir::BinOpKind::And, .. },
-                ref l,
-                ref r,
-            )
-            | hir::ExprKind::Binary(
-                source_map::Spanned { node: outer @ hir::BinOpKind::Or, .. },
+                source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
                 ref l,
                 ref r,
             ) => {
@@ -268,14 +263,19 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
                 // into a terminating scope if it is not a binop.
 
                 let terminate_lhs = match l.kind {
+                    // let expressions can create temporaries that live on
                     hir::ExprKind::Let(_) => false,
-                    hir::ExprKind::Binary(source_map::Spanned { node, .. }, ..)
-                        if node == outer =>
-                    {
-                        false
-                    }
-                    // If the LHS is not another binop itself of the same kind as
-                    // the current binop, mark it as terminating.
+                    // binops already drop their temporaries, so there is no
+                    // need to put them into a terminating scope.
+                    // This is purely an optimization to reduce the number of
+                    // terminating scopes.
+                    hir::ExprKind::Binary(
+                        source_map::Spanned {
+                            node: hir::BinOpKind::And | hir::BinOpKind::Or, ..
+                        },
+                        ..,
+                    ) => false,
+                    // otherwise: mark it as terminating
                     _ => true,
                 };
                 if terminate_lhs {
index 4e5c1205bb9c305137f009d3b8b5b02709123445..5ce1fd54a9e62027a7f53517d8fb03fb74c14207 100644 (file)
@@ -172,6 +172,20 @@ fn or_chain(&self) {
         }
     }
 
+    fn mixed_and_or_chain(&self) {
+        // issue-103107
+        if self.option_loud_drop(1).is_none() // 1
+            || self.option_loud_drop(2).is_none() // 2
+            || self.option_loud_drop(3).is_some() // 3
+            && self.option_loud_drop(4).is_some() // 4
+            && self.option_loud_drop(5).is_none() // 5
+            || self.option_loud_drop(6).is_none() // 6
+            || self.option_loud_drop(7).is_some() // 7
+        {
+            self.print(8); // 8
+        }
+    }
+
     fn let_chain(&self) {
         // take the "then" branch
         if self.option_loud_drop(1).is_some() // 1
@@ -251,6 +265,11 @@ fn main() {
     collector.or_chain();
     collector.assert_sorted();
 
+    println!("-- mixed and/or chain --");
+    let collector = DropOrderCollector::default();
+    collector.mixed_and_or_chain();
+    collector.assert_sorted();
+
     println!("-- if let --");
     let collector = DropOrderCollector::default();
     collector.if_let();