parse: recover on &'lt $expr / 'lt $expr.

This commit is contained in:
Mazdak Farrokhzad 2020-03-05 07:54:22 +01:00
parent 8ee220c447
commit 055733f3b3
7 changed files with 136 additions and 12 deletions

View File

@ -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) {
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.

View File

@ -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 `:`
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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
error: aborting due to previous error

View File

@ -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 `)`
}
fn main() {}

View File

@ -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