1
Fork 0

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.
This commit is contained in:
est31 2022-12-04 00:21:19 +01:00
parent a2076dc0a6
commit a59a2d3f6a
2 changed files with 32 additions and 13 deletions

View 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 {

View file

@ -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();