Skip to content

Commit 6c9f298

Browse files
committed
review comments
1 parent ed60cf2 commit 6c9f298

File tree

1 file changed

+49
-38
lines changed

1 file changed

+49
-38
lines changed

src/libsyntax/parse/diagnostics.rs

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ impl<'a> Parser<'a> {
560560
);
561561
match lhs.kind {
562562
ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
563+
563564
// Respan to include both operators.
564565
let op_span = op.span.to(self.prev_span);
565566
let mut err = self.struct_span_err(
@@ -573,70 +574,63 @@ impl<'a> Parser<'a> {
573574
let msg = "use `::<...>` instead of `<...>` if you meant to specify type \
574575
arguments";
575576
if *outer_op == AssocOp::Less {
576-
// if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) {
577577
let snapshot = self.clone();
578578
self.bump();
579-
// So far we have parsed `foo<bar<`
580-
let mut acc = 1;
581-
while acc > 0 {
582-
match &self.token.kind {
583-
token::Lt => {
584-
acc += 1;
585-
}
586-
token::Gt => {
587-
acc -= 1;
588-
}
589-
token::BinOp(token::Shr) => {
590-
acc -= 2;
591-
}
592-
token::Eof => {
593-
break;
594-
}
595-
_ => {}
596-
}
597-
self.bump();
598-
}
579+
// So far we have parsed `foo<bar<`, consume the rest of the type params
580+
let modifiers = vec![
581+
(token::Lt, 1),
582+
(token::Gt, -1),
583+
(token::BinOp(token::Shr), -2),
584+
];
585+
let early_return = vec![token::Eof];
586+
self.consume_tts(1, &modifiers[..], &early_return[..]);
587+
599588
if self.token.kind != token::OpenDelim(token::Paren) {
589+
// We don't have `foo< bar >(`, so we rewind the parser and bail out.
600590
mem::replace(self, snapshot.clone());
601591
}
602592
}
603593
if self.token.kind == token::OpenDelim(token::Paren) {
594+
// We have high certainty that this was a bad turbofish at this point.
595+
// `foo< bar >(`
604596
err.span_suggestion(
605597
op_span.shrink_to_lo(),
606598
msg,
607599
"::".to_string(),
608600
Applicability::MaybeIncorrect,
609601
);
602+
610603
let snapshot = self.clone();
611-
self.bump();
612-
let mut acc = 1;
613-
while acc > 0 {
614-
match &self.token.kind {
615-
token::OpenDelim(token::Paren) => {
616-
acc += 1;
617-
}
618-
token::CloseDelim(token::Paren) => {
619-
acc -= 1;
620-
}
621-
token::Eof => {
622-
break;
623-
}
624-
_ => {}
625-
}
626-
self.bump();
627-
}
604+
605+
// Consume the fn call arguments.
606+
let modifiers = vec![
607+
(token::OpenDelim(token::Paren), 1),
608+
(token::CloseDelim(token::Paren), -1),
609+
];
610+
let early_return = vec![token::Eof];
611+
self.bump(); // `(`
612+
self.consume_tts(1, &modifiers[..], &early_return[..]);
613+
628614
if self.token.kind == token::Eof {
615+
// Not entirely sure now, but we bubble the error up with the
616+
// suggestion.
629617
mem::replace(self, snapshot);
630618
return Err(err);
631619
} else {
620+
// 99% certain that the suggestion is correct, continue parsing.
632621
err.emit();
622+
// FIXME: actually check that the two expressions in the binop are
623+
// paths and resynthesize new fn call expression instead of using
624+
// `ExprKind::Err` placeholder.
633625
return Ok(Some(self.mk_expr(
634626
lhs.span.to(self.prev_span),
635627
ExprKind::Err,
636628
ThinVec::new(),
637629
)));
638630
}
639631
} else {
632+
// All we know is that this is `foo < bar >` and *nothing* else. Try to
633+
// be helpful, but don't attempt to recover.
640634
err.help(msg);
641635
err.help("or use `(...)` if you meant to specify fn arguments");
642636
// These cases cause too many knock-down errors, bail out (#61329).
@@ -1424,6 +1418,23 @@ impl<'a> Parser<'a> {
14241418
err
14251419
}
14261420

1421+
fn consume_tts(
1422+
&mut self,
1423+
mut acc: i64,
1424+
modifier: &[(token::TokenKind, i64)], // Not using FxHasMap and FxHashSet due to
1425+
early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`.
1426+
) {
1427+
while acc > 0 {
1428+
if let Some((_, val)) = modifier.iter().filter(|(t, _)| *t == self.token.kind).next() {
1429+
acc += *val;
1430+
}
1431+
if early_return.contains(&self.token.kind) {
1432+
break;
1433+
}
1434+
self.bump();
1435+
}
1436+
}
1437+
14271438
/// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors.
14281439
///
14291440
/// This is necessary because at this point we don't know whether we parsed a function with

0 commit comments

Comments
 (0)