From a59a2d3f6a80001b0610f03cfc7a6452b63f8935 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 4 Dec 2022 00:21:19 +0100 Subject: [PATCH] Also avoid creating a terminating scope in mixed chains 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. --- .../rustc_hir_analysis/src/check/region.rs | 26 +++++++++---------- src/test/ui/drop/drop_order.rs | 19 ++++++++++++++ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 6221b1b993798..b315ebad4686c 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -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 { diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs index 4e5c1205bb9c3..5ce1fd54a9e62 100644 --- a/src/test/ui/drop/drop_order.rs +++ b/src/test/ui/drop/drop_order.rs @@ -172,6 +172,20 @@ impl DropOrderCollector { } } + 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();