1
1
use super :: { ForceCollect , Parser , PathStyle , TrailingToken } ;
2
2
use crate :: errors:: {
3
- self , AmbiguousRangePattern , DotDotDotForRemainingFields , DotDotDotRangeToPatternNotAllowed ,
4
- DotDotDotRestPattern , EnumPatternInsteadOfIdentifier , ExpectedBindingLeftOfAt ,
5
- ExpectedCommaAfterPatternField , GenericArgsInPatRequireTurbofishSyntax ,
6
- InclusiveRangeExtraEquals , InclusiveRangeMatchArrow , InclusiveRangeNoEnd , InvalidMutInPattern ,
7
- PatternOnWrongSideOfAt , RefMutOrderIncorrect , RemoveLet , RepeatedMutInPattern ,
8
- SwitchRefBoxOrder , TopLevelOrPatternNotAllowed , TopLevelOrPatternNotAllowedSugg ,
9
- TrailingVertNotAllowed , UnexpectedLifetimeInPattern , UnexpectedVertVertBeforeFunctionParam ,
10
- UnexpectedVertVertInPattern ,
3
+ AmbiguousRangePattern , BoxNotPat , DotDotDotForRemainingFields ,
4
+ DotDotDotRangeToPatternNotAllowed , DotDotDotRestPattern , EnumPatternInsteadOfIdentifier ,
5
+ ExpectedBindingLeftOfAt , ExpectedCommaAfterPatternField ,
6
+ GenericArgsInPatRequireTurbofishSyntax , InclusiveRangeExtraEquals , InclusiveRangeMatchArrow ,
7
+ InclusiveRangeNoEnd , InvalidMutInPattern , PatternOnWrongSideOfAt , RefMutOrderIncorrect ,
8
+ RemoveLet , RepeatedMutInPattern , SwitchRefBoxOrder , TopLevelOrPatternNotAllowed ,
9
+ TopLevelOrPatternNotAllowedSugg , TrailingVertNotAllowed , UnexpectedLifetimeInPattern ,
10
+ UnexpectedParenInRangePat , UnexpectedParenInRangePatSugg ,
11
+ UnexpectedVertVertBeforeFunctionParam , UnexpectedVertVertInPattern ,
11
12
} ;
12
13
use crate :: { maybe_recover_from_interpolated_ty_qpath, maybe_whole} ;
13
14
use rustc_ast:: mut_visit:: { noop_visit_pat, MutVisitor } ;
@@ -18,7 +19,7 @@ use rustc_ast::{
18
19
PatField , PatFieldsRest , PatKind , Path , QSelf , RangeEnd , RangeSyntax ,
19
20
} ;
20
21
use rustc_ast_pretty:: pprust;
21
- use rustc_errors:: { Applicability , DiagnosticBuilder , PResult } ;
22
+ use rustc_errors:: { Applicability , DiagnosticBuilder , MultiSpan , PResult } ;
22
23
use rustc_session:: errors:: ExprParenthesesNeeded ;
23
24
use rustc_span:: source_map:: { respan, Spanned } ;
24
25
use rustc_span:: symbol:: { kw, sym, Ident } ;
@@ -579,6 +580,8 @@ impl<'a> Parser<'a> {
579
580
580
581
/// Parse a tuple or parenthesis pattern.
581
582
fn parse_pat_tuple_or_parens ( & mut self ) -> PResult < ' a , PatKind > {
583
+ let open_paren = self . token . span ;
584
+
582
585
let ( fields, trailing_comma) = self . parse_paren_comma_seq ( |p| {
583
586
p. parse_pat_allow_top_alt (
584
587
None ,
@@ -591,7 +594,26 @@ impl<'a> Parser<'a> {
591
594
// Here, `(pat,)` is a tuple pattern.
592
595
// For backward compatibility, `(..)` is a tuple pattern as well.
593
596
Ok ( if fields. len ( ) == 1 && !( trailing_comma || fields[ 0 ] . is_rest ( ) ) {
594
- PatKind :: Paren ( fields. into_iter ( ) . next ( ) . unwrap ( ) )
597
+ let pat = fields. into_iter ( ) . next ( ) . unwrap ( ) ;
598
+ let close_paren = self . prev_token . span ;
599
+
600
+ match & pat. kind {
601
+ // recover ranges with parentheses around the `(start)..`
602
+ PatKind :: Lit ( begin) if let Some ( form) = self . parse_range_end ( ) => {
603
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
604
+ span : MultiSpan :: from_spans ( vec ! [ open_paren, close_paren] ) ,
605
+ sugg : UnexpectedParenInRangePatSugg {
606
+ start_span : open_paren,
607
+ end_span : close_paren,
608
+ } ,
609
+ } ) ;
610
+
611
+ self . parse_pat_range_begin_with ( begin. clone ( ) , form) ?
612
+ }
613
+
614
+ // (pat) with optional parentheses
615
+ _ => PatKind :: Paren ( pat) ,
616
+ }
595
617
} else {
596
618
PatKind :: Tuple ( fields)
597
619
} )
@@ -727,6 +749,13 @@ impl<'a> Parser<'a> {
727
749
begin : P < Expr > ,
728
750
re : Spanned < RangeEnd > ,
729
751
) -> PResult < ' a , PatKind > {
752
+ // recover from `(`
753
+ let open_paren =
754
+ matches ! ( self . token. kind, token:: OpenDelim ( Delimiter :: Parenthesis ) ) . then ( || {
755
+ self . bump ( ) ;
756
+ self . prev_token . span
757
+ } ) ;
758
+
730
759
let end = if self . is_pat_range_end_start ( 0 ) {
731
760
// Parsing e.g. `X..=Y`.
732
761
Some ( self . parse_pat_range_end ( ) ?)
@@ -738,6 +767,19 @@ impl<'a> Parser<'a> {
738
767
}
739
768
None
740
769
} ;
770
+
771
+ if let Some ( span) = open_paren {
772
+ self . expect ( & token:: CloseDelim ( Delimiter :: Parenthesis ) ) ?;
773
+
774
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
775
+ span : MultiSpan :: from_spans ( vec ! [ span, self . prev_token. span] ) ,
776
+ sugg : UnexpectedParenInRangePatSugg {
777
+ start_span : span,
778
+ end_span : self . prev_token . span ,
779
+ } ,
780
+ } ) ;
781
+ }
782
+
741
783
Ok ( PatKind :: Range ( Some ( begin) , end, re) )
742
784
}
743
785
@@ -777,11 +819,31 @@ impl<'a> Parser<'a> {
777
819
/// The form `...X` is prohibited to reduce confusion with the potential
778
820
/// expression syntax `...expr` for splatting in expressions.
779
821
fn parse_pat_range_to ( & mut self , mut re : Spanned < RangeEnd > ) -> PResult < ' a , PatKind > {
822
+ // recover from `(`
823
+ let open_paren =
824
+ matches ! ( self . token. kind, token:: OpenDelim ( Delimiter :: Parenthesis ) ) . then ( || {
825
+ self . bump ( ) ;
826
+ self . prev_token . span
827
+ } ) ;
828
+
780
829
let end = self . parse_pat_range_end ( ) ?;
781
830
if let RangeEnd :: Included ( syn @ RangeSyntax :: DotDotDot ) = & mut re. node {
782
831
* syn = RangeSyntax :: DotDotEq ;
783
832
self . dcx ( ) . emit_err ( DotDotDotRangeToPatternNotAllowed { span : re. span } ) ;
784
833
}
834
+
835
+ if let Some ( span) = open_paren {
836
+ self . expect ( & token:: CloseDelim ( Delimiter :: Parenthesis ) ) ?;
837
+
838
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
839
+ span : MultiSpan :: from_spans ( vec ! [ span, self . prev_token. span] ) ,
840
+ sugg : UnexpectedParenInRangePatSugg {
841
+ start_span : span,
842
+ end_span : self . prev_token . span ,
843
+ } ,
844
+ } ) ;
845
+ }
846
+
785
847
Ok ( PatKind :: Range ( None , Some ( end) , re) )
786
848
}
787
849
@@ -794,6 +856,9 @@ impl<'a> Parser<'a> {
794
856
|| t. can_begin_literal_maybe_minus ( ) // e.g. `42`.
795
857
|| t. is_whole_expr ( )
796
858
|| t. is_lifetime ( ) // recover `'a` instead of `'a'`
859
+ || ( t. kind == token:: OpenDelim ( Delimiter :: Parenthesis ) // recover leading `(`
860
+ && self . look_ahead ( dist + 1 , |t| t. kind != token:: OpenDelim ( Delimiter :: Parenthesis ) )
861
+ && self . is_pat_range_end_start ( dist + 1 ) )
797
862
} )
798
863
}
799
864
@@ -942,7 +1007,7 @@ impl<'a> Parser<'a> {
942
1007
943
1008
if self . isnt_pattern_start ( ) {
944
1009
let descr = super :: token_descr ( & self . token ) ;
945
- self . dcx ( ) . emit_err ( errors :: BoxNotPat {
1010
+ self . dcx ( ) . emit_err ( BoxNotPat {
946
1011
span : self . token . span ,
947
1012
kw : box_span,
948
1013
lo : box_span. shrink_to_lo ( ) ,
0 commit comments