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