Skip to content

Commit

Permalink
Merge pull request #1837 from dtolnay/rangebailout
Browse files Browse the repository at this point in the history
Choose range bailouts based on precedence
  • Loading branch information
dtolnay authored Jan 10, 2025
2 parents cd3fa5a + aaca8b8 commit 83195c0
Showing 1 changed file with 52 additions and 47 deletions.
99 changes: 52 additions & 47 deletions src/fixup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl FixupContext {
fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
#[cfg(feature = "full")]
if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range {
if let Scan::Bailout = scan_right(expr, self, false, 0, 0) {
if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) {
if scan_left(expr, self) {
return Precedence::Unambiguous;
}
Expand Down Expand Up @@ -354,13 +354,8 @@ impl FixupContext {
if default_prec < Precedence::Prefix
&& (!self.next_operator_can_begin_expr || self.next_operator == Precedence::Range)
{
if let Scan::Bailout | Scan::Fail = scan_right(
expr,
self,
self.previous_operator == Precedence::Range,
1,
0,
) {
if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0)
{
if scan_left(expr, self) {
return Precedence::Prefix;
}
Expand Down Expand Up @@ -467,6 +462,13 @@ impl Clone for Scan {
}
}

#[cfg(feature = "full")]
impl PartialEq for Scan {
fn eq(&self, other: &Self) -> bool {
*self as u8 == *other as u8
}
}

#[cfg(feature = "full")]
fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
match expr {
Expand All @@ -485,12 +487,21 @@ fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
fn scan_right(
expr: &Expr,
fixup: FixupContext,
range: bool,
precedence: Precedence,
fail_offset: u8,
bailout_offset: u8,
) -> Scan {
let consume_by_precedence = if match precedence {
Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator,
_ => precedence < fixup.next_operator,
} || fixup.next_operator == Precedence::MIN
{
Scan::Consume
} else {
Scan::Bailout
};
if fixup.parenthesize(expr) {
return Scan::Consume;
return consume_by_precedence;
}
match expr {
Expr::Assign(e) => {
Expand All @@ -504,7 +515,7 @@ fn scan_right(
let scan = scan_right(
&e.right,
right_fixup,
false,
Precedence::Assign,
match fixup.next_operator {
Precedence::Unambiguous => fail_offset,
_ => 1,
Expand All @@ -521,7 +532,10 @@ fn scan_right(
}
Expr::Binary(e) => {
if match fixup.next_operator {
Precedence::Unambiguous => fail_offset >= 2,
Precedence::Unambiguous => {
fail_offset >= 2
&& (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
}
_ => bailout_offset >= 1,
} {
return Scan::Consume;
Expand All @@ -531,29 +545,22 @@ fn scan_right(
let scan = scan_right(
&e.right,
right_fixup,
range && binop_prec != Precedence::Assign,
binop_prec,
match fixup.next_operator {
Precedence::Unambiguous => fail_offset,
_ => 1,
},
match (binop_prec, fixup.next_operator) {
(Precedence::Assign, _) => 1,
(_, Precedence::Assign | Precedence::Range) if range => 0,
_ => 1,
},
consume_by_precedence as u8 - Scan::Bailout as u8,
);
if match (scan, fixup.next_operator) {
(Scan::Fail, _) => false,
(Scan::Bailout, _) if binop_prec == Precedence::Assign => true,
(Scan::Bailout, Precedence::Assign | Precedence::Range) => !range,
(Scan::Bailout | Scan::Consume, _) => true,
} {
return Scan::Consume;
match scan {
Scan::Fail => {}
Scan::Bailout => return consume_by_precedence,
Scan::Consume => return Scan::Consume,
}
let right_needs_group = binop_prec != Precedence::Assign
&& right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
if right_needs_group {
Scan::Consume
consume_by_precedence
} else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
Scan::Fail
} else {
Expand All @@ -564,7 +571,10 @@ fn scan_right(
| Expr::Reference(ExprReference { expr, .. })
| Expr::Unary(ExprUnary { expr, .. }) => {
if match fixup.next_operator {
Precedence::Unambiguous => fail_offset >= 2,
Precedence::Unambiguous => {
fail_offset >= 2
&& (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
}
_ => bailout_offset >= 1,
} {
return Scan::Consume;
Expand All @@ -573,25 +583,20 @@ fn scan_right(
let scan = scan_right(
expr,
right_fixup,
range,
precedence,
match fixup.next_operator {
Precedence::Unambiguous => fail_offset,
_ => 1,
},
match fixup.next_operator {
Precedence::Assign | Precedence::Range if range => 0,
_ => 1,
},
consume_by_precedence as u8 - Scan::Bailout as u8,
);
if match (scan, fixup.next_operator) {
(Scan::Fail, _) => false,
(Scan::Bailout, Precedence::Assign | Precedence::Range) => !range,
(Scan::Bailout | Scan::Consume, _) => true,
} {
return Scan::Consume;
match scan {
Scan::Fail => {}
Scan::Bailout => return consume_by_precedence,
Scan::Consume => return Scan::Consume,
}
if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix {
Scan::Consume
consume_by_precedence
} else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
Scan::Fail
} else {
Expand All @@ -608,7 +613,7 @@ fn scan_right(
let scan = scan_right(
end,
right_fixup,
true,
Precedence::Range,
fail_offset,
match fixup.next_operator {
Precedence::Assign | Precedence::Range => 0,
Expand Down Expand Up @@ -639,13 +644,13 @@ fn scan_right(
return Scan::Consume;
}
let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump);
match scan_right(value, right_fixup, false, 1, 1) {
match scan_right(value, right_fixup, Precedence::Jump, 1, 1) {
Scan::Fail => Scan::Bailout,
Scan::Bailout | Scan::Consume => Scan::Consume,
}
}
None => match fixup.next_operator {
Precedence::Assign if range => Scan::Fail,
Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
_ => Scan::Consume,
},
},
Expand All @@ -656,13 +661,13 @@ fn scan_right(
}
let right_fixup =
fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump);
match scan_right(e, right_fixup, false, 1, 1) {
match scan_right(e, right_fixup, Precedence::Jump, 1, 1) {
Scan::Fail => Scan::Bailout,
Scan::Bailout | Scan::Consume => Scan::Consume,
}
}
None => match fixup.next_operator {
Precedence::Assign if range => Scan::Fail,
Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
_ => Scan::Consume,
},
},
Expand All @@ -675,7 +680,7 @@ fn scan_right(
}
let right_fixup =
fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump);
match scan_right(&e.body, right_fixup, false, 1, 1) {
match scan_right(&e.body, right_fixup, Precedence::Jump, 1, 1) {
Scan::Fail => Scan::Bailout,
Scan::Bailout | Scan::Consume => Scan::Consume,
}
Expand Down Expand Up @@ -713,8 +718,8 @@ fn scan_right(
| Expr::Unsafe(_)
| Expr::Verbatim(_)
| Expr::While(_) => match fixup.next_operator {
Precedence::Assign | Precedence::Range if range => Scan::Fail,
_ => Scan::Consume,
Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
_ => consume_by_precedence,
},
}
}

0 comments on commit 83195c0

Please sign in to comment.