Skip to content

Commit 83195c0

Browse files
authored
Merge pull request #1837 from dtolnay/rangebailout
Choose range bailouts based on precedence
2 parents cd3fa5a + aaca8b8 commit 83195c0

File tree

1 file changed

+52
-47
lines changed

1 file changed

+52
-47
lines changed

src/fixup.rs

+52-47
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl FixupContext {
285285
fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
286286
#[cfg(feature = "full")]
287287
if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range {
288-
if let Scan::Bailout = scan_right(expr, self, false, 0, 0) {
288+
if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) {
289289
if scan_left(expr, self) {
290290
return Precedence::Unambiguous;
291291
}
@@ -354,13 +354,8 @@ impl FixupContext {
354354
if default_prec < Precedence::Prefix
355355
&& (!self.next_operator_can_begin_expr || self.next_operator == Precedence::Range)
356356
{
357-
if let Scan::Bailout | Scan::Fail = scan_right(
358-
expr,
359-
self,
360-
self.previous_operator == Precedence::Range,
361-
1,
362-
0,
363-
) {
357+
if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0)
358+
{
364359
if scan_left(expr, self) {
365360
return Precedence::Prefix;
366361
}
@@ -467,6 +462,13 @@ impl Clone for Scan {
467462
}
468463
}
469464

465+
#[cfg(feature = "full")]
466+
impl PartialEq for Scan {
467+
fn eq(&self, other: &Self) -> bool {
468+
*self as u8 == *other as u8
469+
}
470+
}
471+
470472
#[cfg(feature = "full")]
471473
fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
472474
match expr {
@@ -485,12 +487,21 @@ fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
485487
fn scan_right(
486488
expr: &Expr,
487489
fixup: FixupContext,
488-
range: bool,
490+
precedence: Precedence,
489491
fail_offset: u8,
490492
bailout_offset: u8,
491493
) -> Scan {
494+
let consume_by_precedence = if match precedence {
495+
Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator,
496+
_ => precedence < fixup.next_operator,
497+
} || fixup.next_operator == Precedence::MIN
498+
{
499+
Scan::Consume
500+
} else {
501+
Scan::Bailout
502+
};
492503
if fixup.parenthesize(expr) {
493-
return Scan::Consume;
504+
return consume_by_precedence;
494505
}
495506
match expr {
496507
Expr::Assign(e) => {
@@ -504,7 +515,7 @@ fn scan_right(
504515
let scan = scan_right(
505516
&e.right,
506517
right_fixup,
507-
false,
518+
Precedence::Assign,
508519
match fixup.next_operator {
509520
Precedence::Unambiguous => fail_offset,
510521
_ => 1,
@@ -521,7 +532,10 @@ fn scan_right(
521532
}
522533
Expr::Binary(e) => {
523534
if match fixup.next_operator {
524-
Precedence::Unambiguous => fail_offset >= 2,
535+
Precedence::Unambiguous => {
536+
fail_offset >= 2
537+
&& (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
538+
}
525539
_ => bailout_offset >= 1,
526540
} {
527541
return Scan::Consume;
@@ -531,29 +545,22 @@ fn scan_right(
531545
let scan = scan_right(
532546
&e.right,
533547
right_fixup,
534-
range && binop_prec != Precedence::Assign,
548+
binop_prec,
535549
match fixup.next_operator {
536550
Precedence::Unambiguous => fail_offset,
537551
_ => 1,
538552
},
539-
match (binop_prec, fixup.next_operator) {
540-
(Precedence::Assign, _) => 1,
541-
(_, Precedence::Assign | Precedence::Range) if range => 0,
542-
_ => 1,
543-
},
553+
consume_by_precedence as u8 - Scan::Bailout as u8,
544554
);
545-
if match (scan, fixup.next_operator) {
546-
(Scan::Fail, _) => false,
547-
(Scan::Bailout, _) if binop_prec == Precedence::Assign => true,
548-
(Scan::Bailout, Precedence::Assign | Precedence::Range) => !range,
549-
(Scan::Bailout | Scan::Consume, _) => true,
550-
} {
551-
return Scan::Consume;
555+
match scan {
556+
Scan::Fail => {}
557+
Scan::Bailout => return consume_by_precedence,
558+
Scan::Consume => return Scan::Consume,
552559
}
553560
let right_needs_group = binop_prec != Precedence::Assign
554561
&& right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
555562
if right_needs_group {
556-
Scan::Consume
563+
consume_by_precedence
557564
} else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
558565
Scan::Fail
559566
} else {
@@ -564,7 +571,10 @@ fn scan_right(
564571
| Expr::Reference(ExprReference { expr, .. })
565572
| Expr::Unary(ExprUnary { expr, .. }) => {
566573
if match fixup.next_operator {
567-
Precedence::Unambiguous => fail_offset >= 2,
574+
Precedence::Unambiguous => {
575+
fail_offset >= 2
576+
&& (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
577+
}
568578
_ => bailout_offset >= 1,
569579
} {
570580
return Scan::Consume;
@@ -573,25 +583,20 @@ fn scan_right(
573583
let scan = scan_right(
574584
expr,
575585
right_fixup,
576-
range,
586+
precedence,
577587
match fixup.next_operator {
578588
Precedence::Unambiguous => fail_offset,
579589
_ => 1,
580590
},
581-
match fixup.next_operator {
582-
Precedence::Assign | Precedence::Range if range => 0,
583-
_ => 1,
584-
},
591+
consume_by_precedence as u8 - Scan::Bailout as u8,
585592
);
586-
if match (scan, fixup.next_operator) {
587-
(Scan::Fail, _) => false,
588-
(Scan::Bailout, Precedence::Assign | Precedence::Range) => !range,
589-
(Scan::Bailout | Scan::Consume, _) => true,
590-
} {
591-
return Scan::Consume;
593+
match scan {
594+
Scan::Fail => {}
595+
Scan::Bailout => return consume_by_precedence,
596+
Scan::Consume => return Scan::Consume,
592597
}
593598
if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix {
594-
Scan::Consume
599+
consume_by_precedence
595600
} else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
596601
Scan::Fail
597602
} else {
@@ -608,7 +613,7 @@ fn scan_right(
608613
let scan = scan_right(
609614
end,
610615
right_fixup,
611-
true,
616+
Precedence::Range,
612617
fail_offset,
613618
match fixup.next_operator {
614619
Precedence::Assign | Precedence::Range => 0,
@@ -639,13 +644,13 @@ fn scan_right(
639644
return Scan::Consume;
640645
}
641646
let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump);
642-
match scan_right(value, right_fixup, false, 1, 1) {
647+
match scan_right(value, right_fixup, Precedence::Jump, 1, 1) {
643648
Scan::Fail => Scan::Bailout,
644649
Scan::Bailout | Scan::Consume => Scan::Consume,
645650
}
646651
}
647652
None => match fixup.next_operator {
648-
Precedence::Assign if range => Scan::Fail,
653+
Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
649654
_ => Scan::Consume,
650655
},
651656
},
@@ -656,13 +661,13 @@ fn scan_right(
656661
}
657662
let right_fixup =
658663
fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump);
659-
match scan_right(e, right_fixup, false, 1, 1) {
664+
match scan_right(e, right_fixup, Precedence::Jump, 1, 1) {
660665
Scan::Fail => Scan::Bailout,
661666
Scan::Bailout | Scan::Consume => Scan::Consume,
662667
}
663668
}
664669
None => match fixup.next_operator {
665-
Precedence::Assign if range => Scan::Fail,
670+
Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
666671
_ => Scan::Consume,
667672
},
668673
},
@@ -675,7 +680,7 @@ fn scan_right(
675680
}
676681
let right_fixup =
677682
fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump);
678-
match scan_right(&e.body, right_fixup, false, 1, 1) {
683+
match scan_right(&e.body, right_fixup, Precedence::Jump, 1, 1) {
679684
Scan::Fail => Scan::Bailout,
680685
Scan::Bailout | Scan::Consume => Scan::Consume,
681686
}
@@ -713,8 +718,8 @@ fn scan_right(
713718
| Expr::Unsafe(_)
714719
| Expr::Verbatim(_)
715720
| Expr::While(_) => match fixup.next_operator {
716-
Precedence::Assign | Precedence::Range if range => Scan::Fail,
717-
_ => Scan::Consume,
721+
Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
722+
_ => consume_by_precedence,
718723
},
719724
}
720725
}

0 commit comments

Comments
 (0)