Rollup merge of #114300 - MU001999:fix/turbofish-pat, r=estebank
Suggests turbofish in patterns Fixes #114112 r? ```@estebank```
This commit is contained in:
commit
51d1dacdc2
17 changed files with 125 additions and 42 deletions
|
@ -272,6 +272,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
|
||||||
parse_function_body_equals_expr = function body cannot be `= expression;`
|
parse_function_body_equals_expr = function body cannot be `= expression;`
|
||||||
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
.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
|
parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
|
||||||
.suggestion = surround the type parameters with angle brackets
|
.suggestion = surround the type parameters with angle brackets
|
||||||
|
|
||||||
|
|
|
@ -2738,3 +2738,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg {
|
||||||
#[suggestion_part(code = "")]
|
#[suggestion_part(code = "")]
|
||||||
pub right: Span,
|
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,
|
||||||
|
}
|
||||||
|
|
|
@ -2107,7 +2107,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()?;
|
||||||
|
|
||||||
|
@ -2515,7 +2515,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();
|
||||||
}
|
}
|
||||||
|
@ -2779,7 +2779,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(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -2,10 +2,11 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
|
self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
|
||||||
DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
|
DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
|
||||||
ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
|
ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
|
||||||
InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect,
|
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
|
||||||
RemoveLet, RepeatedMutInPattern, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
|
PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
|
||||||
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
|
||||||
|
UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
||||||
UnexpectedVertVertInPattern,
|
UnexpectedVertVertInPattern,
|
||||||
};
|
};
|
||||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||||
|
@ -80,7 +81,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 +93,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 +116,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 +127,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 +140,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)?;
|
||||||
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 +179,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 +215,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 +327,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);
|
||||||
|
@ -358,11 +367,11 @@ impl<'a> Parser<'a> {
|
||||||
// Parse _
|
// Parse _
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
} else if self.eat_keyword(kw::Mut) {
|
} 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) {
|
} else if self.eat_keyword(kw::Ref) {
|
||||||
// Parse ref ident @ pat / ref mut ident @ pat
|
// Parse ref ident @ pat / ref mut ident @ pat
|
||||||
let mutbl = self.parse_mutability();
|
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) {
|
} else if self.eat_keyword(kw::Box) {
|
||||||
self.parse_pat_box()?
|
self.parse_pat_box()?
|
||||||
} else if self.check_inline_const(0) {
|
} else if self.check_inline_const(0) {
|
||||||
|
@ -384,7 +393,7 @@ impl<'a> Parser<'a> {
|
||||||
// Parse `ident @ pat`
|
// Parse `ident @ pat`
|
||||||
// This can give false positives and parse nullary enums,
|
// This can give false positives and parse nullary enums,
|
||||||
// they are dealt with later in resolve.
|
// 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() {
|
} else if self.is_start_of_pat_with_path() {
|
||||||
// Parse pattern starting with a path
|
// Parse pattern starting with a path
|
||||||
let (qself, path) = if self.eat_lt() {
|
let (qself, path) = if self.eat_lt() {
|
||||||
|
@ -485,7 +494,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 +550,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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,12 +575,12 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a mutable binding with the `mut` token already eaten.
|
/// 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<PatternLocation>) -> PResult<'a, PatKind> {
|
||||||
let mut_span = self.prev_token.span;
|
let mut_span = self.prev_token.span;
|
||||||
|
|
||||||
if self.eat_keyword(kw::Ref) {
|
if self.eat_keyword(kw::Ref) {
|
||||||
self.sess.emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) });
|
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();
|
self.recover_additional_muts();
|
||||||
|
@ -584,7 +593,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
|
||||||
|
@ -810,10 +819,25 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses `ident` or `ident @ pat`.
|
/// Parses `ident` or `ident @ pat`.
|
||||||
/// Used by the copy foo and ref foo patterns to give a good
|
/// Used by the copy foo and ref foo patterns to give a good
|
||||||
/// error message when parsing mistakes like `ref foo(a, b)`.
|
/// 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<PatternLocation>,
|
||||||
|
) -> PResult<'a, PatKind> {
|
||||||
let ident = self.parse_ident()?;
|
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) {
|
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
|
||||||
};
|
};
|
||||||
|
@ -902,14 +926,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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||||
);
|
);
|
||||||
parse_macro_arg!(
|
parse_macro_arg!(
|
||||||
Pat,
|
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<ast::Pat>| Some(x)
|
|x: ptr::P<ast::Pat>| Some(x)
|
||||||
);
|
);
|
||||||
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
||||||
|
|
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
enum E<T> {
|
||||||
|
A(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match E::<i32>::A(1) {
|
||||||
|
E<i32>::A(v) => { //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
|
println!("{v:?}");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
error: generic args in patterns require the turbofish syntax
|
||||||
|
--> $DIR/issue-114112.rs:7:10
|
||||||
|
|
|
||||||
|
LL | E<i32>::A(v) => {
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
|
||||||
|
LL | E::<i32>::A(v) => {
|
||||||
|
| ++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let caller<F> = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
let caller<F> = |f: F| //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
where F: Fn() -> i32
|
where F: Fn() -> i32
|
||||||
{
|
{
|
||||||
let x = f();
|
let x = f();
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-22647.rs:2:15
|
||||||
|
|
|
|
||||||
LL | let caller<F> = |f: F|
|
LL | let caller<F> = |f: F|
|
||||||
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
|
| ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
|
||||||
|
LL | let caller::<F> = |f: F|
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ struct Foo<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bar() {
|
fn bar() {
|
||||||
let Foo<Vec<u8>> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
let Foo<Vec<u8>> //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
--> $DIR/issue-22712.rs:6:12
|
||||||
|
|
|
|
||||||
LL | let Foo<Vec<u8>>
|
LL | let Foo<Vec<u8>>
|
||||||
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
|
| ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
|
||||||
|
LL | let Foo::<Vec<u8>>
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@ struct Foo<T>(T, T);
|
||||||
impl<T> Foo<T> {
|
impl<T> Foo<T> {
|
||||||
fn foo(&self) {
|
fn foo(&self) {
|
||||||
match *self {
|
match *self {
|
||||||
Foo<T>(x, y) => {
|
Foo<T>(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
//~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
|
||||||
println!("Goodbye, World!")
|
println!("Goodbye, World!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
--> $DIR/pat-lt-bracket-3.rs:6:16
|
||||||
|
|
|
|
||||||
LL | Foo<T>(x, y) => {
|
LL | Foo<T>(x, y) => {
|
||||||
| ^ expected one of `=>`, `@`, `if`, or `|`
|
| ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
|
||||||
|
LL | Foo::<T>(x, y) => {
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ enum BtNode {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let y = match 10 {
|
let y = match 10 {
|
||||||
Foo<T>::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
Foo<T>::A(value) => value, //~ ERROR generic args in patterns require the turbofish syntax
|
||||||
Foo<T>::B => 7,
|
Foo<T>::B => 7,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
--> $DIR/pat-lt-bracket-4.rs:8:12
|
||||||
|
|
|
|
||||||
LL | Foo<T>::A(value) => value,
|
LL | Foo<T>::A(value) => value,
|
||||||
| ^ expected one of `=>`, `@`, `if`, or `|`
|
| ^
|
||||||
|
|
|
||||||
|
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||||
|
|
|
||||||
|
LL | Foo::<T>::A(value) => value,
|
||||||
|
| ++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue