1
Fork 0

Keep the suggestion for wrong arbitrary self types

This commit is contained in:
Mu001999 2023-08-03 00:00:56 +08:00
parent 049c728c60
commit 89b2fe7750
15 changed files with 133 additions and 80 deletions

View file

@ -260,7 +260,7 @@ impl<'a> Parser<'a> {
item item
} else { } else {
let do_parse = |this: &mut Self| { 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()?; let args = this.parse_attr_args()?;
Ok(ast::AttrItem { path, args, tokens: None }) Ok(ast::AttrItem { path, args, tokens: None })
}; };
@ -387,7 +387,7 @@ impl<'a> Parser<'a> {
} }
let lo = self.token.span; 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 kind = self.parse_meta_item_kind()?;
let span = lo.to(self.prev_token.span); let span = lo.to(self.prev_token.span);
Ok(ast::MetaItem { path, kind, span }) Ok(ast::MetaItem { path, kind, span })

View file

@ -1579,7 +1579,7 @@ impl<'a> Parser<'a> {
self.expect(&token::ModSep)?; self.expect(&token::ModSep)?;
let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None }; 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); 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)); 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 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 { match pat.kind {
PatKind::Ident(_, ident, _) => ( PatKind::Ident(_, ident, _) => (
ident, ident,
@ -2029,6 +2029,7 @@ impl<'a> Parser<'a> {
pat.span.shrink_to_lo(), pat.span.shrink_to_lo(),
pat.span.shrink_to_hi(), pat.span.shrink_to_hi(),
pat.span.shrink_to_lo(), pat.span.shrink_to_lo(),
true,
), ),
// Also catches `fn foo(&a)`. // Also catches `fn foo(&a)`.
PatKind::Ref(ref inner_pat, mutab) PatKind::Ref(ref inner_pat, mutab)
@ -2045,11 +2046,22 @@ impl<'a> Parser<'a> {
pat.span.shrink_to_lo(), pat.span.shrink_to_lo(),
pat.span, pat.span,
pat.span.shrink_to_lo(), pat.span.shrink_to_lo(),
true,
) )
} }
_ => unreachable!(), _ => 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. // Otherwise, try to get a type and emit a suggestion.
if let Some(ty) = pat.to_ty() { 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 // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
// `fn foo(HashMap: TypeName<u32>)`. // `fn foo(HashMap: TypeName<u32>)`.
if self.token != token::Lt { if self.token != token::Lt && maybe_name {
err.span_suggestion( err.span_suggestion(
param_span, param_span,
"if this is a parameter name, give it a type", "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>)> { 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)?; self.expect(&token::Colon)?;
let ty = self.parse_ty()?; let ty = self.parse_ty()?;
@ -2508,7 +2520,7 @@ impl<'a> Parser<'a> {
// Skip the `:`. // Skip the `:`.
snapshot_pat.bump(); snapshot_pat.bump();
snapshot_type.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) => { Err(inner_err) => {
inner_err.cancel(); inner_err.cancel();
} }
@ -2772,7 +2784,7 @@ impl<'a> Parser<'a> {
/// sequence of patterns until `)` is reached. /// sequence of patterns until `)` is reached.
fn skip_pat_list(&mut self) -> PResult<'a, ()> { fn skip_pat_list(&mut self) -> PResult<'a, ()> {
while !self.check(&token::CloseDelim(Delimiter::Parenthesis)) { 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) { if !self.eat(&token::Comma) {
return Ok(()); return Ok(());
} }

View file

@ -775,7 +775,7 @@ impl<'a> Parser<'a> {
_ => {} _ => {}
} }
match self.parse_path(PathStyle::Expr) { match self.parse_path(PathStyle::Expr, None) {
Ok(path) => { Ok(path) => {
let span_after_type = parser_snapshot_after_type.token.span; let span_after_type = parser_snapshot_after_type.token.span;
let expr = mk_expr( let expr = mk_expr(
@ -1314,7 +1314,7 @@ impl<'a> Parser<'a> {
} }
let fn_span_lo = self.token.span; 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_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
self.check_turbofish_missing_angle_brackets(&mut seg); self.check_turbofish_missing_angle_brackets(&mut seg);
@ -1544,7 +1544,7 @@ impl<'a> Parser<'a> {
})?; })?;
(Some(qself), path) (Some(qself), path)
} else { } 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. // `!`, 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 lo = self.token.span;
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { 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) { let ty = if this.eat(&token::Colon) {
this.parse_ty()? this.parse_ty()?
} else { } else {
@ -2781,7 +2781,7 @@ impl<'a> Parser<'a> {
return None; return None;
} }
let pre_pat_snapshot = self.create_snapshot_for_diagnostic(); 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) => { Ok(_pat) => {
if self.token.kind == token::FatArrow { if self.token.kind == token::FatArrow {
// Reached arm end. // Reached arm end.

View file

@ -452,7 +452,7 @@ impl<'a> Parser<'a> {
/// Parses an item macro, e.g., `item!();`. /// Parses an item macro, e.g., `item!();`.
fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { 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)?; // `!` self.expect(&token::Not)?; // `!`
match self.parse_delim_args() { match self.parse_delim_args() {
// `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
@ -976,7 +976,7 @@ impl<'a> Parser<'a> {
self.parse_use_tree_glob_or_nested()? self.parse_use_tree_glob_or_nested()?
} else { } else {
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` // `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) { if self.eat(&token::ModSep) {
self.parse_use_tree_glob_or_nested()? self.parse_use_tree_glob_or_nested()?
@ -987,7 +987,7 @@ impl<'a> Parser<'a> {
.emit_err(errors::SingleColonImportPath { span: self.prev_token.span }); .emit_err(errors::SingleColonImportPath { span: self.prev_token.span });
// We parse the rest of the path and append it to the original prefix. // 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); prefix.span = lo.to(self.prev_token.span);
} }

View file

@ -1413,7 +1413,7 @@ impl<'a> Parser<'a> {
// Parse `pub(in path)`. // Parse `pub(in path)`.
self.bump(); // `(` self.bump(); // `(`
self.bump(); // `in` 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))?; // `)` self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
let vis = VisibilityKind::Restricted { let vis = VisibilityKind::Restricted {
path: P(path), path: P(path),
@ -1430,7 +1430,7 @@ impl<'a> Parser<'a> {
{ {
// Parse `pub(crate)`, `pub(self)`, or `pub(super)`. // Parse `pub(crate)`, `pub(self)`, or `pub(super)`.
self.bump(); // `(` 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))?; // `)` self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
let vis = VisibilityKind::Restricted { let vis = VisibilityKind::Restricted {
path: P(path), 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 }` /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> { fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
self.bump(); // `(` self.bump(); // `(`
let path = self.parse_path(PathStyle::Mod)?; let path = self.parse_path(PathStyle::Mod, None)?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)` self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
let path_str = pprust::path_to_string(&path); let path_str = pprust::path_to_string(&path);

View file

@ -131,7 +131,7 @@ impl<'a> Parser<'a> {
}, },
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
token::NtPat(self.collect_tokens_no_attrs(|this| match kind { 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( NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
None, None,
RecoverComma::No, RecoverComma::No,
@ -168,7 +168,7 @@ impl<'a> Parser<'a> {
}.into_diagnostic(&self.sess.span_diagnostic)); }.into_diagnostic(&self.sess.span_diagnostic));
} }
NonterminalKind::Path => token::NtPath( 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::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
NonterminalKind::Vis => token::NtVis( NonterminalKind::Vis => token::NtVis(

View file

@ -80,7 +80,8 @@ enum EatOrResult {
} }
/// The syntax location of a given pattern. Used for diagnostics. /// The syntax location of a given pattern. Used for diagnostics.
pub(super) enum PatternLocation { #[derive(Clone, Copy)]
pub enum PatternLocation {
LetBinding, LetBinding,
FunctionParameter, FunctionParameter,
} }
@ -91,8 +92,12 @@ impl<'a> Parser<'a> {
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns /// 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, /// at the top level. Used when parsing the parameters of lambda expressions,
/// functions, function pointers, and `pat` macro fragments. /// functions, function pointers, and `pat` macro fragments.
pub fn parse_pat_no_top_alt(&mut self, expected: Option<Expected>) -> PResult<'a, P<Pat>> { pub fn parse_pat_no_top_alt(
self.parse_pat_with_range_pat(true, expected) &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. /// Parses a pattern.
@ -110,7 +115,7 @@ impl<'a> Parser<'a> {
ra: RecoverColon, ra: RecoverColon,
rt: CommaRecoveryMode, rt: CommaRecoveryMode,
) -> PResult<'a, P<Pat>> { ) -> 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 = /// 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, rc: RecoverComma,
ra: RecoverColon, ra: RecoverColon,
rt: CommaRecoveryMode, rt: CommaRecoveryMode,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, (P<Pat>, bool)> { ) -> PResult<'a, (P<Pat>, bool)> {
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
// suggestions (which bothers rustfix). // suggestions (which bothers rustfix).
@ -133,7 +139,7 @@ impl<'a> Parser<'a> {
}; };
// Parse the first pattern (`p_0`). // 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 { if rc == RecoverComma::Yes {
self.maybe_recover_unexpected_comma(first_pat.span, rt)?; self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
} }
@ -172,7 +178,7 @@ impl<'a> Parser<'a> {
break; 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.span_label(lo, WHILE_PARSING_OR_MSG);
err err
})?; })?;
@ -208,6 +214,7 @@ impl<'a> Parser<'a> {
rc, rc,
RecoverColon::No, RecoverColon::No,
CommaRecoveryMode::LikelyTuple, CommaRecoveryMode::LikelyTuple,
Some(syntax_loc),
)?; )?;
let colon = self.eat(&token::Colon); let colon = self.eat(&token::Colon);
@ -319,6 +326,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
allow_range_pat: bool, allow_range_pat: bool,
expected: Option<Expected>, expected: Option<Expected>,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, P<Pat>> { ) -> PResult<'a, P<Pat>> {
maybe_recover_from_interpolated_ty_qpath!(self, true); maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole!(self, NtPat, |x| x); maybe_whole!(self, NtPat, |x| x);
@ -393,7 +401,7 @@ impl<'a> Parser<'a> {
(Some(qself), path) (Some(qself), path)
} else { } else {
// Parse an unqualified path // 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); 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. // At this point we attempt to parse `@ $pat_rhs` and emit an error.
self.bump(); // `@` 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); let whole_span = lhs.span.to(rhs.span);
if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind { if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
@ -541,7 +549,7 @@ impl<'a> Parser<'a> {
} }
let mutbl = self.parse_mutability(); 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)) Ok(PatKind::Ref(subpat, mutbl))
} }
@ -584,7 +592,7 @@ impl<'a> Parser<'a> {
} }
// Parse the pattern we hope to be an identifier. // 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 we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
@ -776,7 +784,7 @@ impl<'a> Parser<'a> {
(Some(qself), path) (Some(qself), path)
} else { } else {
// Parse an unqualified path // Parse an unqualified path
(None, self.parse_path(PathStyle::Pat)?) (None, self.parse_path(PathStyle::Pat, None)?)
}; };
let hi = self.prev_token.span; let hi = self.prev_token.span;
Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path))) 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> { fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?; let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) { 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 { } else {
None None
}; };
@ -903,14 +911,14 @@ impl<'a> Parser<'a> {
// We cannot use `parse_pat_ident()` since it will complain `box` // We cannot use `parse_pat_ident()` since it will complain `box`
// is not an identifier. // is not an identifier.
let sub = if self.eat(&token::At) { 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 { } else {
None None
}; };
Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub)) Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
} else { } 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)); self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
Ok(PatKind::Box(pat)) Ok(PatKind::Box(pat))
} }

View file

@ -1,3 +1,4 @@
use super::pat::PatternLocation;
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType}; use super::{Parser, Restrictions, TokenType};
use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon}; use crate::errors::{GenericArgsInPatRequireTurbofishSyntax, PathSingleColon};
@ -79,7 +80,7 @@ impl<'a> Parser<'a> {
let (mut path, path_span); let (mut path, path_span);
if self.eat_keyword(kw::As) { if self.eat_keyword(kw::As) {
let path_lo = self.token.span; 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); path_span = path_lo.to(self.prev_token.span);
} else { } else {
path_span = self.token.span.to(self.token.span); 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() }); 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(( Ok((
qself, qself,
@ -139,8 +140,12 @@ impl<'a> Parser<'a> {
true true
} }
pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { pub(super) fn parse_path(
self.parse_path_inner(style, None) &mut self,
style: PathStyle,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, Path> {
self.parse_path_inner(style, None, syntax_loc)
} }
/// Parses simple paths. /// Parses simple paths.
@ -157,6 +162,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
style: PathStyle, style: PathStyle,
ty_generics: Option<&Generics>, ty_generics: Option<&Generics>,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, Path> { ) -> PResult<'a, Path> {
let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| { let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| {
// Ensure generic arguments don't end up in attribute paths, such as: // 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) { if self.eat(&token::ModSep) {
segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); 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 }) Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
} }
@ -210,9 +216,10 @@ impl<'a> Parser<'a> {
segments: &mut ThinVec<PathSegment>, segments: &mut ThinVec<PathSegment>,
style: PathStyle, style: PathStyle,
ty_generics: Option<&Generics>, ty_generics: Option<&Generics>,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
loop { 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() { if style.has_generic_ambiguity() {
// In order to check for trailing angle brackets, we must have finished // In order to check for trailing angle brackets, we must have finished
// recursing (`parse_path_segment` can indirectly call this function), // recursing (`parse_path_segment` can indirectly call this function),
@ -267,6 +274,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
style: PathStyle, style: PathStyle,
ty_generics: Option<&Generics>, ty_generics: Option<&Generics>,
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, PathSegment> { ) -> PResult<'a, PathSegment> {
let ident = self.parse_path_segment_ident()?; let ident = self.parse_path_segment_ident()?;
let is_args_start = |token: &Token| { let is_args_start = |token: &Token| {
@ -286,6 +294,17 @@ impl<'a> Parser<'a> {
is_args_start(&this.token) 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( Ok(
if style == PathStyle::Type && check_args_start(self) if style == PathStyle::Type && check_args_start(self)
|| style != PathStyle::Mod || style != PathStyle::Mod
@ -382,14 +401,6 @@ impl<'a> Parser<'a> {
}; };
PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID } 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 { } else {
// Generic arguments are not found. // Generic arguments are not found.
PathSegment::from_ident(ident) PathSegment::from_ident(ident)

View file

@ -149,7 +149,7 @@ impl<'a> Parser<'a> {
fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> { 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 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) { if this.eat(&token::Not) {
let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?; let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;

View file

@ -289,7 +289,7 @@ impl<'a> Parser<'a> {
recover_return_sign, recover_return_sign,
)? )?
} else { } 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(); let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)? self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
} }
@ -649,7 +649,7 @@ impl<'a> Parser<'a> {
ty_generics: Option<&Generics>, ty_generics: Option<&Generics>,
) -> PResult<'a, TyKind> { ) -> PResult<'a, TyKind> {
// Simple path // 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) { if self.eat(&token::Not) {
// Macro invocation in type position // Macro invocation in type position
Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? }))) Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
@ -865,7 +865,7 @@ impl<'a> Parser<'a> {
path path
} else { } else {
self.parse_path(PathStyle::Type)? self.parse_path(PathStyle::Type, None)?
}; };
if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) { if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {

View file

@ -45,10 +45,14 @@ LL | fn foo_with_qualified_path(<Bar as T>::Baz);
| ^ expected one of 8 possible tokens | ^ expected one of 8 possible tokens
| |
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685) = 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: <Bar as T>::Baz);
| +++++
help: if this is a type, explicitly ignore the parameter name
| |
LL | fn foo_with_qualified_path(_: <Bar as T>::Baz); LL | fn foo_with_qualified_path(_: <Bar as T>::Baz);
| ~~~~~~~~~~~~~~~~~~ | ++
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:15:56 --> $DIR/anon-params-denied-2018.rs:15:56
@ -69,10 +73,14 @@ LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
| ^ expected one of 8 possible tokens | ^ expected one of 8 possible tokens
| |
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685) = 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: <Bar as T>::Baz, <Bar as T>::Baz);
| +++++
help: if this is a type, explicitly ignore the parameter name
| |
LL | fn foo_with_multiple_qualified_paths(_: <Bar as T>::Baz, <Bar as T>::Baz); LL | fn foo_with_multiple_qualified_paths(_: <Bar as T>::Baz, <Bar as T>::Baz);
| ~~~~~~~~~~~~~~~~~~ | ++
error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
--> $DIR/anon-params-denied-2018.rs:18:74 --> $DIR/anon-params-denied-2018.rs:18:74
@ -81,10 +89,10 @@ LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, <Bar as T>::Baz);
| ^ expected one of 8 possible tokens | ^ expected one of 8 possible tokens
| |
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685) = 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(<Bar as T>::Baz, _: <Bar as T>::Baz); LL | fn foo_with_multiple_qualified_paths(<Bar as T>::Baz, _: <Bar as T>::Baz);
| ~~~~~~~~~~~~~~~~~~ | ++
error: expected one of `:`, `@`, or `|`, found `,` error: expected one of `:`, `@`, or `|`, found `,`
--> $DIR/anon-params-denied-2018.rs:22:36 --> $DIR/anon-params-denied-2018.rs:22:36

View file

@ -1,5 +1,5 @@
fn foo(Option<i32>, String) {} //~ ERROR expected one of fn foo(Option<i32>, 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 bar(x, y: usize) {} //~ ERROR expected one of
fn main() { fn main() {

View file

@ -1,12 +1,17 @@
error: generic args in patterns require the turbofish syntax error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<`
--> $DIR/issue-34264.rs:1:14 --> $DIR/issue-34264.rs:1:14
| |
LL | fn foo(Option<i32>, String) {} LL | fn foo(Option<i32>, 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(Option::<i32>, String) {} LL | fn foo(self: Option<i32>, String) {}
| +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn foo(_: Option<i32>, String) {}
| ++ | ++
error: expected one of `:`, `@`, or `|`, found `)` error: expected one of `:`, `@`, or `|`, found `)`

View file

@ -1,12 +1,11 @@
// This test checks that a suggestion to add a `self: ` parameter name is provided // This test checks that a suggestion to add a `self: ` parameter name is provided
// to functions where this is applicable. // to functions where this is applicable.
pub fn foo(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax pub fn foo(Box<Self>) { } //~ ERROR expected one of
struct Bar; struct Bar;
impl Bar { impl Bar {
fn bar(Box<Self>) { } //~ ERROR generic args in patterns require the turbofish syntax fn bar(Box<Self>) { } //~ ERROR expected one of
} }
fn main() { } fn main() { }

View file

@ -1,23 +1,33 @@
error: generic args in patterns require the turbofish syntax error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<`
--> $DIR/issue-64252-self-type.rs:4:15 --> $DIR/issue-64252-self-type.rs:4:15
| |
LL | pub fn foo(Box<Self>) { } LL | pub fn foo(Box<Self>) { }
| ^ | ^ 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::<Self>) { } LL | pub fn foo(self: Box<Self>) { }
| +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | pub fn foo(_: Box<Self>) { }
| ++ | ++
error: generic args in patterns require the turbofish syntax error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `<`
--> $DIR/issue-64252-self-type.rs:9:15 --> $DIR/issue-64252-self-type.rs:8:15
| |
LL | fn bar(Box<Self>) { } LL | fn bar(Box<Self>) { }
| ^ | ^ 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 bar(Box::<Self>) { } LL | fn bar(self: Box<Self>) { }
| +++++
help: if this is a type, explicitly ignore the parameter name
|
LL | fn bar(_: Box<Self>) { }
| ++ | ++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors