Skip to content

Refactor expression parsing thoroughly #67112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Dec 29, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e77b9d3
refactor parse_field
Centril Dec 4, 2019
8480b31
extract recover_struct_comma_after_dotdot
Centril Dec 4, 2019
701b974
extract find_struct_error_after_field_looking_code
Centril Dec 4, 2019
66b8ae4
extract error_struct_lit_not_allowed_here
Centril Dec 4, 2019
f6e2bdc
extract is_certainly_not_a_block
Centril Dec 4, 2019
de2e443
make parse_async_block conventional
Centril Dec 6, 2019
7262dcc
refactor loop parsing a bit
Centril Dec 6, 2019
44ff4df
more recovery in if-parsing
Centril Dec 6, 2019
7bcc325
refactor parse_if_expr
Centril Dec 6, 2019
ad6f91a
refactor parse_fn_block_param
Centril Dec 6, 2019
f647c11
simplify parse_fn_block_decl
Centril Dec 6, 2019
aa8adba
simplify parse_literal_maybe_minus
Centril Dec 6, 2019
0bb3dad
extract error_float_lits-must_have_int_part
Centril Dec 6, 2019
98701b2
extract parse_index_expr & refactor parse_dot_suffix
Centril Dec 6, 2019
287ba5d
extract parse_fn_call_expr
Centril Dec 6, 2019
a15d0cd
extract parse_tuple_field_access_expr
Centril Dec 6, 2019
ff5762b
extract recover_field_access_by_float_lit
Centril Dec 6, 2019
9c6bbf1
extract error_unexpected_after_dot and de-fatalize
Centril Dec 6, 2019
bc95228
extract parse_dot_suffix_expr
Centril Dec 7, 2019
7ae12c9
extract parse_dot_base_expr
Centril Dec 7, 2019
af5ac23
simplify parse_dot_call_or_expr
Centril Dec 7, 2019
84f9bf1
refactor parse_address_of -> parse_borrow_expr
Centril Dec 7, 2019
00cc8a1
simplify parse_assoc_op_cast
Centril Dec 7, 2019
80eeefb
extract recover_not_expr
Centril Dec 7, 2019
ada388b
extract is_mistaken_not_ident_negation
Centril Dec 7, 2019
f6ab439
extract parse_deref_expr
Centril Dec 7, 2019
4cfcfe9
extract parse_neg_expr
Centril Dec 7, 2019
efdea63
extract parse_prefix_expr
Centril Dec 7, 2019
8456c40
extract parse_not_expr
Centril Dec 7, 2019
e43a7ef
simplify parse_prefix_range_expr
Centril Dec 7, 2019
05c26a4
refactor assoc op parsing
Centril Dec 7, 2019
7a246ac
fix rebase fallout
Centril Dec 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor loop parsing a bit
  • Loading branch information
Centril committed Dec 23, 2019
commit 7262dcc4a78a4e63db29410365fe7d47f2b56fd0
55 changes: 26 additions & 29 deletions src/librustc_parse/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1472,15 +1472,13 @@ impl<'a> Parser<'a> {
}
}

/// Parses a `for ... in` expression (`for` token already eaten).
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
fn parse_for_expr(
&mut self,
opt_label: Option<Label>,
span_lo: Span,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`

// Record whether we are about to parse `for (`.
// This is used below for recovery in case of `for ( $stuff ) $block`
// in which case we will suggest `for $stuff $block`.
Expand All @@ -1491,65 +1489,64 @@ impl<'a> Parser<'a> {

let pat = self.parse_top_pat(GateOr::Yes)?;
if !self.eat_keyword(kw::In) {
let in_span = self.prev_span.between(self.token.span);
self.struct_span_err(in_span, "missing `in` in `for` loop")
.span_suggestion_short(
in_span,
"try adding `in` here",
" in ".into(),
// has been misleading, at least in the past (closed Issue #48492)
Applicability::MaybeIncorrect,
)
.emit();
self.error_missing_in_for_loop();
}
let in_span = self.prev_span;
self.check_for_for_in_in_typo(in_span);
self.check_for_for_in_in_typo(self.prev_span);
let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;

let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);

let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);

let hi = self.prev_span;
Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs))
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs))
}

fn error_missing_in_for_loop(&self) {
let in_span = self.prev_span.between(self.token.span);
self.struct_span_err(in_span, "missing `in` in `for` loop")
.span_suggestion_short(
in_span,
"try adding `in` here",
" in ".into(),
// Has been misleading, at least in the past (closed Issue #48492).
Applicability::MaybeIncorrect,
)
.emit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add extra checks here to not suggest in when it wouldn't be appropriate and bubble the error up in those cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What situations do you have in mind for "inappropriate" ?

}

/// Parses a `while` or `while let` expression (`while` token already eaten).
fn parse_while_expr(
&mut self,
opt_label: Option<Label>,
span_lo: Span,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
let cond = self.parse_cond_expr()?;
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let span = span_lo.to(body.span);
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::While(cond, body, opt_label), attrs))
}

/// Parses `loop { ... }` (`loop` token already eaten).
fn parse_loop_expr(
&mut self,
opt_label: Option<Label>,
span_lo: Span,
lo: Span,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
attrs.extend(iattrs);
let span = span_lo.to(body.span);
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::Loop(body, opt_label), attrs))
}

fn eat_label(&mut self) -> Option<Label> {
if let Some(ident) = self.token.lifetime() {
self.token.lifetime().map(|ident| {
let span = self.token.span;
self.bump();
Some(Label { ident: Ident::new(ident.name, span) })
} else {
None
}
Label { ident: Ident::new(ident.name, span) }
})
}

/// Parses a `match ... { ... }` expression (`match` token already eaten).
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/while-let.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ warning: irrefutable while-let pattern
--> $DIR/while-let.rs:7:13
|
LL | while let $p = $e $b
| ^^^^^
| ^^^^^^^^^^^^^^^^^^^^
...
LL | / foo!(_a, 1, {
LL | | println!("irrefutable pattern");
Expand All @@ -15,7 +15,7 @@ warning: irrefutable while-let pattern
--> $DIR/while-let.rs:7:13
|
LL | while let $p = $e $b
| ^^^^^
| ^^^^^^^^^^^^^^^^^^^^
...
LL | / bar!(_a, 1, {
LL | | println!("irrefutable pattern");
Expand Down