Skip to content

Commit af3a5a8

Browse files
committed
Save tokens for a few kinds of expressions
1 parent c99fd5c commit af3a5a8

File tree

1 file changed

+99
-87
lines changed

1 file changed

+99
-87
lines changed

src/librustc_parse/parser/expr.rs

+99-87
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Para
99
use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
1010
use rustc_ast::ptr::P;
1111
use rustc_ast::token::{self, Token, TokenKind};
12+
use rustc_ast::tokenstream::TokenStream;
1213
use rustc_ast::util::classify;
1314
use rustc_ast::util::literal::LitError;
1415
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
@@ -86,10 +87,7 @@ impl<'a> Parser<'a> {
8687
/// Parses an expression.
8788
#[inline]
8889
pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
89-
let (mut expr, tokens) =
90-
self.collect_tokens(|this| this.parse_expr_res(Restrictions::empty(), None))?;
91-
expr.tokens = Some(tokens);
92-
Ok(expr)
90+
self.parse_expr_res(Restrictions::empty(), None)
9391
}
9492

9593
pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
@@ -904,92 +902,96 @@ impl<'a> Parser<'a> {
904902
// attributes by giving them a empty "already-parsed" list.
905903
let attrs = AttrVec::new();
906904

907-
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
908-
let lo = self.token.span;
909-
if let token::Literal(_) = self.token.kind {
910-
// This match arm is a special-case of the `_` match arm below and
911-
// could be removed without changing functionality, but it's faster
912-
// to have it here, especially for programs with large constants.
913-
self.parse_lit_expr(attrs)
914-
} else if self.check(&token::OpenDelim(token::Paren)) {
915-
self.parse_tuple_parens_expr(attrs)
916-
} else if self.check(&token::OpenDelim(token::Brace)) {
917-
self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs)
918-
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
919-
self.parse_closure_expr(attrs)
920-
} else if self.check(&token::OpenDelim(token::Bracket)) {
921-
self.parse_array_or_repeat_expr(attrs)
922-
} else if self.eat_lt() {
923-
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
924-
Ok(self.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
925-
} else if self.check_path() {
926-
self.parse_path_start_expr(attrs)
927-
} else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
928-
self.parse_closure_expr(attrs)
929-
} else if self.eat_keyword(kw::If) {
930-
self.parse_if_expr(attrs)
931-
} else if self.eat_keyword(kw::For) {
932-
self.parse_for_expr(None, self.prev_token.span, attrs)
933-
} else if self.eat_keyword(kw::While) {
934-
self.parse_while_expr(None, self.prev_token.span, attrs)
935-
} else if let Some(label) = self.eat_label() {
936-
self.parse_labeled_expr(label, attrs)
937-
} else if self.eat_keyword(kw::Loop) {
938-
self.parse_loop_expr(None, self.prev_token.span, attrs)
939-
} else if self.eat_keyword(kw::Continue) {
940-
let kind = ExprKind::Continue(self.eat_label());
941-
Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs))
942-
} else if self.eat_keyword(kw::Match) {
943-
let match_sp = self.prev_token.span;
944-
self.parse_match_expr(attrs).map_err(|mut err| {
945-
err.span_label(match_sp, "while parsing this match expression");
946-
err
947-
})
948-
} else if self.eat_keyword(kw::Unsafe) {
949-
self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
950-
} else if self.is_do_catch_block() {
951-
self.recover_do_catch(attrs)
952-
} else if self.is_try_block() {
953-
self.expect_keyword(kw::Try)?;
954-
self.parse_try_block(lo, attrs)
955-
} else if self.eat_keyword(kw::Return) {
956-
self.parse_return_expr(attrs)
957-
} else if self.eat_keyword(kw::Break) {
958-
self.parse_break_expr(attrs)
959-
} else if self.eat_keyword(kw::Yield) {
960-
self.parse_yield_expr(attrs)
961-
} else if self.eat_keyword(kw::Let) {
962-
self.parse_let_expr(attrs)
963-
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
964-
// Don't complain about bare semicolons after unclosed braces
965-
// recovery in order to keep the error count down. Fixing the
966-
// delimiters will possibly also fix the bare semicolon found in
967-
// expression context. For example, silence the following error:
968-
//
969-
// error: expected expression, found `;`
970-
// --> file.rs:2:13
971-
// |
972-
// 2 | foo(bar(;
973-
// | ^ expected expression
974-
self.bump();
975-
Ok(self.mk_expr_err(self.token.span))
976-
} else if self.token.uninterpolated_span().rust_2018() {
977-
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
978-
if self.check_keyword(kw::Async) {
979-
if self.is_async_block() {
980-
// Check for `async {` and `async move {`.
981-
self.parse_async_block(attrs)
905+
let (mut expr, tokens) = self.collect_tokens(|this| {
906+
// Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
907+
let lo = this.token.span;
908+
if let token::Literal(_) = this.token.kind {
909+
// This match arm is a special-case of the `_` match arm below and
910+
// could be removed without changing functionality, but it's faster
911+
// to have it here, especially for programs with large constants.
912+
this.parse_lit_expr(attrs)
913+
} else if this.check(&token::OpenDelim(token::Paren)) {
914+
this.parse_tuple_parens_expr(attrs)
915+
} else if this.check(&token::OpenDelim(token::Brace)) {
916+
this.parse_block_expr(None, lo, BlockCheckMode::Default, attrs)
917+
} else if this.check(&token::BinOp(token::Or)) || this.check(&token::OrOr) {
918+
this.parse_closure_expr(attrs)
919+
} else if this.check(&token::OpenDelim(token::Bracket)) {
920+
this.parse_array_or_repeat_expr(attrs)
921+
} else if this.eat_lt() {
922+
let (qself, path) = this.parse_qpath(PathStyle::Expr)?;
923+
Ok(this.mk_expr(lo.to(path.span), ExprKind::Path(Some(qself), path), attrs))
924+
} else if this.check_path() {
925+
this.parse_path_start_expr(attrs)
926+
} else if this.check_keyword(kw::Move) || this.check_keyword(kw::Static) {
927+
this.parse_closure_expr(attrs)
928+
} else if this.eat_keyword(kw::If) {
929+
this.parse_if_expr(attrs)
930+
} else if this.eat_keyword(kw::For) {
931+
this.parse_for_expr(None, this.prev_token.span, attrs)
932+
} else if this.eat_keyword(kw::While) {
933+
this.parse_while_expr(None, this.prev_token.span, attrs)
934+
} else if let Some(label) = this.eat_label() {
935+
this.parse_labeled_expr(label, attrs)
936+
} else if this.eat_keyword(kw::Loop) {
937+
this.parse_loop_expr(None, this.prev_token.span, attrs)
938+
} else if this.eat_keyword(kw::Continue) {
939+
let kind = ExprKind::Continue(this.eat_label());
940+
Ok(this.mk_expr(lo.to(this.prev_token.span), kind, attrs))
941+
} else if this.eat_keyword(kw::Match) {
942+
let match_sp = this.prev_token.span;
943+
this.parse_match_expr(attrs).map_err(|mut err| {
944+
err.span_label(match_sp, "while parsing this match expression");
945+
err
946+
})
947+
} else if this.eat_keyword(kw::Unsafe) {
948+
this.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
949+
} else if this.is_do_catch_block() {
950+
this.recover_do_catch(attrs)
951+
} else if this.is_try_block() {
952+
this.expect_keyword(kw::Try)?;
953+
this.parse_try_block(lo, attrs)
954+
} else if this.eat_keyword(kw::Return) {
955+
this.parse_return_expr(attrs)
956+
} else if this.eat_keyword(kw::Break) {
957+
this.parse_break_expr(attrs)
958+
} else if this.eat_keyword(kw::Yield) {
959+
this.parse_yield_expr(attrs)
960+
} else if this.eat_keyword(kw::Let) {
961+
this.parse_let_expr(attrs)
962+
} else if !this.unclosed_delims.is_empty() && this.check(&token::Semi) {
963+
// Don't complain about bare semicolons after unclosed braces
964+
// recovery in order to keep the error count down. Fixing the
965+
// delimiters will possibly also fix the bare semicolon found in
966+
// expression context. For example, silence the following error:
967+
//
968+
// error: expected expression, found `;`
969+
// --> file.rs:2:13
970+
// |
971+
// 2 | foo(bar(;
972+
// | ^ expected expression
973+
this.bump();
974+
Ok(this.mk_expr_err(this.token.span))
975+
} else if this.token.uninterpolated_span().rust_2018() {
976+
// `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
977+
if this.check_keyword(kw::Async) {
978+
if this.is_async_block() {
979+
// Check for `async {` and `async move {`.
980+
this.parse_async_block(attrs)
981+
} else {
982+
this.parse_closure_expr(attrs)
983+
}
984+
} else if this.eat_keyword(kw::Await) {
985+
this.recover_incorrect_await_syntax(lo, this.prev_token.span, attrs)
982986
} else {
983-
self.parse_closure_expr(attrs)
987+
this.parse_lit_expr(attrs)
984988
}
985-
} else if self.eat_keyword(kw::Await) {
986-
self.recover_incorrect_await_syntax(lo, self.prev_token.span, attrs)
987989
} else {
988-
self.parse_lit_expr(attrs)
990+
this.parse_lit_expr(attrs)
989991
}
990-
} else {
991-
self.parse_lit_expr(attrs)
992-
}
992+
})?;
993+
expr.tokens = Some(tokens);
994+
Ok(expr)
993995
}
994996

995997
fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
@@ -2124,10 +2126,20 @@ impl<'a> Parser<'a> {
21242126
Ok(await_expr)
21252127
}
21262128

2127-
crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
2129+
crate fn mk_expr_with_tokens(
2130+
&self,
2131+
span: Span,
2132+
kind: ExprKind,
2133+
attrs: AttrVec,
2134+
tokens: Option<TokenStream>,
2135+
) -> P<Expr> {
21282136
P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
21292137
}
21302138

2139+
crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
2140+
self.mk_expr_with_tokens(span, kind, attrs, None)
2141+
}
2142+
21312143
pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
21322144
self.mk_expr(span, ExprKind::Err, AttrVec::new())
21332145
}

0 commit comments

Comments
 (0)