@@ -3729,6 +3729,13 @@ impl<'a> Parser<'a> {
3729
3729
}
3730
3730
}
3731
3731
3732
+ /// Is the current token suitable as the start of a range patterns end?
3733
+ fn is_pat_range_end_start ( & self ) -> bool {
3734
+ self . token . is_path_start ( ) // e.g. `MY_CONST`;
3735
+ || self . token == token:: Dot // e.g. `.5` for recovery;
3736
+ || self . token . can_begin_literal_or_bool ( ) // e.g. `42`.
3737
+ }
3738
+
3732
3739
// helper function to decide whether to parse as ident binding or to try to do
3733
3740
// something more complex like range patterns
3734
3741
fn parse_as_ident ( & mut self ) -> bool {
@@ -3801,6 +3808,26 @@ impl<'a> Parser<'a> {
3801
3808
self . parse_pat_with_range_pat ( true , expected)
3802
3809
}
3803
3810
3811
+ /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
3812
+ fn parse_pat_range_to ( & mut self , re : RangeEnd , form : & str ) -> PResult < ' a , PatKind > {
3813
+ let lo = self . prev_span ;
3814
+ let end = self . parse_pat_range_end ( ) ?;
3815
+ let range_span = lo. to ( end. span ) ;
3816
+ let begin = self . mk_expr ( range_span, ExprKind :: Err , ThinVec :: new ( ) ) ;
3817
+
3818
+ self . diagnostic ( )
3819
+ . struct_span_err ( range_span, & format ! ( "`{}X` range patterns are not supported" , form) )
3820
+ . span_suggestion (
3821
+ range_span,
3822
+ "try using the minimum value for the type" ,
3823
+ format ! ( "MIN{}{}" , form, pprust:: expr_to_string( & end) ) ,
3824
+ Applicability :: HasPlaceholders ,
3825
+ )
3826
+ . emit ( ) ;
3827
+
3828
+ Ok ( PatKind :: Range ( begin, end, respan ( lo, re) ) )
3829
+ }
3830
+
3804
3831
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
3805
3832
/// allowed).
3806
3833
fn parse_pat_with_range_pat (
@@ -3842,9 +3869,24 @@ impl<'a> Parser<'a> {
3842
3869
pat = PatKind :: Slice ( slice) ;
3843
3870
}
3844
3871
token:: DotDot => {
3845
- // Parse `..`.
3846
3872
self . bump ( ) ;
3847
- pat = PatKind :: Rest ;
3873
+ pat = if self . is_pat_range_end_start ( ) {
3874
+ // Parse `..42` for recovery.
3875
+ self . parse_pat_range_to ( RangeEnd :: Excluded , ".." ) ?
3876
+ } else {
3877
+ // A rest pattern `..`.
3878
+ PatKind :: Rest
3879
+ } ;
3880
+ }
3881
+ token:: DotDotEq => {
3882
+ // Parse `..=42` for recovery.
3883
+ self . bump ( ) ;
3884
+ pat = self . parse_pat_range_to ( RangeEnd :: Included ( RangeSyntax :: DotDotEq ) , "..=" ) ?;
3885
+ }
3886
+ token:: DotDotDot => {
3887
+ // Parse `...42` for recovery.
3888
+ self . bump ( ) ;
3889
+ pat = self . parse_pat_range_to ( RangeEnd :: Included ( RangeSyntax :: DotDotDot ) , "..." ) ?;
3848
3890
}
3849
3891
// At this point, token != &, &&, (, [
3850
3892
_ => if self . eat_keyword ( kw:: Underscore ) {
@@ -3914,8 +3956,7 @@ impl<'a> Parser<'a> {
3914
3956
let begin = self . mk_expr ( span, ExprKind :: Path ( qself, path) , ThinVec :: new ( ) ) ;
3915
3957
self . bump ( ) ;
3916
3958
let end = self . parse_pat_range_end ( ) ?;
3917
- let op = Spanned { span : op_span, node : end_kind } ;
3918
- pat = PatKind :: Range ( begin, end, op) ;
3959
+ pat = PatKind :: Range ( begin, end, respan ( op_span, end_kind) ) ;
3919
3960
}
3920
3961
token:: OpenDelim ( token:: Brace ) => {
3921
3962
if qself. is_some ( ) {
@@ -3965,8 +4006,7 @@ impl<'a> Parser<'a> {
3965
4006
on a range-operator token")
3966
4007
} ;
3967
4008
let end = self . parse_pat_range_end ( ) ?;
3968
- let op = Spanned { span : op_span, node : end_kind } ;
3969
- pat = PatKind :: Range ( begin, end, op) ;
4009
+ pat = PatKind :: Range ( begin, end, respan ( op_span, end_kind) )
3970
4010
} else {
3971
4011
pat = PatKind :: Lit ( begin) ;
3972
4012
}
0 commit comments