@@ -785,23 +785,14 @@ impl<'a> Parser<'a> {
785
785
}
786
786
} ;
787
787
788
- self . parse_and_disallow_postfix_after_cast ( cast_expr)
789
- }
790
-
791
- /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast,
792
- /// then emits an error and returns the newly parsed tree.
793
- /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`.
794
- fn parse_and_disallow_postfix_after_cast (
795
- & mut self ,
796
- cast_expr : P < Expr > ,
797
- ) -> PResult < ' a , P < Expr > > {
798
- if let ExprKind :: Type ( _, _) = cast_expr. kind {
799
- panic ! ( "ExprKind::Type must not be parsed" ) ;
800
- }
788
+ // Try to parse a postfix operator such as `.`, `?`, or index (`[]`)
789
+ // after a cast. If one is present, emit an error then return a valid
790
+ // parse tree; For something like `&x as T[0]` will be as if it was
791
+ // written `((&x) as T)[0]`.
801
792
802
793
let span = cast_expr. span ;
803
794
804
- let with_postfix = self . parse_expr_dot_or_call_with_ ( cast_expr, span) ?;
795
+ let with_postfix = self . parse_expr_dot_or_call_with ( AttrVec :: new ( ) , cast_expr, span) ?;
805
796
806
797
// Check if an illegal postfix operator has been added after the cast.
807
798
// If the resulting expression is not a cast, it is an illegal postfix operator.
@@ -885,23 +876,63 @@ impl<'a> Parser<'a> {
885
876
self . collect_tokens_for_expr ( attrs, |this, attrs| {
886
877
let base = this. parse_expr_bottom ( ) ?;
887
878
let span = this. interpolated_or_expr_span ( & base) ;
888
- this. parse_expr_dot_or_call_with ( base , span , attrs )
879
+ this. parse_expr_dot_or_call_with ( attrs , base , span )
889
880
} )
890
881
}
891
882
892
883
pub ( super ) fn parse_expr_dot_or_call_with (
893
884
& mut self ,
894
- e0 : P < Expr > ,
895
- lo : Span ,
896
885
mut attrs : ast:: AttrVec ,
886
+ mut e : P < Expr > ,
887
+ lo : Span ,
897
888
) -> PResult < ' a , P < Expr > > {
898
- // Stitch the list of outer attributes onto the return value.
899
- // A little bit ugly, but the best way given the current code
900
- // structure
901
- let res = ensure_sufficient_stack (
902
- // this expr demonstrates the recursion it guards against
903
- || self . parse_expr_dot_or_call_with_ ( e0, lo) ,
904
- ) ;
889
+ let res = ensure_sufficient_stack ( || {
890
+ loop {
891
+ let has_question =
892
+ if self . prev_token . kind == TokenKind :: Ident ( kw:: Return , IdentIsRaw :: No ) {
893
+ // We are using noexpect here because we don't expect a `?` directly after
894
+ // a `return` which could be suggested otherwise.
895
+ self . eat_noexpect ( & token:: Question )
896
+ } else {
897
+ self . eat ( & token:: Question )
898
+ } ;
899
+ if has_question {
900
+ // `expr?`
901
+ e = self . mk_expr ( lo. to ( self . prev_token . span ) , ExprKind :: Try ( e) ) ;
902
+ continue ;
903
+ }
904
+ let has_dot =
905
+ if self . prev_token . kind == TokenKind :: Ident ( kw:: Return , IdentIsRaw :: No ) {
906
+ // We are using noexpect here because we don't expect a `.` directly after
907
+ // a `return` which could be suggested otherwise.
908
+ self . eat_noexpect ( & token:: Dot )
909
+ } else if self . token . kind == TokenKind :: RArrow && self . may_recover ( ) {
910
+ // Recovery for `expr->suffix`.
911
+ self . bump ( ) ;
912
+ let span = self . prev_token . span ;
913
+ self . dcx ( ) . emit_err ( errors:: ExprRArrowCall { span } ) ;
914
+ true
915
+ } else {
916
+ self . eat ( & token:: Dot )
917
+ } ;
918
+ if has_dot {
919
+ // expr.f
920
+ e = self . parse_dot_suffix_expr ( lo, e) ?;
921
+ continue ;
922
+ }
923
+ if self . expr_is_complete ( & e) {
924
+ return Ok ( e) ;
925
+ }
926
+ e = match self . token . kind {
927
+ token:: OpenDelim ( Delimiter :: Parenthesis ) => self . parse_expr_fn_call ( lo, e) ,
928
+ token:: OpenDelim ( Delimiter :: Bracket ) => self . parse_expr_index ( lo, e) ?,
929
+ _ => return Ok ( e) ,
930
+ }
931
+ }
932
+ } ) ;
933
+
934
+ // Stitch the list of outer attributes onto the return value. A little
935
+ // bit ugly, but the best way given the current code structure.
905
936
if attrs. is_empty ( ) {
906
937
res
907
938
} else {
@@ -915,50 +946,6 @@ impl<'a> Parser<'a> {
915
946
}
916
947
}
917
948
918
- fn parse_expr_dot_or_call_with_ ( & mut self , mut e : P < Expr > , lo : Span ) -> PResult < ' a , P < Expr > > {
919
- loop {
920
- let has_question =
921
- if self . prev_token . kind == TokenKind :: Ident ( kw:: Return , IdentIsRaw :: No ) {
922
- // we are using noexpect here because we don't expect a `?` directly after a `return`
923
- // which could be suggested otherwise
924
- self . eat_noexpect ( & token:: Question )
925
- } else {
926
- self . eat ( & token:: Question )
927
- } ;
928
- if has_question {
929
- // `expr?`
930
- e = self . mk_expr ( lo. to ( self . prev_token . span ) , ExprKind :: Try ( e) ) ;
931
- continue ;
932
- }
933
- let has_dot = if self . prev_token . kind == TokenKind :: Ident ( kw:: Return , IdentIsRaw :: No ) {
934
- // we are using noexpect here because we don't expect a `.` directly after a `return`
935
- // which could be suggested otherwise
936
- self . eat_noexpect ( & token:: Dot )
937
- } else if self . token . kind == TokenKind :: RArrow && self . may_recover ( ) {
938
- // Recovery for `expr->suffix`.
939
- self . bump ( ) ;
940
- let span = self . prev_token . span ;
941
- self . dcx ( ) . emit_err ( errors:: ExprRArrowCall { span } ) ;
942
- true
943
- } else {
944
- self . eat ( & token:: Dot )
945
- } ;
946
- if has_dot {
947
- // expr.f
948
- e = self . parse_dot_suffix_expr ( lo, e) ?;
949
- continue ;
950
- }
951
- if self . expr_is_complete ( & e) {
952
- return Ok ( e) ;
953
- }
954
- e = match self . token . kind {
955
- token:: OpenDelim ( Delimiter :: Parenthesis ) => self . parse_expr_fn_call ( lo, e) ,
956
- token:: OpenDelim ( Delimiter :: Bracket ) => self . parse_expr_index ( lo, e) ?,
957
- _ => return Ok ( e) ,
958
- }
959
- }
960
- }
961
-
962
949
pub ( super ) fn parse_dot_suffix_expr (
963
950
& mut self ,
964
951
lo : Span ,
@@ -1388,7 +1375,7 @@ impl<'a> Parser<'a> {
1388
1375
/// Parses things like parenthesized exprs, macros, `return`, etc.
1389
1376
///
1390
1377
/// N.B., this does not parse outer attributes, and is private because it only works
1391
- /// correctly if called from `parse_dot_or_call_expr() `.
1378
+ /// correctly if called from `parse_expr_dot_or_call `.
1392
1379
fn parse_expr_bottom ( & mut self ) -> PResult < ' a , P < Expr > > {
1393
1380
maybe_recover_from_interpolated_ty_qpath ! ( self , true ) ;
1394
1381
0 commit comments