Skip to content

Commit d7dceaa

Browse files
committed
Account for missing turbofish in paths too
1 parent 6c9f298 commit d7dceaa

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

src/libsyntax/parse/diagnostics.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,12 +585,51 @@ impl<'a> Parser<'a> {
585585
let early_return = vec![token::Eof];
586586
self.consume_tts(1, &modifiers[..], &early_return[..]);
587587

588-
if self.token.kind != token::OpenDelim(token::Paren) {
589-
// We don't have `foo< bar >(`, so we rewind the parser and bail out.
588+
if !&[
589+
token::OpenDelim(token::Paren),
590+
token::ModSep,
591+
].contains(&self.token.kind) {
592+
// We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
593+
// parser and bail out.
590594
mem::replace(self, snapshot.clone());
591595
}
592596
}
593-
if self.token.kind == token::OpenDelim(token::Paren) {
597+
if token::ModSep == self.token.kind {
598+
// We have some certainty that this was a bad turbofish at this point.
599+
// `foo< bar >::`
600+
err.span_suggestion(
601+
op_span.shrink_to_lo(),
602+
msg,
603+
"::".to_string(),
604+
Applicability::MaybeIncorrect,
605+
);
606+
607+
let snapshot = self.clone();
608+
609+
self.bump(); // `::`
610+
// Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
611+
match self.parse_expr() {
612+
Ok(_) => {
613+
// 99% certain that the suggestion is correct, continue parsing.
614+
err.emit();
615+
// FIXME: actually check that the two expressions in the binop are
616+
// paths and resynthesize new fn call expression instead of using
617+
// `ExprKind::Err` placeholder.
618+
return Ok(Some(self.mk_expr(
619+
lhs.span.to(self.prev_span),
620+
ExprKind::Err,
621+
ThinVec::new(),
622+
)));
623+
}
624+
Err(mut err) => {
625+
err.cancel();
626+
// Not entirely sure now, but we bubble the error up with the
627+
// suggestion.
628+
mem::replace(self, snapshot);
629+
return Err(err);
630+
}
631+
}
632+
} else if token::OpenDelim(token::Paren) == self.token.kind {
594633
// We have high certainty that this was a bad turbofish at this point.
595634
// `foo< bar >(`
596635
err.span_suggestion(
@@ -601,14 +640,14 @@ impl<'a> Parser<'a> {
601640
);
602641

603642
let snapshot = self.clone();
643+
self.bump(); // `(`
604644

605645
// Consume the fn call arguments.
606646
let modifiers = vec![
607647
(token::OpenDelim(token::Paren), 1),
608648
(token::CloseDelim(token::Paren), -1),
609649
];
610650
let early_return = vec![token::Eof];
611-
self.bump(); // `(`
612651
self.consume_tts(1, &modifiers[..], &early_return[..]);
613652

614653
if self.token.kind == token::Eof {

src/test/ui/did_you_mean/issue-40396.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ error: chained comparison operators require parentheses
1313
|
1414
LL | Vec<i32>::new();
1515
| ^^^^^
16+
help: use `::<...>` instead of `<...>` if you meant to specify type arguments
1617
|
17-
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
18-
= help: or use `(...)` if you meant to specify fn arguments
18+
LL | Vec::<i32>::new();
19+
| ^^
1920

2021
error: chained comparison operators require parentheses
2122
--> $DIR/issue-40396.rs:12:20

0 commit comments

Comments
 (0)