@@ -2,10 +2,11 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken};
22use crate :: errors:: {
33 self , AmbiguousRangePattern , DotDotDotForRemainingFields , DotDotDotRangeToPatternNotAllowed ,
44 DotDotDotRestPattern , EnumPatternInsteadOfIdentifier , ExpectedBindingLeftOfAt ,
5- ExpectedCommaAfterPatternField , InclusiveRangeExtraEquals , InclusiveRangeMatchArrow ,
6- InclusiveRangeNoEnd , InvalidMutInPattern , PatternOnWrongSideOfAt , RefMutOrderIncorrect ,
7- RemoveLet , RepeatedMutInPattern , TopLevelOrPatternNotAllowed , TopLevelOrPatternNotAllowedSugg ,
8- TrailingVertNotAllowed , UnexpectedLifetimeInPattern , UnexpectedVertVertBeforeFunctionParam ,
5+ ExpectedCommaAfterPatternField , GenericArgsInPatRequireTurbofishSyntax ,
6+ InclusiveRangeExtraEquals , InclusiveRangeMatchArrow , InclusiveRangeNoEnd , InvalidMutInPattern ,
7+ PatternOnWrongSideOfAt , RefMutOrderIncorrect , RemoveLet , RepeatedMutInPattern ,
8+ TopLevelOrPatternNotAllowed , TopLevelOrPatternNotAllowedSugg , TrailingVertNotAllowed ,
9+ UnexpectedLifetimeInPattern , UnexpectedVertVertBeforeFunctionParam ,
910 UnexpectedVertVertInPattern ,
1011} ;
1112use crate :: { maybe_recover_from_interpolated_ty_qpath, maybe_whole} ;
@@ -80,7 +81,8 @@ enum EatOrResult {
8081}
8182
8283/// The syntax location of a given pattern. Used for diagnostics.
83- pub ( super ) enum PatternLocation {
84+ #[ derive( Clone , Copy ) ]
85+ pub enum PatternLocation {
8486 LetBinding ,
8587 FunctionParameter ,
8688}
@@ -91,8 +93,12 @@ impl<'a> Parser<'a> {
9193 /// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
9294 /// at the top level. Used when parsing the parameters of lambda expressions,
9395 /// functions, function pointers, and `pat` macro fragments.
94- pub fn parse_pat_no_top_alt ( & mut self , expected : Option < Expected > ) -> PResult < ' a , P < Pat > > {
95- self . parse_pat_with_range_pat ( true , expected)
96+ pub fn parse_pat_no_top_alt (
97+ & mut self ,
98+ expected : Option < Expected > ,
99+ syntax_loc : Option < PatternLocation > ,
100+ ) -> PResult < ' a , P < Pat > > {
101+ self . parse_pat_with_range_pat ( true , expected, syntax_loc)
96102 }
97103
98104 /// Parses a pattern.
@@ -110,7 +116,7 @@ impl<'a> Parser<'a> {
110116 ra : RecoverColon ,
111117 rt : CommaRecoveryMode ,
112118 ) -> PResult < ' a , P < Pat > > {
113- self . parse_pat_allow_top_alt_inner ( expected, rc, ra, rt) . map ( |( pat, _) | pat)
119+ self . parse_pat_allow_top_alt_inner ( expected, rc, ra, rt, None ) . map ( |( pat, _) | pat)
114120 }
115121
116122 /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@@ -121,6 +127,7 @@ impl<'a> Parser<'a> {
121127 rc : RecoverComma ,
122128 ra : RecoverColon ,
123129 rt : CommaRecoveryMode ,
130+ syntax_loc : Option < PatternLocation > ,
124131 ) -> PResult < ' a , ( P < Pat > , bool ) > {
125132 // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
126133 // suggestions (which bothers rustfix).
@@ -133,7 +140,7 @@ impl<'a> Parser<'a> {
133140 } ;
134141
135142 // Parse the first pattern (`p_0`).
136- let mut first_pat = self . parse_pat_no_top_alt ( expected) ?;
143+ let mut first_pat = self . parse_pat_no_top_alt ( expected, syntax_loc ) ?;
137144 if rc == RecoverComma :: Yes {
138145 self . maybe_recover_unexpected_comma ( first_pat. span , rt) ?;
139146 }
@@ -172,7 +179,7 @@ impl<'a> Parser<'a> {
172179 break ;
173180 }
174181 }
175- let pat = self . parse_pat_no_top_alt ( expected) . map_err ( |mut err| {
182+ let pat = self . parse_pat_no_top_alt ( expected, syntax_loc ) . map_err ( |mut err| {
176183 err. span_label ( lo, WHILE_PARSING_OR_MSG ) ;
177184 err
178185 } ) ?;
@@ -208,6 +215,7 @@ impl<'a> Parser<'a> {
208215 rc,
209216 RecoverColon :: No ,
210217 CommaRecoveryMode :: LikelyTuple ,
218+ Some ( syntax_loc) ,
211219 ) ?;
212220 let colon = self . eat ( & token:: Colon ) ;
213221
@@ -319,6 +327,7 @@ impl<'a> Parser<'a> {
319327 & mut self ,
320328 allow_range_pat : bool ,
321329 expected : Option < Expected > ,
330+ syntax_loc : Option < PatternLocation > ,
322331 ) -> PResult < ' a , P < Pat > > {
323332 maybe_recover_from_interpolated_ty_qpath ! ( self , true ) ;
324333 maybe_whole ! ( self , NtPat , |x| x) ;
@@ -358,11 +367,11 @@ impl<'a> Parser<'a> {
358367 // Parse _
359368 PatKind :: Wild
360369 } else if self . eat_keyword ( kw:: Mut ) {
361- self . parse_pat_ident_mut ( ) ?
370+ self . parse_pat_ident_mut ( syntax_loc ) ?
362371 } else if self . eat_keyword ( kw:: Ref ) {
363372 // Parse ref ident @ pat / ref mut ident @ pat
364373 let mutbl = self . parse_mutability ( ) ;
365- self . parse_pat_ident ( BindingAnnotation ( ByRef :: Yes , mutbl) ) ?
374+ self . parse_pat_ident ( BindingAnnotation ( ByRef :: Yes , mutbl) , syntax_loc ) ?
366375 } else if self . eat_keyword ( kw:: Box ) {
367376 self . parse_pat_box ( ) ?
368377 } else if self . check_inline_const ( 0 ) {
@@ -384,7 +393,7 @@ impl<'a> Parser<'a> {
384393 // Parse `ident @ pat`
385394 // This can give false positives and parse nullary enums,
386395 // they are dealt with later in resolve.
387- self . parse_pat_ident ( BindingAnnotation :: NONE ) ?
396+ self . parse_pat_ident ( BindingAnnotation :: NONE , syntax_loc ) ?
388397 } else if self . is_start_of_pat_with_path ( ) {
389398 // Parse pattern starting with a path
390399 let ( qself, path) = if self . eat_lt ( ) {
@@ -485,7 +494,7 @@ impl<'a> Parser<'a> {
485494
486495 // At this point we attempt to parse `@ $pat_rhs` and emit an error.
487496 self . bump ( ) ; // `@`
488- let mut rhs = self . parse_pat_no_top_alt ( None ) ?;
497+ let mut rhs = self . parse_pat_no_top_alt ( None , None ) ?;
489498 let whole_span = lhs. span . to ( rhs. span ) ;
490499
491500 if let PatKind :: Ident ( _, _, sub @ None ) = & mut rhs. kind {
@@ -541,7 +550,7 @@ impl<'a> Parser<'a> {
541550 }
542551
543552 let mutbl = self . parse_mutability ( ) ;
544- let subpat = self . parse_pat_with_range_pat ( false , expected) ?;
553+ let subpat = self . parse_pat_with_range_pat ( false , expected, None ) ?;
545554 Ok ( PatKind :: Ref ( subpat, mutbl) )
546555 }
547556
@@ -566,12 +575,12 @@ impl<'a> Parser<'a> {
566575 }
567576
568577 /// Parse a mutable binding with the `mut` token already eaten.
569- fn parse_pat_ident_mut ( & mut self ) -> PResult < ' a , PatKind > {
578+ fn parse_pat_ident_mut ( & mut self , syntax_loc : Option < PatternLocation > ) -> PResult < ' a , PatKind > {
570579 let mut_span = self . prev_token . span ;
571580
572581 if self . eat_keyword ( kw:: Ref ) {
573582 self . sess . emit_err ( RefMutOrderIncorrect { span : mut_span. to ( self . prev_token . span ) } ) ;
574- return self . parse_pat_ident ( BindingAnnotation :: REF_MUT ) ;
583+ return self . parse_pat_ident ( BindingAnnotation :: REF_MUT , syntax_loc ) ;
575584 }
576585
577586 self . recover_additional_muts ( ) ;
@@ -584,7 +593,7 @@ impl<'a> Parser<'a> {
584593 }
585594
586595 // Parse the pattern we hope to be an identifier.
587- let mut pat = self . parse_pat_no_top_alt ( Some ( Expected :: Identifier ) ) ?;
596+ let mut pat = self . parse_pat_no_top_alt ( Some ( Expected :: Identifier ) , None ) ?;
588597
589598 // If we don't have `mut $ident (@ pat)?`, error.
590599 if let PatKind :: Ident ( BindingAnnotation ( ByRef :: No , m @ Mutability :: Not ) , ..) = & mut pat. kind
@@ -810,10 +819,25 @@ impl<'a> Parser<'a> {
810819 /// Parses `ident` or `ident @ pat`.
811820 /// Used by the copy foo and ref foo patterns to give a good
812821 /// error message when parsing mistakes like `ref foo(a, b)`.
813- fn parse_pat_ident ( & mut self , binding_annotation : BindingAnnotation ) -> PResult < ' a , PatKind > {
822+ fn parse_pat_ident (
823+ & mut self ,
824+ binding_annotation : BindingAnnotation ,
825+ syntax_loc : Option < PatternLocation > ,
826+ ) -> PResult < ' a , PatKind > {
814827 let ident = self . parse_ident ( ) ?;
828+
829+ if !matches ! ( syntax_loc, Some ( PatternLocation :: FunctionParameter ) )
830+ && self . check_noexpect ( & token:: Lt )
831+ && self . look_ahead ( 1 , |t| t. can_begin_type ( ) )
832+ {
833+ return Err ( self . sess . create_err ( GenericArgsInPatRequireTurbofishSyntax {
834+ span : self . token . span ,
835+ suggest_turbofish : self . token . span . shrink_to_lo ( ) ,
836+ } ) ) ;
837+ }
838+
815839 let sub = if self . eat ( & token:: At ) {
816- Some ( self . parse_pat_no_top_alt ( Some ( Expected :: BindingPattern ) ) ?)
840+ Some ( self . parse_pat_no_top_alt ( Some ( Expected :: BindingPattern ) , None ) ?)
817841 } else {
818842 None
819843 } ;
@@ -902,14 +926,14 @@ impl<'a> Parser<'a> {
902926 // We cannot use `parse_pat_ident()` since it will complain `box`
903927 // is not an identifier.
904928 let sub = if self . eat ( & token:: At ) {
905- Some ( self . parse_pat_no_top_alt ( Some ( Expected :: BindingPattern ) ) ?)
929+ Some ( self . parse_pat_no_top_alt ( Some ( Expected :: BindingPattern ) , None ) ?)
906930 } else {
907931 None
908932 } ;
909933
910934 Ok ( PatKind :: Ident ( BindingAnnotation :: NONE , Ident :: new ( kw:: Box , box_span) , sub) )
911935 } else {
912- let pat = self . parse_pat_with_range_pat ( false , None ) ?;
936+ let pat = self . parse_pat_with_range_pat ( false , None , None ) ?;
913937 self . sess . gated_spans . gate ( sym:: box_patterns, box_span. to ( self . prev_token . span ) ) ;
914938 Ok ( PatKind :: Box ( pat) )
915939 }
0 commit comments