From 049c728c60f7c950b7185f0f277609694a8e2a16 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Tue, 1 Aug 2023 23:30:40 +0800 Subject: [PATCH 1/6] Suggests turbofish in patterns --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 14 ++++++++ compiler/rustc_parse/src/parser/pat.rs | 1 + compiler/rustc_parse/src/parser/path.rs | 10 +++++- tests/ui/did_you_mean/issue-114112.rs | 11 +++++++ tests/ui/did_you_mean/issue-114112.stderr | 13 ++++++++ tests/ui/parser/issues/issue-22647.rs | 2 +- tests/ui/parser/issues/issue-22647.stderr | 9 ++++-- tests/ui/parser/issues/issue-22712.rs | 2 +- tests/ui/parser/issues/issue-22712.stderr | 9 ++++-- tests/ui/parser/pat-lt-bracket-3.rs | 3 +- tests/ui/parser/pat-lt-bracket-3.stderr | 9 ++++-- tests/ui/parser/pat-lt-bracket-4.rs | 2 +- tests/ui/parser/pat-lt-bracket-4.stderr | 9 ++++-- tests/ui/span/issue-34264.rs | 2 +- tests/ui/span/issue-34264.stderr | 15 +++------ tests/ui/suggestions/issue-64252-self-type.rs | 6 ++-- .../suggestions/issue-64252-self-type.stderr | 32 +++++++------------ 18 files changed, 101 insertions(+), 50 deletions(-) create mode 100644 tests/ui/did_you_mean/issue-114112.rs create mode 100644 tests/ui/did_you_mean/issue-114112.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 83d96ad8e7665..6a9a5a239e48a 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -270,6 +270,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}` parse_function_body_equals_expr = function body cannot be `= expression;` .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` +parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax + parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets .suggestion = surround the type parameters with angle brackets diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 06c0996072730..3184ca777cef2 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2731,3 +2731,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg { #[suggestion_part(code = "")] pub right: Span, } + +#[derive(Diagnostic)] +#[diag(parse_generic_args_in_pat_require_turbofish_syntax)] +pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { + #[primary_span] + pub span: Span, + #[suggestion( + parse_sugg_turbofish_syntax, + style = "verbose", + code = "::", + applicability = "maybe-incorrect" + )] + pub suggest_turbofish: Span, +} diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 14891c45d81a2..e0539c4ac04dc 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -805,6 +805,7 @@ impl<'a> Parser<'a> { | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. | token::ModSep // A tuple / struct variant pattern. | token::Not)) // A macro expanding to a pattern. + && !(self.look_ahead(1, |t| t.kind == token::Lt) && self.look_ahead(2, |t| t.can_begin_type())) // May suggest the turbofish syntax for generics, only valid for recoveries. } /// Parses `ident` or `ident @ pat`. diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index feb7e829caf68..4fe8a5aa62609 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,6 +1,6 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; -use crate::errors::PathSingleColon; +use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon}; use crate::{errors, maybe_whole}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -382,6 +382,14 @@ 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/tests/ui/did_you_mean/issue-114112.rs b/tests/ui/did_you_mean/issue-114112.rs new file mode 100644 index 0000000000000..0fde12ecd788f --- /dev/null +++ b/tests/ui/did_you_mean/issue-114112.rs @@ -0,0 +1,11 @@ +enum E { + A(T) +} + +fn main() { + match E::::A(1) { + E::A(v) => { //~ ERROR generic args in patterns require the turbofish syntax + println!("{v:?}"); + }, + } +} diff --git a/tests/ui/did_you_mean/issue-114112.stderr b/tests/ui/did_you_mean/issue-114112.stderr new file mode 100644 index 0000000000000..d76b5f72e30cf --- /dev/null +++ b/tests/ui/did_you_mean/issue-114112.stderr @@ -0,0 +1,13 @@ +error: generic args in patterns require the turbofish syntax + --> $DIR/issue-114112.rs:7:10 + | +LL | E::A(v) => { + | ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | E::::A(v) => { + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-22647.rs b/tests/ui/parser/issues/issue-22647.rs index a6861410682cb..163cbc69ddd62 100644 --- a/tests/ui/parser/issues/issue-22647.rs +++ b/tests/ui/parser/issues/issue-22647.rs @@ -1,5 +1,5 @@ fn main() { - let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` + let caller = |f: F| //~ ERROR generic args in patterns require the turbofish syntax where F: Fn() -> i32 { let x = f(); diff --git a/tests/ui/parser/issues/issue-22647.stderr b/tests/ui/parser/issues/issue-22647.stderr index 89b454d1973d5..585e70266619a 100644 --- a/tests/ui/parser/issues/issue-22647.stderr +++ b/tests/ui/parser/issues/issue-22647.stderr @@ -1,8 +1,13 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/issue-22647.rs:2:15 | LL | let caller = |f: F| - | ^ expected one of `:`, `;`, `=`, `@`, or `|` + | ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let caller:: = |f: F| + | ++ error: aborting due to previous error diff --git a/tests/ui/parser/issues/issue-22712.rs b/tests/ui/parser/issues/issue-22712.rs index 774de9c7e6448..92b12b8e1934c 100644 --- a/tests/ui/parser/issues/issue-22712.rs +++ b/tests/ui/parser/issues/issue-22712.rs @@ -3,7 +3,7 @@ struct Foo { } fn bar() { - let Foo> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` + let Foo> //~ ERROR generic args in patterns require the turbofish syntax } fn main() {} diff --git a/tests/ui/parser/issues/issue-22712.stderr b/tests/ui/parser/issues/issue-22712.stderr index 30fabac65640c..7f9d99d8edfa1 100644 --- a/tests/ui/parser/issues/issue-22712.stderr +++ b/tests/ui/parser/issues/issue-22712.stderr @@ -1,8 +1,13 @@ -error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/issue-22712.rs:6:12 | LL | let Foo> - | ^ expected one of `:`, `;`, `=`, `@`, or `|` + | ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let Foo::> + | ++ error: aborting due to previous error diff --git a/tests/ui/parser/pat-lt-bracket-3.rs b/tests/ui/parser/pat-lt-bracket-3.rs index a8bdfd3fa181b..bd83fe8db4b56 100644 --- a/tests/ui/parser/pat-lt-bracket-3.rs +++ b/tests/ui/parser/pat-lt-bracket-3.rs @@ -3,8 +3,7 @@ struct Foo(T, T); impl Foo { fn foo(&self) { match *self { - Foo(x, y) => { - //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + Foo(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax println!("Goodbye, World!") } } diff --git a/tests/ui/parser/pat-lt-bracket-3.stderr b/tests/ui/parser/pat-lt-bracket-3.stderr index bacf868e3c4e7..afdf1e9a55762 100644 --- a/tests/ui/parser/pat-lt-bracket-3.stderr +++ b/tests/ui/parser/pat-lt-bracket-3.stderr @@ -1,8 +1,13 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/pat-lt-bracket-3.rs:6:16 | LL | Foo(x, y) => { - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | Foo::(x, y) => { + | ++ error: aborting due to previous error diff --git a/tests/ui/parser/pat-lt-bracket-4.rs b/tests/ui/parser/pat-lt-bracket-4.rs index de314f6c6412d..6d348b68cd66b 100644 --- a/tests/ui/parser/pat-lt-bracket-4.rs +++ b/tests/ui/parser/pat-lt-bracket-4.rs @@ -5,7 +5,7 @@ enum BtNode { fn main() { let y = match 10 { - Foo::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + Foo::A(value) => value, //~ ERROR generic args in patterns require the turbofish syntax Foo::B => 7, }; } diff --git a/tests/ui/parser/pat-lt-bracket-4.stderr b/tests/ui/parser/pat-lt-bracket-4.stderr index 911c276b9319a..b71a5ad939e59 100644 --- a/tests/ui/parser/pat-lt-bracket-4.stderr +++ b/tests/ui/parser/pat-lt-bracket-4.stderr @@ -1,8 +1,13 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/pat-lt-bracket-4.rs:8:12 | LL | Foo::A(value) => value, - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | Foo::::A(value) => value, + | ++ error: aborting due to previous error diff --git a/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs index 9227ee482dfa5..c7a8440f28401 100644 --- a/tests/ui/span/issue-34264.rs +++ b/tests/ui/span/issue-34264.rs @@ -1,5 +1,5 @@ fn foo(Option, String) {} //~ ERROR expected one of -//~^ ERROR expected one of +//~^ ERROR generic args in patterns require the turbofish syntax fn bar(x, y: usize) {} //~ ERROR expected one of fn main() { diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr index f0dea66f6128d..1874d7f853379 100644 --- a/tests/ui/span/issue-34264.stderr +++ b/tests/ui/span/issue-34264.stderr @@ -1,18 +1,13 @@ -error: expected one of `:`, `@`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/issue-34264.rs:1:14 | LL | fn foo(Option, String) {} - | ^ expected one of `:`, `@`, or `|` + | ^ | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name - | -LL | fn foo(self: Option, String) {} - | +++++ -help: if this is a type, explicitly ignore the parameter name +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | -LL | fn foo(_: Option, String) {} - | ++ +LL | fn foo(Option::, String) {} + | ++ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs index 128d5e85c22c8..ad25d334507fc 100644 --- a/tests/ui/suggestions/issue-64252-self-type.rs +++ b/tests/ui/suggestions/issue-64252-self-type.rs @@ -1,14 +1,12 @@ // This test checks that a suggestion to add a `self: ` parameter name is provided // to functions where this is applicable. -pub fn foo(Box) { } -//~^ ERROR expected one of `:`, `@`, or `|`, found `<` +pub fn foo(Box) { } //~ ERROR generic args in patterns require the turbofish syntax struct Bar; impl Bar { - fn bar(Box) { } - //~^ ERROR expected one of `:`, `@`, or `|`, found `<` + fn bar(Box) { } //~ ERROR generic args in patterns require the turbofish syntax } fn main() { } diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr index c3418dab0e8af..ba5c2da241500 100644 --- a/tests/ui/suggestions/issue-64252-self-type.stderr +++ b/tests/ui/suggestions/issue-64252-self-type.stderr @@ -1,34 +1,24 @@ -error: expected one of `:`, `@`, or `|`, found `<` +error: generic args in patterns require the turbofish syntax --> $DIR/issue-64252-self-type.rs:4:15 | LL | pub fn foo(Box) { } - | ^ expected one of `:`, `@`, or `|` + | ^ | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | -LL | pub fn foo(self: Box) { } - | +++++ -help: if this is a type, explicitly ignore the parameter name - | -LL | pub fn foo(_: Box) { } - | ++ +LL | pub fn foo(Box::) { } + | ++ -error: expected one of `:`, `@`, or `|`, found `<` - --> $DIR/issue-64252-self-type.rs:10:15 +error: generic args in patterns require the turbofish syntax + --> $DIR/issue-64252-self-type.rs:9:15 | LL | fn bar(Box) { } - | ^ expected one of `:`, `@`, or `|` - | - = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name + | ^ | -LL | fn bar(self: Box) { } - | +++++ -help: if this is a type, explicitly ignore the parameter name +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments | -LL | fn bar(_: Box) { } - | ++ +LL | fn bar(Box::) { } + | ++ error: aborting due to 2 previous errors From 89b2fe7750eb251c2b621bad1f8d86477d7a1f91 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Thu, 3 Aug 2023 00:00:56 +0800 Subject: [PATCH 2/6] Keep the suggestion for wrong arbitrary self types --- compiler/rustc_parse/src/parser/attr.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 26 +++++++++---- compiler/rustc_parse/src/parser/expr.rs | 10 ++--- compiler/rustc_parse/src/parser/item.rs | 6 +-- compiler/rustc_parse/src/parser/mod.rs | 6 +-- .../rustc_parse/src/parser/nonterminal.rs | 4 +- compiler/rustc_parse/src/parser/pat.rs | 36 ++++++++++------- compiler/rustc_parse/src/parser/path.rs | 39 ++++++++++++------- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 6 +-- .../anon-params-denied-2018.stderr | 20 +++++++--- tests/ui/span/issue-34264.rs | 2 +- tests/ui/span/issue-34264.stderr | 15 ++++--- tests/ui/suggestions/issue-64252-self-type.rs | 5 +-- .../suggestions/issue-64252-self-type.stderr | 32 +++++++++------ 15 files changed, 133 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index ee0abba1c1753..1271bce799d5c 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 7d04a335c9e0b..8bc4433a9653a 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)` is fixed with a change to // `fn foo(HashMap: TypeName)`. - 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, P)> { - 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 b54cb8c5a0c10..6dafb8b999b2f 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 1301ed3e3882e..d3f756139def3 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 37b4c371c94b4..2af0caa1bdaf7 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 adb0d372a40df..a09c1e4d7fde2 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 e0539c4ac04dc..615ef28db085d 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` 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) -> PResult<'a, P> { - self.parse_pat_with_range_pat(true, expected) + pub fn parse_pat_no_top_alt( + &mut self, + expected: Option, + syntax_loc: Option, + ) -> PResult<'a, P> { + 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> { - 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, ) -> PResult<'a, (P, 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, + syntax_loc: Option, ) -> PResult<'a, P> { 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 4fe8a5aa62609..0d5f48e424e2c 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, + ) -> 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, ) -> 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, style: PathStyle, ty_generics: Option<&Generics>, + syntax_loc: Option, ) -> 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, ) -> 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 9fcf51a04ec05..2c08e984be578 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 3bb50b05aa346..8be84c7d46224 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) { diff --git a/tests/ui/anon-params/anon-params-denied-2018.stderr b/tests/ui/anon-params/anon-params-denied-2018.stderr index bb60c898e8122..ede0e70cd7100 100644 --- a/tests/ui/anon-params/anon-params-denied-2018.stderr +++ b/tests/ui/anon-params/anon-params-denied-2018.stderr @@ -45,10 +45,14 @@ LL | fn foo_with_qualified_path(::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: explicitly ignore the parameter name +help: if this is a `self` type, give it a parameter name + | +LL | fn foo_with_qualified_path(self: ::Baz); + | +++++ +help: if this is a type, explicitly ignore the parameter name | LL | fn foo_with_qualified_path(_: ::Baz); - | ~~~~~~~~~~~~~~~~~~ + | ++ error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:15:56 @@ -69,10 +73,14 @@ LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: explicitly ignore the parameter name +help: if this is a `self` type, give it a parameter name + | +LL | fn foo_with_multiple_qualified_paths(self: ::Baz, ::Baz); + | +++++ +help: if this is a type, explicitly ignore the parameter name | LL | fn foo_with_multiple_qualified_paths(_: ::Baz, ::Baz); - | ~~~~~~~~~~~~~~~~~~ + | ++ error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:18:74 @@ -81,10 +89,10 @@ LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: explicitly ignore the parameter name +help: if this is a type, explicitly ignore the parameter name | LL | fn foo_with_multiple_qualified_paths(::Baz, _: ::Baz); - | ~~~~~~~~~~~~~~~~~~ + | ++ error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:22:36 diff --git a/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs index c7a8440f28401..9227ee482dfa5 100644 --- a/tests/ui/span/issue-34264.rs +++ b/tests/ui/span/issue-34264.rs @@ -1,5 +1,5 @@ fn foo(Option, String) {} //~ ERROR expected one of -//~^ ERROR generic args in patterns require the turbofish syntax +//~^ ERROR expected one of fn bar(x, y: usize) {} //~ ERROR expected one of fn main() { diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr index 1874d7f853379..8c639d5513b53 100644 --- a/tests/ui/span/issue-34264.stderr +++ b/tests/ui/span/issue-34264.stderr @@ -1,13 +1,18 @@ -error: generic args in patterns require the turbofish syntax +error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` --> $DIR/issue-34264.rs:1:14 | LL | fn foo(Option, String) {} - | ^ + | ^ expected one of 9 possible tokens | -help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: Option, String) {} + | +++++ +help: if this is a type, explicitly ignore the parameter name | -LL | fn foo(Option::, String) {} - | ++ +LL | fn foo(_: Option, String) {} + | ++ error: expected one of `:`, `@`, or `|`, found `)` --> $DIR/issue-34264.rs:1:27 diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs index ad25d334507fc..ea76dc8742b9b 100644 --- a/tests/ui/suggestions/issue-64252-self-type.rs +++ b/tests/ui/suggestions/issue-64252-self-type.rs @@ -1,12 +1,11 @@ // This test checks that a suggestion to add a `self: ` parameter name is provided // to functions where this is applicable. -pub fn foo(Box) { } //~ ERROR generic args in patterns require the turbofish syntax - +pub fn foo(Box) { } //~ ERROR expected one of struct Bar; impl Bar { - fn bar(Box) { } //~ ERROR generic args in patterns require the turbofish syntax + fn bar(Box) { } //~ ERROR expected one of } fn main() { } diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr index ba5c2da241500..dd83d6a1cb291 100644 --- a/tests/ui/suggestions/issue-64252-self-type.stderr +++ b/tests/ui/suggestions/issue-64252-self-type.stderr @@ -1,24 +1,34 @@ -error: generic args in patterns require the turbofish syntax +error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` --> $DIR/issue-64252-self-type.rs:4:15 | LL | pub fn foo(Box) { } - | ^ + | ^ expected one of 9 possible tokens | -help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name | -LL | pub fn foo(Box::) { } - | ++ +LL | pub fn foo(self: Box) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | pub fn foo(_: Box) { } + | ++ -error: generic args in patterns require the turbofish syntax - --> $DIR/issue-64252-self-type.rs:9:15 +error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` + --> $DIR/issue-64252-self-type.rs:8:15 | LL | fn bar(Box) { } - | ^ + | ^ expected one of 9 possible tokens + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name | -help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments +LL | fn bar(self: Box) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name | -LL | fn bar(Box::) { } - | ++ +LL | fn bar(_: Box) { } + | ++ error: aborting due to 2 previous errors From f5243d2bfc9c8982523d443e960f8b8c54f6cd73 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Thu, 3 Aug 2023 00:13:41 +0800 Subject: [PATCH 3/6] Fix rustfmt dep --- src/tools/rustfmt/src/parse/macros/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 67f3985926e2f..7a802f7a88e06 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -56,7 +56,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { ); parse_macro_arg!( Pat, - |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None, None), |x: ptr::P| Some(x) ); // `parse_item` returns `Option>`. From 41e85c3d2369ebc44c19c6009a061b64d43672ee Mon Sep 17 00:00:00 2001 From: r0cky Date: Thu, 3 Aug 2023 05:18:19 +0000 Subject: [PATCH 4/6] Apply suggestions --- compiler/rustc_parse/src/parser/pat.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 615ef28db085d..5803d0c1c0524 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -139,7 +139,7 @@ impl<'a> Parser<'a> { }; // Parse the first pattern (`p_0`). - let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc.clone())?; + let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc)?; if rc == RecoverComma::Yes { self.maybe_recover_unexpected_comma(first_pat.span, rt)?; } @@ -813,7 +813,9 @@ impl<'a> Parser<'a> { | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. | token::ModSep // A tuple / struct variant pattern. | token::Not)) // A macro expanding to a pattern. - && !(self.look_ahead(1, |t| t.kind == token::Lt) && self.look_ahead(2, |t| t.can_begin_type())) // May suggest the turbofish syntax for generics, only valid for recoveries. + // May suggest the turbofish syntax for generics, only valid for recoveries. + && !(self.look_ahead(1, |t| t.kind == token::Lt) + && self.look_ahead(2, |t| t.can_begin_type())) } /// Parses `ident` or `ident @ pat`. From 8c8af6cf99d6a54ece11d21c15e909aef2b60552 Mon Sep 17 00:00:00 2001 From: r0cky Date: Thu, 3 Aug 2023 08:56:31 +0000 Subject: [PATCH 5/6] Avoid too many expected symbols and reduce `None`s --- compiler/rustc_parse/src/parser/attr.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 6 +-- compiler/rustc_parse/src/parser/item.rs | 6 +-- compiler/rustc_parse/src/parser/mod.rs | 6 +-- .../rustc_parse/src/parser/nonterminal.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 43 ++++++++++++------- compiler/rustc_parse/src/parser/path.rs | 33 +++----------- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 6 +-- tests/ui/span/issue-34264.stderr | 4 +- .../suggestions/issue-64252-self-type.stderr | 8 ++-- 12 files changed, 58 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 1271bce799d5c..ee0abba1c1753 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, None)?; + let path = this.parse_path(PathStyle::Mod)?; 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, None)?; + let path = self.parse_path(PathStyle::Mod)?; 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 8bc4433a9653a..5fa4f7902d624 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, None)?; + self.parse_path_segments(&mut path.segments, T::PATH_STYLE, 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)); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6dafb8b999b2f..0e19a67a8413a 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, None) { + match self.parse_path(PathStyle::Expr) { 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, None)?; + let mut seg = self.parse_path_segment(PathStyle::Expr, 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)?) + (None, self.parse_path(PathStyle::Expr)?) }; // `!`, as an operator, is prefix, so we know this isn't that. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index d3f756139def3..1301ed3e3882e 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, None)?; // `foo::bar` + let path = self.parse_path(PathStyle::Mod)?; // `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, None)?; + prefix = self.parse_path(PathStyle::Mod)?; 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, None)?; + self.parse_path_segments(&mut prefix.segments, PathStyle::Mod, 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 2af0caa1bdaf7..37b4c371c94b4 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, None)?; // `path` + let path = self.parse_path(PathStyle::Mod)?; // `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, None)?; // `crate`/`super`/`self` + let path = self.parse_path(PathStyle::Mod)?; // `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, None)?; + let path = self.parse_path(PathStyle::Mod)?; 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 a09c1e4d7fde2..f5681532b3af7 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -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, None))?), + P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?), ), 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 5803d0c1c0524..8d68a3a50acae 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -2,10 +2,11 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken}; use crate::errors::{ self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, - ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, - InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect, - RemoveLet, RepeatedMutInPattern, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam, + ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax, + InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, + PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern, + TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, + UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, }; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -366,11 +367,11 @@ impl<'a> Parser<'a> { // Parse _ PatKind::Wild } else if self.eat_keyword(kw::Mut) { - self.parse_pat_ident_mut()? + self.parse_pat_ident_mut(syntax_loc)? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl))? + self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)? } else if self.eat_keyword(kw::Box) { self.parse_pat_box()? } else if self.check_inline_const(0) { @@ -392,7 +393,7 @@ impl<'a> Parser<'a> { // Parse `ident @ pat` // This can give false positives and parse nullary enums, // they are dealt with later in resolve. - self.parse_pat_ident(BindingAnnotation::NONE)? + self.parse_pat_ident(BindingAnnotation::NONE, syntax_loc)? } else if self.is_start_of_pat_with_path() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -401,7 +402,7 @@ impl<'a> Parser<'a> { (Some(qself), path) } else { // Parse an unqualified path - (None, self.parse_path(PathStyle::Pat, syntax_loc)?) + (None, self.parse_path(PathStyle::Pat)?) }; let span = lo.to(self.prev_token.span); @@ -574,12 +575,12 @@ impl<'a> Parser<'a> { } /// Parse a mutable binding with the `mut` token already eaten. - fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { + fn parse_pat_ident_mut(&mut self, syntax_loc: Option) -> PResult<'a, PatKind> { let mut_span = self.prev_token.span; if self.eat_keyword(kw::Ref) { self.sess.emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) }); - return self.parse_pat_ident(BindingAnnotation::REF_MUT); + return self.parse_pat_ident(BindingAnnotation::REF_MUT, syntax_loc); } self.recover_additional_muts(); @@ -784,7 +785,7 @@ impl<'a> Parser<'a> { (Some(qself), path) } else { // Parse an unqualified path - (None, self.parse_path(PathStyle::Pat, None)?) + (None, self.parse_path(PathStyle::Pat)?) }; let hi = self.prev_token.span; Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path))) @@ -813,16 +814,28 @@ impl<'a> Parser<'a> { | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern. | token::ModSep // A tuple / struct variant pattern. | token::Not)) // A macro expanding to a pattern. - // May suggest the turbofish syntax for generics, only valid for recoveries. - && !(self.look_ahead(1, |t| t.kind == token::Lt) - && self.look_ahead(2, |t| t.can_begin_type())) } /// Parses `ident` or `ident @ pat`. /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. - fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> { + fn parse_pat_ident( + &mut self, + binding_annotation: BindingAnnotation, + syntax_loc: Option, + ) -> PResult<'a, PatKind> { let ident = self.parse_ident()?; + + if !matches!(syntax_loc, Some(PatternLocation::FunctionParameter)) + && 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(), + })); + } + let sub = if self.eat(&token::At) { Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?) } else { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 0d5f48e424e2c..feb7e829caf68 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,7 +1,6 @@ -use super::pat::PatternLocation; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; -use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon}; +use crate::errors::PathSingleColon; use crate::{errors, maybe_whole}; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -80,7 +79,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, None)?; + path = self.parse_path(PathStyle::Type)?; path_span = path_lo.to(self.prev_token.span); } else { path_span = self.token.span.to(self.token.span); @@ -99,7 +98,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, None)?; + self.parse_path_segments(&mut path.segments, style, None)?; Ok(( qself, @@ -140,12 +139,8 @@ impl<'a> Parser<'a> { true } - pub(super) fn parse_path( - &mut self, - style: PathStyle, - syntax_loc: Option, - ) -> PResult<'a, Path> { - self.parse_path_inner(style, None, syntax_loc) + pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + self.parse_path_inner(style, None) } /// Parses simple paths. @@ -162,7 +157,6 @@ impl<'a> Parser<'a> { &mut self, style: PathStyle, ty_generics: Option<&Generics>, - syntax_loc: Option, ) -> 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: @@ -207,7 +201,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, syntax_loc)?; + self.parse_path_segments(&mut segments, style, ty_generics)?; Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None }) } @@ -216,10 +210,9 @@ impl<'a> Parser<'a> { segments: &mut ThinVec, style: PathStyle, ty_generics: Option<&Generics>, - syntax_loc: Option, ) -> PResult<'a, ()> { loop { - let segment = self.parse_path_segment(style, ty_generics, syntax_loc)?; + let segment = self.parse_path_segment(style, ty_generics)?; 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), @@ -274,7 +267,6 @@ impl<'a> Parser<'a> { &mut self, style: PathStyle, ty_generics: Option<&Generics>, - syntax_loc: Option, ) -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; let is_args_start = |token: &Token| { @@ -294,17 +286,6 @@ 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 diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2c08e984be578..9fcf51a04ec05 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, None)?; + let path = this.parse_path(PathStyle::Expr)?; 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 8be84c7d46224..3bb50b05aa346 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, None)?; + let path = self.parse_path(PathStyle::Type)?; 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, None)?; + let path = self.parse_path_inner(PathStyle::Type, ty_generics)?; 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, None)? + self.parse_path(PathStyle::Type)? }; if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) { diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr index 8c639d5513b53..f0dea66f6128d 100644 --- a/tests/ui/span/issue-34264.stderr +++ b/tests/ui/span/issue-34264.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-34264.rs:1:14 | LL | fn foo(Option, String) {} - | ^ expected one of 9 possible tokens + | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this is a `self` type, give it a parameter name diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr index dd83d6a1cb291..dbef39faeadf6 100644 --- a/tests/ui/suggestions/issue-64252-self-type.stderr +++ b/tests/ui/suggestions/issue-64252-self-type.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-64252-self-type.rs:4:15 | LL | pub fn foo(Box) { } - | ^ expected one of 9 possible tokens + | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this is a `self` type, give it a parameter name @@ -14,11 +14,11 @@ help: if this is a type, explicitly ignore the parameter name LL | pub fn foo(_: Box) { } | ++ -error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<` +error: expected one of `:`, `@`, or `|`, found `<` --> $DIR/issue-64252-self-type.rs:8:15 | LL | fn bar(Box) { } - | ^ expected one of 9 possible tokens + | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) help: if this is a `self` type, give it a parameter name From dce7e87b1646fd5f4f7908fcd0aa1060c5189d44 Mon Sep 17 00:00:00 2001 From: r0cky Date: Thu, 3 Aug 2023 10:34:57 +0000 Subject: [PATCH 6/6] Reduce arbitrary self type suggestions --- .../rustc_parse/src/parser/diagnostics.rs | 18 +++-------------- .../anon-params-denied-2018.stderr | 20 ++++++------------- tests/ui/suggestions/issue-64252-self-type.rs | 7 +++++-- .../suggestions/issue-64252-self-type.stderr | 2 +- 4 files changed, 15 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 5fa4f7902d624..00ffa7de2ff62 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -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, maybe_name) = + let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) = match pat.kind { PatKind::Ident(_, ident, _) => ( ident, @@ -2029,7 +2029,6 @@ 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) @@ -2046,22 +2045,11 @@ 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() { @@ -2089,7 +2077,7 @@ impl<'a> Parser<'a> { } // Avoid suggesting that `fn foo(HashMap)` is fixed with a change to // `fn foo(HashMap: TypeName)`. - if self.token != token::Lt && maybe_name { + if self.token != token::Lt { err.span_suggestion( param_span, "if this is a parameter name, give it a type", diff --git a/tests/ui/anon-params/anon-params-denied-2018.stderr b/tests/ui/anon-params/anon-params-denied-2018.stderr index ede0e70cd7100..bb60c898e8122 100644 --- a/tests/ui/anon-params/anon-params-denied-2018.stderr +++ b/tests/ui/anon-params/anon-params-denied-2018.stderr @@ -45,14 +45,10 @@ LL | fn foo_with_qualified_path(::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name - | -LL | fn foo_with_qualified_path(self: ::Baz); - | +++++ -help: if this is a type, explicitly ignore the parameter name +help: explicitly ignore the parameter name | LL | fn foo_with_qualified_path(_: ::Baz); - | ++ + | ~~~~~~~~~~~~~~~~~~ error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:15:56 @@ -73,14 +69,10 @@ LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a `self` type, give it a parameter name - | -LL | fn foo_with_multiple_qualified_paths(self: ::Baz, ::Baz); - | +++++ -help: if this is a type, explicitly ignore the parameter name +help: explicitly ignore the parameter name | LL | fn foo_with_multiple_qualified_paths(_: ::Baz, ::Baz); - | ++ + | ~~~~~~~~~~~~~~~~~~ error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` --> $DIR/anon-params-denied-2018.rs:18:74 @@ -89,10 +81,10 @@ LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); | ^ expected one of 8 possible tokens | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) -help: if this is a type, explicitly ignore the parameter name +help: explicitly ignore the parameter name | LL | fn foo_with_multiple_qualified_paths(::Baz, _: ::Baz); - | ++ + | ~~~~~~~~~~~~~~~~~~ error: expected one of `:`, `@`, or `|`, found `,` --> $DIR/anon-params-denied-2018.rs:22:36 diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs index ea76dc8742b9b..128d5e85c22c8 100644 --- a/tests/ui/suggestions/issue-64252-self-type.rs +++ b/tests/ui/suggestions/issue-64252-self-type.rs @@ -1,11 +1,14 @@ // This test checks that a suggestion to add a `self: ` parameter name is provided // to functions where this is applicable. -pub fn foo(Box) { } //~ ERROR expected one of +pub fn foo(Box) { } +//~^ ERROR expected one of `:`, `@`, or `|`, found `<` + struct Bar; impl Bar { - fn bar(Box) { } //~ ERROR expected one of + fn bar(Box) { } + //~^ ERROR expected one of `:`, `@`, or `|`, found `<` } fn main() { } diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr index dbef39faeadf6..c3418dab0e8af 100644 --- a/tests/ui/suggestions/issue-64252-self-type.stderr +++ b/tests/ui/suggestions/issue-64252-self-type.stderr @@ -15,7 +15,7 @@ LL | pub fn foo(_: Box) { } | ++ error: expected one of `:`, `@`, or `|`, found `<` - --> $DIR/issue-64252-self-type.rs:8:15 + --> $DIR/issue-64252-self-type.rs:10:15 | LL | fn bar(Box) { } | ^ expected one of `:`, `@`, or `|`