@@ -834,9 +834,7 @@ impl<'a> Parser<'a> {
834
834
hi = self . prev_span;
835
835
ex = ExprKind :: Lit ( literal) ;
836
836
}
837
- None => {
838
- return Err ( self . expected_expression_found( ) ) ;
839
- }
837
+ None => return Err ( self . expected_expression_found( ) ) ,
840
838
}
841
839
}
842
840
}
@@ -846,37 +844,8 @@ impl<'a> Parser<'a> {
846
844
// This match arm is a special-case of the `_` match arm below and
847
845
// could be removed without changing functionality, but it's faster
848
846
// to have it here, especially for programs with large constants.
849
- token:: Literal ( _) => {
850
- parse_lit ! ( )
851
- }
852
- token:: OpenDelim ( token:: Paren ) => {
853
- let mut first = true ;
854
- let parse_leading_attr_expr = |this : & mut Parser < ' a > | {
855
- if first {
856
- attrs. extend ( this. parse_inner_attributes ( ) ?) ;
857
- first = false ;
858
- }
859
- this. parse_expr_catch_underscore ( )
860
- } ;
861
-
862
- // (e) is parenthesized e
863
- // (e,) is a tuple with only one field, e
864
- let ( es, trailing_comma) =
865
- match self . parse_paren_comma_seq ( parse_leading_attr_expr)
866
- {
867
- Ok ( x) => x,
868
- Err ( err) => return Ok (
869
- self . recover_seq_parse_error ( token:: Paren , lo, Err ( err) ) ,
870
- ) ,
871
- } ;
872
-
873
- hi = self . prev_span ;
874
- ex = if es. len ( ) == 1 && !trailing_comma {
875
- ExprKind :: Paren ( es. into_iter ( ) . nth ( 0 ) . unwrap ( ) )
876
- } else {
877
- ExprKind :: Tup ( es)
878
- } ;
879
- }
847
+ token:: Literal ( _) => parse_lit ! ( ) ,
848
+ token:: OpenDelim ( token:: Paren ) => return self . parse_tuple_parens_expr ( ) ,
880
849
token:: OpenDelim ( token:: Brace ) => {
881
850
return self . parse_block_expr ( None , lo, BlockCheckMode :: Default , attrs) ;
882
851
}
@@ -1095,6 +1064,34 @@ impl<'a> Parser<'a> {
1095
1064
self . maybe_recover_from_bad_qpath ( expr, true )
1096
1065
}
1097
1066
1067
+ fn parse_tuple_parens_expr ( & mut self ) -> PResult < ' a , P < Expr > > {
1068
+ let lo = self . token . span ;
1069
+ let mut first = true ;
1070
+ let mut attrs = ThinVec :: new ( ) ;
1071
+ let parse_leading_attr_expr = |p : & mut Self | {
1072
+ if first {
1073
+ // `(#![foo] a, b, ...)` is OK...
1074
+ attrs = p. parse_inner_attributes ( ) ?. into ( ) ;
1075
+ // ...but not `(a, #![foo] b, ...)`.
1076
+ first = false ;
1077
+ }
1078
+ p. parse_expr_catch_underscore ( )
1079
+ } ;
1080
+ let ( es, trailing_comma) = match self . parse_paren_comma_seq ( parse_leading_attr_expr) {
1081
+ Ok ( x) => x,
1082
+ Err ( err) => return Ok ( self . recover_seq_parse_error ( token:: Paren , lo, Err ( err) ) ) ,
1083
+ } ;
1084
+ let kind = if es. len ( ) == 1 && !trailing_comma {
1085
+ // `(e)` is parenthesized `e`.
1086
+ ExprKind :: Paren ( es. into_iter ( ) . nth ( 0 ) . unwrap ( ) )
1087
+ } else {
1088
+ // `(e,)` is a tuple with only one field, `e`.
1089
+ ExprKind :: Tup ( es)
1090
+ } ;
1091
+ let expr = self . mk_expr ( lo. to ( self . prev_span ) , kind, attrs) ;
1092
+ self . maybe_recover_from_bad_qpath ( expr, true )
1093
+ }
1094
+
1098
1095
/// Returns a string literal if the next token is a string literal.
1099
1096
/// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
1100
1097
/// and returns `None` if the next token is not literal at all.
0 commit comments