diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-07-23 09:34:07 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-07-23 09:35:49 -0700 |
| commit | 20f4e5d9c24809031fd6631436f0a7a5b075fe40 (patch) | |
| tree | 04ec2b6aa9813e7c3561310ca0e999d8838e6174 /src/librustc_parse/parser | |
| parent | 9e92106d457abd14f82adc29e7f2496861e07916 (diff) | |
| download | rust-20f4e5d9c24809031fd6631436f0a7a5b075fe40.tar.gz rust-20f4e5d9c24809031fd6631436f0a7a5b075fe40.zip | |
Detect turbofish missing surrounding angle brackets
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/diagnostics.rs | 42 | ||||
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 3 | ||||
| -rw-r--r-- | src/librustc_parse/parser/path.rs | 2 |
3 files changed, 44 insertions, 3 deletions
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 3244b35e89b..f84f54054ac 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -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. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3926122606e..d06b172bc14 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -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()` diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 67e9b3af4a8..3dcefd36257 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -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); |
