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