Detect turbofish missing surrounding angle brackets

This commit is contained in:
Esteban Küber 2020-07-23 09:34:07 -07:00
parent 9e92106d45
commit 20f4e5d9c2
5 changed files with 61 additions and 3 deletions

View File

@ -2,7 +2,9 @@ use super::ty::AllowPlus;
use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
use rustc_ast::ast::{self, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Item, Param};
use rustc_ast::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
use rustc_ast::ast::{
AngleBracketedArgs, AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Lit, LitKind, TokenKind};
use rustc_ast::util::parser::AssocOp;
@ -488,6 +490,44 @@ impl<'a> Parser<'a> {
false
}
/// Check if a method call with an intended turbofish has been written without surrounding
/// angle brackets.
pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
if token::ModSep == self.token.kind && segment.args.is_none() {
let snapshot = self.clone();
self.bump();
let lo = self.token.span;
match self.parse_angle_args() {
Ok(args) if self.token.kind == token::OpenDelim(token::Paren) => {
// Recover from bad turbofish: `foo.collect::Vec<_>()`.
let span = lo.to(self.prev_token.span);
let args = AngleBracketedArgs { args, span }.into();
segment.args = args;
self.struct_span_err(
span,
"generic parameters without surrounding angle brackets",
)
.multipart_suggestion(
"surround the type parameters with angle brackets",
vec![
(span.shrink_to_lo(), "<".to_string()),
(span.shrink_to_hi(), ">".to_string()),
],
Applicability::MachineApplicable,
)
.emit();
}
Ok(_) => {
*self = snapshot;
}
Err(mut err) => {
err.cancel();
*self = snapshot;
}
}
}
}
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
/// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
/// parenthesising the leftmost comparison.

View File

@ -909,8 +909,9 @@ impl<'a> Parser<'a> {
}
let fn_span_lo = self.token.span;
let segment = self.parse_path_segment(PathStyle::Expr)?;
let mut segment = self.parse_path_segment(PathStyle::Expr)?;
self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
self.check_turbofish_missing_angle_brackets(&mut segment);
if self.check(&token::OpenDelim(token::Paren)) {
// Method call `expr.f()`

View File

@ -387,7 +387,7 @@ impl<'a> Parser<'a> {
/// Parses (possibly empty) list of generic arguments / associated item constraints,
/// possibly including trailing comma.
fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
let mut args = Vec::new();
while let Some(arg) = self.parse_angle_arg()? {
args.push(arg);

View File

@ -0,0 +1,4 @@
fn main() {
let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
//~^ ERROR generic parameters without surrounding angle brackets
}

View File

@ -0,0 +1,13 @@
error: generic parameters without surrounding angle brackets
--> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48
|
LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
| ^^^^^^
|
help: surround the type parameters with angle brackets
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
| ^ ^
error: aborting due to previous error