diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 125 |
1 files changed, 56 insertions, 69 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0ba8c66f48f..0e7497cea41 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -785,23 +785,14 @@ impl<'a> Parser<'a> { } }; - self.parse_and_disallow_postfix_after_cast(cast_expr) - } - - /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, - /// then emits an error and returns the newly parsed tree. - /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. - fn parse_and_disallow_postfix_after_cast( - &mut self, - cast_expr: P<Expr>, - ) -> PResult<'a, P<Expr>> { - if let ExprKind::Type(_, _) = cast_expr.kind { - panic!("ExprKind::Type must not be parsed"); - } + // Try to parse a postfix operator such as `.`, `?`, or index (`[]`) + // after a cast. If one is present, emit an error then return a valid + // parse tree; For something like `&x as T[0]` will be as if it was + // written `((&x) as T)[0]`. let span = cast_expr.span; - let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?; + let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?; // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, it is an illegal postfix operator. @@ -885,23 +876,63 @@ impl<'a> Parser<'a> { self.collect_tokens_for_expr(attrs, |this, attrs| { let base = this.parse_expr_bottom()?; let span = this.interpolated_or_expr_span(&base); - this.parse_expr_dot_or_call_with(base, span, attrs) + this.parse_expr_dot_or_call_with(attrs, base, span) }) } pub(super) fn parse_expr_dot_or_call_with( &mut self, - e0: P<Expr>, - lo: Span, mut attrs: ast::AttrVec, + mut e: P<Expr>, + lo: Span, ) -> PResult<'a, P<Expr>> { - // Stitch the list of outer attributes onto the return value. - // A little bit ugly, but the best way given the current code - // structure - let res = ensure_sufficient_stack( - // this expr demonstrates the recursion it guards against - || self.parse_expr_dot_or_call_with_(e0, lo), - ); + let res = ensure_sufficient_stack(|| { + loop { + let has_question = + if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + // We are using noexpect here because we don't expect a `?` directly after + // a `return` which could be suggested otherwise. + self.eat_noexpect(&token::Question) + } else { + self.eat(&token::Question) + }; + if has_question { + // `expr?` + e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); + continue; + } + let has_dot = + if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + // We are using noexpect here because we don't expect a `.` directly after + // a `return` which could be suggested otherwise. + self.eat_noexpect(&token::Dot) + } else if self.token.kind == TokenKind::RArrow && self.may_recover() { + // Recovery for `expr->suffix`. + self.bump(); + let span = self.prev_token.span; + self.dcx().emit_err(errors::ExprRArrowCall { span }); + true + } else { + self.eat(&token::Dot) + }; + if has_dot { + // expr.f + e = self.parse_dot_suffix_expr(lo, e)?; + continue; + } + if self.expr_is_complete(&e) { + return Ok(e); + } + e = match self.token.kind { + token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e), + token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?, + _ => return Ok(e), + } + } + }); + + // Stitch the list of outer attributes onto the return value. A little + // bit ugly, but the best way given the current code structure. if attrs.is_empty() { res } else { @@ -915,50 +946,6 @@ impl<'a> Parser<'a> { } } - fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { - loop { - let has_question = - if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { - // we are using noexpect here because we don't expect a `?` directly after a `return` - // which could be suggested otherwise - self.eat_noexpect(&token::Question) - } else { - self.eat(&token::Question) - }; - if has_question { - // `expr?` - e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); - continue; - } - let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { - // we are using noexpect here because we don't expect a `.` directly after a `return` - // which could be suggested otherwise - self.eat_noexpect(&token::Dot) - } else if self.token.kind == TokenKind::RArrow && self.may_recover() { - // Recovery for `expr->suffix`. - self.bump(); - let span = self.prev_token.span; - self.dcx().emit_err(errors::ExprRArrowCall { span }); - true - } else { - self.eat(&token::Dot) - }; - if has_dot { - // expr.f - e = self.parse_dot_suffix_expr(lo, e)?; - continue; - } - if self.expr_is_complete(&e) { - return Ok(e); - } - e = match self.token.kind { - token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e), - token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?, - _ => return Ok(e), - } - } - } - pub(super) fn parse_dot_suffix_expr( &mut self, lo: Span, @@ -1388,7 +1375,7 @@ impl<'a> Parser<'a> { /// Parses things like parenthesized exprs, macros, `return`, etc. /// /// N.B., this does not parse outer attributes, and is private because it only works - /// correctly if called from `parse_dot_or_call_expr()`. + /// correctly if called from `parse_expr_dot_or_call`. fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> { maybe_recover_from_interpolated_ty_qpath!(self, true); |
