@@ -2,10 +2,11 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken};
2
2
use crate :: errors:: {
3
3
self , AmbiguousRangePattern , DotDotDotForRemainingFields , DotDotDotRangeToPatternNotAllowed ,
4
4
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 ,
9
10
UnexpectedVertVertInPattern ,
10
11
} ;
11
12
use crate :: { maybe_recover_from_interpolated_ty_qpath, maybe_whole} ;
@@ -80,7 +81,8 @@ enum EatOrResult {
80
81
}
81
82
82
83
/// The syntax location of a given pattern. Used for diagnostics.
83
- pub ( super ) enum PatternLocation {
84
+ #[ derive( Clone , Copy ) ]
85
+ pub enum PatternLocation {
84
86
LetBinding ,
85
87
FunctionParameter ,
86
88
}
@@ -91,8 +93,12 @@ impl<'a> Parser<'a> {
91
93
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
92
94
/// at the top level. Used when parsing the parameters of lambda expressions,
93
95
/// 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)
96
102
}
97
103
98
104
/// Parses a pattern.
@@ -110,7 +116,7 @@ impl<'a> Parser<'a> {
110
116
ra : RecoverColon ,
111
117
rt : CommaRecoveryMode ,
112
118
) -> 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)
114
120
}
115
121
116
122
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@@ -121,6 +127,7 @@ impl<'a> Parser<'a> {
121
127
rc : RecoverComma ,
122
128
ra : RecoverColon ,
123
129
rt : CommaRecoveryMode ,
130
+ syntax_loc : Option < PatternLocation > ,
124
131
) -> PResult < ' a , ( P < Pat > , bool ) > {
125
132
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
126
133
// suggestions (which bothers rustfix).
@@ -133,7 +140,7 @@ impl<'a> Parser<'a> {
133
140
} ;
134
141
135
142
// 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 ) ?;
137
144
if rc == RecoverComma :: Yes {
138
145
self . maybe_recover_unexpected_comma ( first_pat. span , rt) ?;
139
146
}
@@ -172,7 +179,7 @@ impl<'a> Parser<'a> {
172
179
break ;
173
180
}
174
181
}
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| {
176
183
err. span_label ( lo, WHILE_PARSING_OR_MSG ) ;
177
184
err
178
185
} ) ?;
@@ -208,6 +215,7 @@ impl<'a> Parser<'a> {
208
215
rc,
209
216
RecoverColon :: No ,
210
217
CommaRecoveryMode :: LikelyTuple ,
218
+ Some ( syntax_loc) ,
211
219
) ?;
212
220
let colon = self . eat ( & token:: Colon ) ;
213
221
@@ -319,6 +327,7 @@ impl<'a> Parser<'a> {
319
327
& mut self ,
320
328
allow_range_pat : bool ,
321
329
expected : Option < Expected > ,
330
+ syntax_loc : Option < PatternLocation > ,
322
331
) -> PResult < ' a , P < Pat > > {
323
332
maybe_recover_from_interpolated_ty_qpath ! ( self , true ) ;
324
333
maybe_whole ! ( self , NtPat , |x| x) ;
@@ -358,11 +367,11 @@ impl<'a> Parser<'a> {
358
367
// Parse _
359
368
PatKind :: Wild
360
369
} else if self . eat_keyword ( kw:: Mut ) {
361
- self . parse_pat_ident_mut ( ) ?
370
+ self . parse_pat_ident_mut ( syntax_loc ) ?
362
371
} else if self . eat_keyword ( kw:: Ref ) {
363
372
// Parse ref ident @ pat / ref mut ident @ pat
364
373
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 ) ?
366
375
} else if self . eat_keyword ( kw:: Box ) {
367
376
self . parse_pat_box ( ) ?
368
377
} else if self . check_inline_const ( 0 ) {
@@ -384,7 +393,7 @@ impl<'a> Parser<'a> {
384
393
// Parse `ident @ pat`
385
394
// This can give false positives and parse nullary enums,
386
395
// they are dealt with later in resolve.
387
- self . parse_pat_ident ( BindingAnnotation :: NONE ) ?
396
+ self . parse_pat_ident ( BindingAnnotation :: NONE , syntax_loc ) ?
388
397
} else if self . is_start_of_pat_with_path ( ) {
389
398
// Parse pattern starting with a path
390
399
let ( qself, path) = if self . eat_lt ( ) {
@@ -485,7 +494,7 @@ impl<'a> Parser<'a> {
485
494
486
495
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
487
496
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 ) ?;
489
498
let whole_span = lhs. span . to ( rhs. span ) ;
490
499
491
500
if let PatKind :: Ident ( _, _, sub @ None ) = & mut rhs. kind {
@@ -541,7 +550,7 @@ impl<'a> Parser<'a> {
541
550
}
542
551
543
552
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 ) ?;
545
554
Ok ( PatKind :: Ref ( subpat, mutbl) )
546
555
}
547
556
@@ -566,12 +575,12 @@ impl<'a> Parser<'a> {
566
575
}
567
576
568
577
/// 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 > {
570
579
let mut_span = self . prev_token . span ;
571
580
572
581
if self . eat_keyword ( kw:: Ref ) {
573
582
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 ) ;
575
584
}
576
585
577
586
self . recover_additional_muts ( ) ;
@@ -584,7 +593,7 @@ impl<'a> Parser<'a> {
584
593
}
585
594
586
595
// 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 ) ?;
588
597
589
598
// If we don't have `mut $ident (@ pat)?`, error.
590
599
if let PatKind :: Ident ( BindingAnnotation ( ByRef :: No , m @ Mutability :: Not ) , ..) = & mut pat. kind
@@ -810,10 +819,25 @@ impl<'a> Parser<'a> {
810
819
/// Parses `ident` or `ident @ pat`.
811
820
/// Used by the copy foo and ref foo patterns to give a good
812
821
/// 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 > {
814
827
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
+
815
839
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 ) ?)
817
841
} else {
818
842
None
819
843
} ;
@@ -902,14 +926,14 @@ impl<'a> Parser<'a> {
902
926
// We cannot use `parse_pat_ident()` since it will complain `box`
903
927
// is not an identifier.
904
928
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 ) ?)
906
930
} else {
907
931
None
908
932
} ;
909
933
910
934
Ok ( PatKind :: Ident ( BindingAnnotation :: NONE , Ident :: new ( kw:: Box , box_span) , sub) )
911
935
} else {
912
- let pat = self . parse_pat_with_range_pat ( false , None ) ?;
936
+ let pat = self . parse_pat_with_range_pat ( false , None , None ) ?;
913
937
self . sess . gated_spans . gate ( sym:: box_patterns, box_span. to ( self . prev_token . span ) ) ;
914
938
Ok ( PatKind :: Box ( pat) )
915
939
}
0 commit comments