@@ -360,10 +360,7 @@ impl<'a> Parser<'a> {
360
360
let mutbl = self . parse_mutability ( ) ;
361
361
self . parse_pat_ident ( BindingMode :: ByRef ( mutbl) ) ?
362
362
} else if self . eat_keyword ( kw:: Box ) {
363
- // Parse `box pat`
364
- let pat = self . parse_pat_with_range_pat ( false , None ) ?;
365
- self . sess . gated_spans . gate ( sym:: box_patterns, lo. to ( self . prev_token . span ) ) ;
366
- PatKind :: Box ( pat)
363
+ self . parse_pat_box ( ) ?
367
364
} else if self . check_inline_const ( 0 ) {
368
365
// Parse `const pat`
369
366
let const_expr = self . parse_const_block ( lo. to ( self . token . span ) , true ) ?;
@@ -915,6 +912,62 @@ impl<'a> Parser<'a> {
915
912
Ok ( PatKind :: TupleStruct ( qself, path, fields) )
916
913
}
917
914
915
+ /// Are we sure this could not possibly be the start of a pattern?
916
+ ///
917
+ /// Currently, this only accounts for tokens that can follow identifiers
918
+ /// in patterns, but this can be extended as necessary.
919
+ fn isnt_pattern_start ( & self ) -> bool {
920
+ [
921
+ token:: Eq ,
922
+ token:: Colon ,
923
+ token:: Comma ,
924
+ token:: Semi ,
925
+ token:: At ,
926
+ token:: OpenDelim ( Delimiter :: Brace ) ,
927
+ token:: CloseDelim ( Delimiter :: Brace ) ,
928
+ token:: CloseDelim ( Delimiter :: Parenthesis ) ,
929
+ ]
930
+ . contains ( & self . token . kind )
931
+ }
932
+
933
+ /// Parses `box pat`
934
+ fn parse_pat_box ( & mut self ) -> PResult < ' a , PatKind > {
935
+ let box_span = self . prev_token . span ;
936
+
937
+ if self . isnt_pattern_start ( ) {
938
+ self . struct_span_err (
939
+ self . token . span ,
940
+ format ! ( "expected pattern, found {}" , super :: token_descr( & self . token) ) ,
941
+ )
942
+ . span_note ( box_span, "`box` is a reserved keyword" )
943
+ . span_suggestion_verbose (
944
+ box_span. shrink_to_lo ( ) ,
945
+ "escape `box` to use it as an identifier" ,
946
+ "r#" ,
947
+ Applicability :: MaybeIncorrect ,
948
+ )
949
+ . emit ( ) ;
950
+
951
+ // We cannot use `parse_pat_ident()` since it will complain `box`
952
+ // is not an identifier.
953
+ let sub = if self . eat ( & token:: At ) {
954
+ Some ( self . parse_pat_no_top_alt ( Some ( "binding pattern" ) ) ?)
955
+ } else {
956
+ None
957
+ } ;
958
+
959
+ Ok ( PatKind :: Ident (
960
+ BindingMode :: ByValue ( Mutability :: Not ) ,
961
+ Ident :: new ( kw:: Box , box_span) ,
962
+ sub,
963
+ ) )
964
+ } else {
965
+ let pat = self . parse_pat_with_range_pat ( false , None ) ?;
966
+ self . sess . gated_spans . gate ( sym:: box_patterns, box_span. to ( self . prev_token . span ) ) ;
967
+ Ok ( PatKind :: Box ( pat) )
968
+ }
969
+ }
970
+
918
971
/// Parses the fields of a struct-like pattern.
919
972
fn parse_pat_fields ( & mut self ) -> PResult < ' a , ( Vec < PatField > , bool ) > {
920
973
let mut fields = Vec :: new ( ) ;
0 commit comments