Skip to content
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

Improve expression & attribute parsing #69760

Merged
merged 19 commits into from
Mar 11, 2020
Merged
Changes from 1 commit
Commits
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
parse: recover on &'lt $expr / 'lt $expr.
  • Loading branch information
Centril committed Mar 10, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 055733f3b3dc5d0841b9284da0c628f9d362461d
35 changes: 31 additions & 4 deletions src/librustc_parse/parser/expr.rs
Original file line number Diff line number Diff line change
@@ -673,10 +673,28 @@ impl<'a> Parser<'a> {
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.expect_and()?;
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
let expr = self.parse_prefix_expr(None);
let (span, expr) = self.interpolated_or_expr_span(expr)?;
Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr)))
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
let span = lo.to(hi);
if let Some(lt) = lifetime {
self.error_remove_borrow_lifetime(span, lt.ident.span);
}
Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
}

fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
estebank marked this conversation as resolved.
Show resolved Hide resolved
self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
.span_label(lt_span, "annotated with lifetime here")
.span_suggestion(
lt_span,
"remove the lifetime annotation",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}

/// Parse `mut?` or `raw [ const | mut ]`.
@@ -1067,11 +1085,12 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr, true)
}

/// Parse `'label: $expr`. The label is already parsed.
fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = label.ident.span;
let label = Some(label);
self.expect(&token::Colon)?;
if self.eat_keyword(kw::While) {
let ate_colon = self.eat(&token::Colon);
let expr = if self.eat_keyword(kw::While) {
self.parse_while_expr(label, lo, attrs)
} else if self.eat_keyword(kw::For) {
self.parse_for_expr(label, lo, attrs)
@@ -1084,7 +1103,15 @@ impl<'a> Parser<'a> {
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
self.parse_expr()
}?;

if !ate_colon {
self.struct_span_err(expr.span, "labeled expression must be followed by `:`")
.span_label(lo, "the label")
.emit();
}

Ok(expr)
}

/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
17 changes: 17 additions & 0 deletions src/test/ui/parser/labeled-no-colon-expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![feature(label_break_value)]

fn main() {
'l0 while false {} //~ ERROR labeled expression must be followed by `:`
'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:`
'l2 loop {} //~ ERROR labeled expression must be followed by `:`
'l3 {} //~ ERROR labeled expression must be followed by `:`
'l4 0; //~ ERROR labeled expression must be followed by `:`
//~^ ERROR expected `while`, `for`, `loop` or `{`

macro_rules! m {
($b:block) => {
'l5 $b; //~ ERROR cannot use a `block` macro fragment here
}
}
m!({}); //~ ERROR labeled expression must be followed by `:`
}
70 changes: 70 additions & 0 deletions src/test/ui/parser/labeled-no-colon-expr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:4:5
|
LL | 'l0 while false {}
| ---^^^^^^^^^^^^^^^
| |
| the label

error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:5:5
|
LL | 'l1 for _ in 0..1 {}
| ---^^^^^^^^^^^^^^^^^
| |
| the label

error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:6:5
|
LL | 'l2 loop {}
| ---^^^^^^^^
| |
| the label

error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:7:5
|
LL | 'l3 {}
| ---^^^
| |
| the label

error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/labeled-no-colon-expr.rs:8:9
|
LL | 'l4 0;
| ^ expected `while`, `for`, `loop` or `{` after a label

error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:8:9
|
LL | 'l4 0;
| --- ^
| |
| the label

error: cannot use a `block` macro fragment here
--> $DIR/labeled-no-colon-expr.rs:13:17
|
LL | 'l5 $b;
| ----^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: labeled expression must be followed by `:`
--> $DIR/labeled-no-colon-expr.rs:16:8
|
LL | 'l5 $b;
| --- the label
...
LL | m!({});
| ^^

error: aborting due to 8 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/parser/regions-out-of-scope-slice.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ fn foo(cond: bool) {
let mut x;

if cond {
x = &'blk [1,2,3]; //~ ERROR expected `:`, found `[`
x = &'blk [1,2,3]; //~ ERROR borrow expressions cannot be annotated with lifetimes
}
}

9 changes: 6 additions & 3 deletions src/test/ui/parser/regions-out-of-scope-slice.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error: expected `:`, found `[`
--> $DIR/regions-out-of-scope-slice.rs:7:19
error: borrow expressions cannot be annotated with lifetimes
--> $DIR/regions-out-of-scope-slice.rs:7:13
|
LL | x = &'blk [1,2,3];
| ^ expected `:`
| ^----^^^^^^^^
| |
| annotated with lifetime here
| help: remove the lifetime annotation
estebank marked this conversation as resolved.
Show resolved Hide resolved

error: aborting due to previous error

3 changes: 2 additions & 1 deletion src/test/ui/parser/trait-object-lifetime-parens.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@ fn check<'a>() {
let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
let _: Box<('a) + Trait>;
//~^ ERROR expected type, found `'a`
//~| ERROR expected `:`, found `)`
//~| ERROR expected `while`, `for`, `loop` or `{` after a label
//~| ERROR expected expression, found `)`
Centril marked this conversation as resolved.
Show resolved Hide resolved
}

fn main() {}
12 changes: 9 additions & 3 deletions src/test/ui/parser/trait-object-lifetime-parens.stderr
Original file line number Diff line number Diff line change
@@ -10,11 +10,17 @@ error: parenthesized lifetime bounds are not supported
LL | let _: Box<Trait + ('a)>;
| ^^^^ help: remove the parentheses

error: expected `:`, found `)`
error: expected `while`, `for`, `loop` or `{` after a label
--> $DIR/trait-object-lifetime-parens.rs:9:19
|
LL | let _: Box<('a) + Trait>;
| ^ expected `:`
| ^ expected `while`, `for`, `loop` or `{` after a label

error: expected expression, found `)`
--> $DIR/trait-object-lifetime-parens.rs:9:19
|
LL | let _: Box<('a) + Trait>;
| ^ expected expression

error: expected type, found `'a`
--> $DIR/trait-object-lifetime-parens.rs:9:17
@@ -24,5 +30,5 @@ LL | let _: Box<('a) + Trait>;
| |
| while parsing the type for `_`

error: aborting due to 4 previous errors
error: aborting due to 5 previous errors