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,28 @@ 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)
603
+ if let Some ( form) = self . may_recover ( ) . then ( || self . parse_range_end ( ) ) =>
604
+ {
605
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
606
+ span : MultiSpan :: from_spans ( vec ! [ open_paren, close_paren] ) ,
607
+ sugg : UnexpectedParenInRangePatSugg {
608
+ start_span : open_paren,
609
+ end_span : close_paren,
610
+ } ,
611
+ } ) ;
612
+
613
+ self . parse_pat_range_begin_with ( begin. clone ( ) , form) ?
614
+ }
615
+
616
+ // (pat) with optional parentheses
617
+ _ => PatKind :: Paren ( pat) ,
618
+ }
595
619
} else {
596
620
PatKind :: Tuple ( fields)
597
621
} )
@@ -727,6 +751,14 @@ impl<'a> Parser<'a> {
727
751
begin : P < Expr > ,
728
752
re : Spanned < RangeEnd > ,
729
753
) -> PResult < ' a , PatKind > {
754
+ // recover from `(`
755
+ let open_paren = ( self . may_recover ( )
756
+ && self . token . kind == token:: OpenDelim ( Delimiter :: Parenthesis ) )
757
+ . then ( || {
758
+ self . bump ( ) ;
759
+ self . prev_token . span
760
+ } ) ;
761
+
730
762
let end = if self . is_pat_range_end_start ( 0 ) {
731
763
// Parsing e.g. `X..=Y`.
732
764
Some ( self . parse_pat_range_end ( ) ?)
@@ -738,6 +770,19 @@ impl<'a> Parser<'a> {
738
770
}
739
771
None
740
772
} ;
773
+
774
+ if let Some ( span) = open_paren {
775
+ self . expect ( & token:: CloseDelim ( Delimiter :: Parenthesis ) ) ?;
776
+
777
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
778
+ span : MultiSpan :: from_spans ( vec ! [ span, self . prev_token. span] ) ,
779
+ sugg : UnexpectedParenInRangePatSugg {
780
+ start_span : span,
781
+ end_span : self . prev_token . span ,
782
+ } ,
783
+ } ) ;
784
+ }
785
+
741
786
Ok ( PatKind :: Range ( Some ( begin) , end, re) )
742
787
}
743
788
@@ -777,11 +822,32 @@ impl<'a> Parser<'a> {
777
822
/// The form `...X` is prohibited to reduce confusion with the potential
778
823
/// expression syntax `...expr` for splatting in expressions.
779
824
fn parse_pat_range_to ( & mut self , mut re : Spanned < RangeEnd > ) -> PResult < ' a , PatKind > {
825
+ // recover from `(`
826
+ let open_paren = ( self . may_recover ( )
827
+ && self . token . kind == token:: OpenDelim ( Delimiter :: Parenthesis ) )
828
+ . then ( || {
829
+ self . bump ( ) ;
830
+ self . prev_token . span
831
+ } ) ;
832
+
780
833
let end = self . parse_pat_range_end ( ) ?;
781
834
if let RangeEnd :: Included ( syn @ RangeSyntax :: DotDotDot ) = & mut re. node {
782
835
* syn = RangeSyntax :: DotDotEq ;
783
836
self . dcx ( ) . emit_err ( DotDotDotRangeToPatternNotAllowed { span : re. span } ) ;
784
837
}
838
+
839
+ if let Some ( span) = open_paren {
840
+ self . expect ( & token:: CloseDelim ( Delimiter :: Parenthesis ) ) ?;
841
+
842
+ self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
843
+ span : MultiSpan :: from_spans ( vec ! [ span, self . prev_token. span] ) ,
844
+ sugg : UnexpectedParenInRangePatSugg {
845
+ start_span : span,
846
+ end_span : self . prev_token . span ,
847
+ } ,
848
+ } ) ;
849
+ }
850
+
785
851
Ok ( PatKind :: Range ( None , Some ( end) , re) )
786
852
}
787
853
@@ -794,6 +860,10 @@ impl<'a> Parser<'a> {
794
860
|| t. can_begin_literal_maybe_minus ( ) // e.g. `42`.
795
861
|| t. is_whole_expr ( )
796
862
|| t. is_lifetime ( ) // recover `'a` instead of `'a'`
863
+ || ( self . may_recover ( ) // recover leading `(`
864
+ && t. kind == token:: OpenDelim ( Delimiter :: Parenthesis )
865
+ && self . look_ahead ( dist + 1 , |t| t. kind != token:: OpenDelim ( Delimiter :: Parenthesis ) )
866
+ && self . is_pat_range_end_start ( dist + 1 ) )
797
867
} )
798
868
}
799
869
@@ -942,7 +1012,7 @@ impl<'a> Parser<'a> {
942
1012
943
1013
if self . isnt_pattern_start ( ) {
944
1014
let descr = super :: token_descr ( & self . token ) ;
945
- self . dcx ( ) . emit_err ( errors :: BoxNotPat {
1015
+ self . dcx ( ) . emit_err ( BoxNotPat {
946
1016
span : self . token . span ,
947
1017
kw : box_span,
948
1018
lo : box_span. shrink_to_lo ( ) ,
0 commit comments