diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-05 07:54:22 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-10 08:32:34 +0100 |
| commit | 055733f3b3dc5d0841b9284da0c628f9d362461d (patch) | |
| tree | 08e0b7154750bb5b34271bb2e60b0802a4a4e4b6 | |
| parent | 8ee220c447911c519ebbd118e1415d961317b18d (diff) | |
| download | rust-055733f3b3dc5d0841b9284da0c628f9d362461d.tar.gz rust-055733f3b3dc5d0841b9284da0c628f9d362461d.zip | |
parse: recover on `&'lt $expr` / `'lt $expr`.
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 35 | ||||
| -rw-r--r-- | src/test/ui/parser/labeled-no-colon-expr.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/parser/labeled-no-colon-expr.stderr | 70 | ||||
| -rw-r--r-- | src/test/ui/parser/regions-out-of-scope-slice.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/parser/regions-out-of-scope-slice.stderr | 9 | ||||
| -rw-r--r-- | src/test/ui/parser/trait-object-lifetime-parens.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/parser/trait-object-lifetime-parens.stderr | 12 |
7 files changed, 136 insertions, 12 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index b1c5eaf8973..5b39701001f 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -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. diff --git a/src/test/ui/parser/labeled-no-colon-expr.rs b/src/test/ui/parser/labeled-no-colon-expr.rs new file mode 100644 index 00000000000..db9ef52c1ae --- /dev/null +++ b/src/test/ui/parser/labeled-no-colon-expr.rs @@ -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 `:` +} diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr new file mode 100644 index 00000000000..8a9e2b32400 --- /dev/null +++ b/src/test/ui/parser/labeled-no-colon-expr.stderr @@ -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 + diff --git a/src/test/ui/parser/regions-out-of-scope-slice.rs b/src/test/ui/parser/regions-out-of-scope-slice.rs index 21369d0be61..d223619e1de 100644 --- a/src/test/ui/parser/regions-out-of-scope-slice.rs +++ b/src/test/ui/parser/regions-out-of-scope-slice.rs @@ -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 } } diff --git a/src/test/ui/parser/regions-out-of-scope-slice.stderr b/src/test/ui/parser/regions-out-of-scope-slice.stderr index 8d9bf0b7a04..bbc657ffd61 100644 --- a/src/test/ui/parser/regions-out-of-scope-slice.stderr +++ b/src/test/ui/parser/regions-out-of-scope-slice.stderr @@ -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 diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs index c8b0eb684f3..dbed17f634a 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.rs +++ b/src/test/ui/parser/trait-object-lifetime-parens.rs @@ -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() {} diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index 319a308c013..367fcc28555 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -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 |
