parse: recover on &'lt $expr
/ 'lt $expr
.
This commit is contained in:
parent
8ee220c447
commit
055733f3b3
@ -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.
|
||||
|
17
src/test/ui/parser/labeled-no-colon-expr.rs
Normal file
17
src/test/ui/parser/labeled-no-colon-expr.rs
Normal 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 `:`
|
||||
}
|
70
src/test/ui/parser/labeled-no-colon-expr.stderr
Normal file
70
src/test/ui/parser/labeled-no-colon-expr.stderr
Normal 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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user