about summary refs log tree commit diff
path: root/compiler/rustc_parse
diff options
context:
space:
mode:
authorMu001999 <mu001999@outlook.com>2023-08-03 00:00:56 +0800
committerMu001999 <mu001999@outlook.com>2023-08-03 00:00:56 +0800
commit89b2fe7750eb251c2b621bad1f8d86477d7a1f91 (patch)
tree7ce4a1cc8b14144511379d43e388e376cced2609 /compiler/rustc_parse
parent049c728c60f7c950b7185f0f277609694a8e2a16 (diff)
downloadrust-89b2fe7750eb251c2b621bad1f8d86477d7a1f91.tar.gz
rust-89b2fe7750eb251c2b621bad1f8d86477d7a1f91.zip
Keep the suggestion for wrong arbitrary self types
Diffstat (limited to 'compiler/rustc_parse')
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs26
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs10
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs6
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs4
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs36
-rw-r--r--compiler/rustc_parse/src/parser/path.rs39
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs2
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs6
10 files changed, 85 insertions, 54 deletions
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index ee0abba1c17..1271bce799d 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -260,7 +260,7 @@ impl<'a> Parser<'a> {
             item
         } else {
             let do_parse = |this: &mut Self| {
-                let path = this.parse_path(PathStyle::Mod)?;
+                let path = this.parse_path(PathStyle::Mod, None)?;
                 let args = this.parse_attr_args()?;
                 Ok(ast::AttrItem { path, args, tokens: None })
             };
@@ -387,7 +387,7 @@ impl<'a> Parser<'a> {
         }
 
         let lo = self.token.span;
-        let path = self.parse_path(PathStyle::Mod)?;
+        let path = self.parse_path(PathStyle::Mod, None)?;
         let kind = self.parse_meta_item_kind()?;
         let span = lo.to(self.prev_token.span);
         Ok(ast::MetaItem { path, kind, span })
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 7d04a335c9e..8bc4433a965 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1579,7 +1579,7 @@ impl<'a> Parser<'a> {
         self.expect(&token::ModSep)?;
 
         let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
-        self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
+        self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None, None)?;
         path.span = ty_span.to(self.prev_token.span);
 
         let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
@@ -2019,7 +2019,7 @@ impl<'a> Parser<'a> {
         {
             let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
 
-            let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
+            let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span, maybe_name) =
                 match pat.kind {
                     PatKind::Ident(_, ident, _) => (
                         ident,
@@ -2029,6 +2029,7 @@ impl<'a> Parser<'a> {
                         pat.span.shrink_to_lo(),
                         pat.span.shrink_to_hi(),
                         pat.span.shrink_to_lo(),
+                        true,
                     ),
                     // Also catches `fn foo(&a)`.
                     PatKind::Ref(ref inner_pat, mutab)
@@ -2045,11 +2046,22 @@ impl<'a> Parser<'a> {
                                     pat.span.shrink_to_lo(),
                                     pat.span,
                                     pat.span.shrink_to_lo(),
+                                    true,
                                 )
                             }
                             _ => unreachable!(),
                         }
-                    }
+                    },
+                    PatKind::Path(_, ref path) if let Some(segment) = path.segments.last() => (
+                        segment.ident,
+                        "self: ",
+                        ": TypeName".to_string(),
+                        "_: ",
+                        pat.span.shrink_to_lo(),
+                        pat.span.shrink_to_hi(),
+                        pat.span.shrink_to_lo(),
+                        path.segments.len() == 1, // Avoid suggesting that `fn foo(a::b)` is fixed with a change to `fn foo(a::b: TypeName)`.
+                    ),
                     _ => {
                         // Otherwise, try to get a type and emit a suggestion.
                         if let Some(ty) = pat.to_ty() {
@@ -2077,7 +2089,7 @@ impl<'a> Parser<'a> {
             }
             // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
             // `fn foo(HashMap: TypeName<u32>)`.
-            if self.token != token::Lt {
+            if self.token != token::Lt && maybe_name {
                 err.span_suggestion(
                     param_span,
                     "if this is a parameter name, give it a type",
@@ -2100,7 +2112,7 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
-        let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName))?;
+        let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
@@ -2508,7 +2520,7 @@ impl<'a> Parser<'a> {
                 // Skip the `:`.
                 snapshot_pat.bump();
                 snapshot_type.bump();
-                match snapshot_pat.parse_pat_no_top_alt(expected) {
+                match snapshot_pat.parse_pat_no_top_alt(expected, None) {
                     Err(inner_err) => {
                         inner_err.cancel();
                     }
@@ -2772,7 +2784,7 @@ impl<'a> Parser<'a> {
     /// sequence of patterns until `)` is reached.
     fn skip_pat_list(&mut self) -> PResult<'a, ()> {
         while !self.check(&token::CloseDelim(Delimiter::Parenthesis)) {
-            self.parse_pat_no_top_alt(None)?;
+            self.parse_pat_no_top_alt(None, None)?;
             if !self.eat(&token::Comma) {
                 return Ok(());
             }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index b54cb8c5a0c..6dafb8b999b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -775,7 +775,7 @@ impl<'a> Parser<'a> {
                     _ => {}
                 }
 
-                match self.parse_path(PathStyle::Expr) {
+                match self.parse_path(PathStyle::Expr, None) {
                     Ok(path) => {
                         let span_after_type = parser_snapshot_after_type.token.span;
                         let expr = mk_expr(
@@ -1314,7 +1314,7 @@ impl<'a> Parser<'a> {
         }
 
         let fn_span_lo = self.token.span;
-        let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
+        let mut seg = self.parse_path_segment(PathStyle::Expr, None, None)?;
         self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
         self.check_turbofish_missing_angle_brackets(&mut seg);
 
@@ -1544,7 +1544,7 @@ impl<'a> Parser<'a> {
             })?;
             (Some(qself), path)
         } else {
-            (None, self.parse_path(PathStyle::Expr)?)
+            (None, self.parse_path(PathStyle::Expr, None)?)
         };
 
         // `!`, as an operator, is prefix, so we know this isn't that.
@@ -2338,7 +2338,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
-            let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName))?;
+            let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?;
             let ty = if this.eat(&token::Colon) {
                 this.parse_ty()?
             } else {
@@ -2781,7 +2781,7 @@ impl<'a> Parser<'a> {
                 return None;
             }
             let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
-            match self.parse_pat_no_top_alt(None) {
+            match self.parse_pat_no_top_alt(None, None) {
                 Ok(_pat) => {
                     if self.token.kind == token::FatArrow {
                         // Reached arm end.
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 1301ed3e388..d3f756139de 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -452,7 +452,7 @@ impl<'a> Parser<'a> {
 
     /// Parses an item macro, e.g., `item!();`.
     fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
-        let path = self.parse_path(PathStyle::Mod)?; // `foo::bar`
+        let path = self.parse_path(PathStyle::Mod, None)?; // `foo::bar`
         self.expect(&token::Not)?; // `!`
         match self.parse_delim_args() {
             // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
@@ -976,7 +976,7 @@ impl<'a> Parser<'a> {
             self.parse_use_tree_glob_or_nested()?
         } else {
             // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
-            prefix = self.parse_path(PathStyle::Mod)?;
+            prefix = self.parse_path(PathStyle::Mod, None)?;
 
             if self.eat(&token::ModSep) {
                 self.parse_use_tree_glob_or_nested()?
@@ -987,7 +987,7 @@ impl<'a> Parser<'a> {
                         .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
 
                     // We parse the rest of the path and append it to the original prefix.
-                    self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None)?;
+                    self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, None, None)?;
                     prefix.span = lo.to(self.prev_token.span);
                 }
 
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 37b4c371c94..2af0caa1bda 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1413,7 +1413,7 @@ impl<'a> Parser<'a> {
                 // Parse `pub(in path)`.
                 self.bump(); // `(`
                 self.bump(); // `in`
-                let path = self.parse_path(PathStyle::Mod)?; // `path`
+                let path = self.parse_path(PathStyle::Mod, None)?; // `path`
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
                 let vis = VisibilityKind::Restricted {
                     path: P(path),
@@ -1430,7 +1430,7 @@ impl<'a> Parser<'a> {
             {
                 // Parse `pub(crate)`, `pub(self)`, or `pub(super)`.
                 self.bump(); // `(`
-                let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self`
+                let path = self.parse_path(PathStyle::Mod, None)?; // `crate`/`super`/`self`
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
                 let vis = VisibilityKind::Restricted {
                     path: P(path),
@@ -1456,7 +1456,7 @@ impl<'a> Parser<'a> {
     /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
     fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
         self.bump(); // `(`
-        let path = self.parse_path(PathStyle::Mod)?;
+        let path = self.parse_path(PathStyle::Mod, None)?;
         self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
 
         let path_str = pprust::path_to_string(&path);
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index adb0d372a40..a09c1e4d7fd 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -131,7 +131,7 @@ impl<'a> Parser<'a> {
             },
             NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
-                    NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
+                    NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
                     NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
@@ -168,7 +168,7 @@ impl<'a> Parser<'a> {
                 }.into_diagnostic(&self.sess.span_diagnostic));
             }
             NonterminalKind::Path => token::NtPath(
-                P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
+                P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type, None))?),
             ),
             NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
             NonterminalKind::Vis => token::NtVis(
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index e0539c4ac04..615ef28db08 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -80,7 +80,8 @@ enum EatOrResult {
 }
 
 /// The syntax location of a given pattern. Used for diagnostics.
-pub(super) enum PatternLocation {
+#[derive(Clone, Copy)]
+pub enum PatternLocation {
     LetBinding,
     FunctionParameter,
 }
@@ -91,8 +92,12 @@ impl<'a> Parser<'a> {
     /// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
     /// at the top level. Used when parsing the parameters of lambda expressions,
     /// functions, function pointers, and `pat` macro fragments.
-    pub fn parse_pat_no_top_alt(&mut self, expected: Option<Expected>) -> PResult<'a, P<Pat>> {
-        self.parse_pat_with_range_pat(true, expected)
+    pub fn parse_pat_no_top_alt(
+        &mut self,
+        expected: Option<Expected>,
+        syntax_loc: Option<PatternLocation>,
+    ) -> PResult<'a, P<Pat>> {
+        self.parse_pat_with_range_pat(true, expected, syntax_loc)
     }
 
     /// Parses a pattern.
@@ -110,7 +115,7 @@ impl<'a> Parser<'a> {
         ra: RecoverColon,
         rt: CommaRecoveryMode,
     ) -> PResult<'a, P<Pat>> {
-        self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt).map(|(pat, _)| pat)
+        self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat)
     }
 
     /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@@ -121,6 +126,7 @@ impl<'a> Parser<'a> {
         rc: RecoverComma,
         ra: RecoverColon,
         rt: CommaRecoveryMode,
+        syntax_loc: Option<PatternLocation>,
     ) -> PResult<'a, (P<Pat>, bool)> {
         // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
         // suggestions (which bothers rustfix).
@@ -133,7 +139,7 @@ impl<'a> Parser<'a> {
         };
 
         // Parse the first pattern (`p_0`).
-        let mut first_pat = self.parse_pat_no_top_alt(expected)?;
+        let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc.clone())?;
         if rc == RecoverComma::Yes {
             self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
         }
@@ -172,7 +178,7 @@ impl<'a> Parser<'a> {
                     break;
                 }
             }
-            let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| {
+            let pat = self.parse_pat_no_top_alt(expected, syntax_loc).map_err(|mut err| {
                 err.span_label(lo, WHILE_PARSING_OR_MSG);
                 err
             })?;
@@ -208,6 +214,7 @@ impl<'a> Parser<'a> {
             rc,
             RecoverColon::No,
             CommaRecoveryMode::LikelyTuple,
+            Some(syntax_loc),
         )?;
         let colon = self.eat(&token::Colon);
 
@@ -319,6 +326,7 @@ impl<'a> Parser<'a> {
         &mut self,
         allow_range_pat: bool,
         expected: Option<Expected>,
+        syntax_loc: Option<PatternLocation>,
     ) -> PResult<'a, P<Pat>> {
         maybe_recover_from_interpolated_ty_qpath!(self, true);
         maybe_whole!(self, NtPat, |x| x);
@@ -393,7 +401,7 @@ impl<'a> Parser<'a> {
                 (Some(qself), path)
             } else {
                 // Parse an unqualified path
-                (None, self.parse_path(PathStyle::Pat)?)
+                (None, self.parse_path(PathStyle::Pat, syntax_loc)?)
             };
             let span = lo.to(self.prev_token.span);
 
@@ -485,7 +493,7 @@ impl<'a> Parser<'a> {
 
         // At this point we attempt to parse `@ $pat_rhs` and emit an error.
         self.bump(); // `@`
-        let mut rhs = self.parse_pat_no_top_alt(None)?;
+        let mut rhs = self.parse_pat_no_top_alt(None, None)?;
         let whole_span = lhs.span.to(rhs.span);
 
         if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
@@ -541,7 +549,7 @@ impl<'a> Parser<'a> {
         }
 
         let mutbl = self.parse_mutability();
-        let subpat = self.parse_pat_with_range_pat(false, expected)?;
+        let subpat = self.parse_pat_with_range_pat(false, expected, None)?;
         Ok(PatKind::Ref(subpat, mutbl))
     }
 
@@ -584,7 +592,7 @@ impl<'a> Parser<'a> {
         }
 
         // Parse the pattern we hope to be an identifier.
-        let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier))?;
+        let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?;
 
         // If we don't have `mut $ident (@ pat)?`, error.
         if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
@@ -776,7 +784,7 @@ impl<'a> Parser<'a> {
                 (Some(qself), path)
             } else {
                 // Parse an unqualified path
-                (None, self.parse_path(PathStyle::Pat)?)
+                (None, self.parse_path(PathStyle::Pat, None)?)
             };
             let hi = self.prev_token.span;
             Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path)))
@@ -814,7 +822,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
         let ident = self.parse_ident()?;
         let sub = if self.eat(&token::At) {
-            Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
+            Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
         } else {
             None
         };
@@ -903,14 +911,14 @@ impl<'a> Parser<'a> {
             // We cannot use `parse_pat_ident()` since it will complain `box`
             // is not an identifier.
             let sub = if self.eat(&token::At) {
-                Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
+                Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
             } else {
                 None
             };
 
             Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
         } else {
-            let pat = self.parse_pat_with_range_pat(false, None)?;
+            let pat = self.parse_pat_with_range_pat(false, None, None)?;
             self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
             Ok(PatKind::Box(pat))
         }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 4fe8a5aa626..0d5f48e424e 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,3 +1,4 @@
+use super::pat::PatternLocation;
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
 use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon};
@@ -79,7 +80,7 @@ impl<'a> Parser<'a> {
         let (mut path, path_span);
         if self.eat_keyword(kw::As) {
             let path_lo = self.token.span;
-            path = self.parse_path(PathStyle::Type)?;
+            path = self.parse_path(PathStyle::Type, None)?;
             path_span = path_lo.to(self.prev_token.span);
         } else {
             path_span = self.token.span.to(self.token.span);
@@ -98,7 +99,7 @@ impl<'a> Parser<'a> {
         }
 
         let qself = P(QSelf { ty, path_span, position: path.segments.len() });
-        self.parse_path_segments(&mut path.segments, style, None)?;
+        self.parse_path_segments(&mut path.segments, style, None, None)?;
 
         Ok((
             qself,
@@ -139,8 +140,12 @@ impl<'a> Parser<'a> {
         true
     }
 
-    pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
-        self.parse_path_inner(style, None)
+    pub(super) fn parse_path(
+        &mut self,
+        style: PathStyle,
+        syntax_loc: Option<PatternLocation>,
+    ) -> PResult<'a, Path> {
+        self.parse_path_inner(style, None, syntax_loc)
     }
 
     /// Parses simple paths.
@@ -157,6 +162,7 @@ impl<'a> Parser<'a> {
         &mut self,
         style: PathStyle,
         ty_generics: Option<&Generics>,
+        syntax_loc: Option<PatternLocation>,
     ) -> PResult<'a, Path> {
         let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| {
             // Ensure generic arguments don't end up in attribute paths, such as:
@@ -201,7 +207,7 @@ impl<'a> Parser<'a> {
         if self.eat(&token::ModSep) {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
-        self.parse_path_segments(&mut segments, style, ty_generics)?;
+        self.parse_path_segments(&mut segments, style, ty_generics, syntax_loc)?;
         Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
     }
 
@@ -210,9 +216,10 @@ impl<'a> Parser<'a> {
         segments: &mut ThinVec<PathSegment>,
         style: PathStyle,
         ty_generics: Option<&Generics>,
+        syntax_loc: Option<PatternLocation>,
     ) -> PResult<'a, ()> {
         loop {
-            let segment = self.parse_path_segment(style, ty_generics)?;
+            let segment = self.parse_path_segment(style, ty_generics, syntax_loc)?;
             if style.has_generic_ambiguity() {
                 // In order to check for trailing angle brackets, we must have finished
                 // recursing (`parse_path_segment` can indirectly call this function),
@@ -267,6 +274,7 @@ impl<'a> Parser<'a> {
         &mut self,
         style: PathStyle,
         ty_generics: Option<&Generics>,
+        syntax_loc: Option<PatternLocation>,
     ) -> PResult<'a, PathSegment> {
         let ident = self.parse_path_segment_ident()?;
         let is_args_start = |token: &Token| {
@@ -286,6 +294,17 @@ impl<'a> Parser<'a> {
             is_args_start(&this.token)
         };
 
+        if let Some(PatternLocation::FunctionParameter) = syntax_loc {
+        } else if style == PathStyle::Pat
+            && self.check_noexpect(&token::Lt)
+            && self.look_ahead(1, |t| t.can_begin_type())
+        {
+            return Err(self.sess.create_err(GenericArgsInPatRequireTurbofishSyntax {
+                span: self.token.span,
+                suggest_turbofish: self.token.span.shrink_to_lo(),
+            }));
+        }
+
         Ok(
             if style == PathStyle::Type && check_args_start(self)
                 || style != PathStyle::Mod
@@ -382,14 +401,6 @@ impl<'a> Parser<'a> {
                 };
 
                 PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID }
-            } else if style == PathStyle::Pat
-                && self.check_noexpect(&token::Lt)
-                && self.look_ahead(1, |t| t.can_begin_type())
-            {
-                return Err(self.sess.create_err(GenericArgsInPatRequireTurbofishSyntax {
-                    span: self.token.span,
-                    suggest_turbofish: self.token.span.shrink_to_lo(),
-                }));
             } else {
                 // Generic arguments are not found.
                 PathSegment::from_ident(ident)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 9fcf51a04ec..2c08e984be5 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -149,7 +149,7 @@ impl<'a> Parser<'a> {
 
     fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
         let stmt = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
-            let path = this.parse_path(PathStyle::Expr)?;
+            let path = this.parse_path(PathStyle::Expr, None)?;
 
             if this.eat(&token::Not) {
                 let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 3bb50b05aa3..8be84c7d462 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -289,7 +289,7 @@ impl<'a> Parser<'a> {
                     recover_return_sign,
                 )?
             } else {
-                let path = self.parse_path(PathStyle::Type)?;
+                let path = self.parse_path(PathStyle::Type, None)?;
                 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
                 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
             }
@@ -649,7 +649,7 @@ impl<'a> Parser<'a> {
         ty_generics: Option<&Generics>,
     ) -> PResult<'a, TyKind> {
         // Simple path
-        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
+        let path = self.parse_path_inner(PathStyle::Type, ty_generics, None)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
             Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
@@ -865,7 +865,7 @@ impl<'a> Parser<'a> {
 
             path
         } else {
-            self.parse_path(PathStyle::Type)?
+            self.parse_path(PathStyle::Type, None)?
         };
 
         if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {