Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 055733f

Browse files
committed
parse: recover on &'lt $expr / 'lt $expr.
1 parent 8ee220c commit 055733f

File tree

7 files changed

+136
-12
lines changed

7 files changed

+136
-12
lines changed

src/librustc_parse/parser/expr.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,28 @@ impl<'a> Parser<'a> {
673673
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
674674
fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
675675
self.expect_and()?;
676+
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
677+
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
676678
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
677679
let expr = self.parse_prefix_expr(None);
678-
let (span, expr) = self.interpolated_or_expr_span(expr)?;
679-
Ok((lo.to(span), ExprKind::AddrOf(borrow_kind, mutbl, expr)))
680+
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
681+
let span = lo.to(hi);
682+
if let Some(lt) = lifetime {
683+
self.error_remove_borrow_lifetime(span, lt.ident.span);
684+
}
685+
Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
686+
}
687+
688+
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
689+
self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
690+
.span_label(lt_span, "annotated with lifetime here")
691+
.span_suggestion(
692+
lt_span,
693+
"remove the lifetime annotation",
694+
String::new(),
695+
Applicability::MachineApplicable,
696+
)
697+
.emit();
680698
}
681699

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

1088+
/// Parse `'label: $expr`. The label is already parsed.
10701089
fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P<Expr>> {
10711090
let lo = label.ident.span;
10721091
let label = Some(label);
1073-
self.expect(&token::Colon)?;
1074-
if self.eat_keyword(kw::While) {
1092+
let ate_colon = self.eat(&token::Colon);
1093+
let expr = if self.eat_keyword(kw::While) {
10751094
self.parse_while_expr(label, lo, attrs)
10761095
} else if self.eat_keyword(kw::For) {
10771096
self.parse_for_expr(label, lo, attrs)
@@ -1084,7 +1103,15 @@ impl<'a> Parser<'a> {
10841103
self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
10851104
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
10861105
self.parse_expr()
1106+
}?;
1107+
1108+
if !ate_colon {
1109+
self.struct_span_err(expr.span, "labeled expression must be followed by `:`")
1110+
.span_label(lo, "the label")
1111+
.emit();
10871112
}
1113+
1114+
Ok(expr)
10881115
}
10891116

10901117
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(label_break_value)]
2+
3+
fn main() {
4+
'l0 while false {} //~ ERROR labeled expression must be followed by `:`
5+
'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:`
6+
'l2 loop {} //~ ERROR labeled expression must be followed by `:`
7+
'l3 {} //~ ERROR labeled expression must be followed by `:`
8+
'l4 0; //~ ERROR labeled expression must be followed by `:`
9+
//~^ ERROR expected `while`, `for`, `loop` or `{`
10+
11+
macro_rules! m {
12+
($b:block) => {
13+
'l5 $b; //~ ERROR cannot use a `block` macro fragment here
14+
}
15+
}
16+
m!({}); //~ ERROR labeled expression must be followed by `:`
17+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
error: labeled expression must be followed by `:`
2+
--> $DIR/labeled-no-colon-expr.rs:4:5
3+
|
4+
LL | 'l0 while false {}
5+
| ---^^^^^^^^^^^^^^^
6+
| |
7+
| the label
8+
9+
error: labeled expression must be followed by `:`
10+
--> $DIR/labeled-no-colon-expr.rs:5:5
11+
|
12+
LL | 'l1 for _ in 0..1 {}
13+
| ---^^^^^^^^^^^^^^^^^
14+
| |
15+
| the label
16+
17+
error: labeled expression must be followed by `:`
18+
--> $DIR/labeled-no-colon-expr.rs:6:5
19+
|
20+
LL | 'l2 loop {}
21+
| ---^^^^^^^^
22+
| |
23+
| the label
24+
25+
error: labeled expression must be followed by `:`
26+
--> $DIR/labeled-no-colon-expr.rs:7:5
27+
|
28+
LL | 'l3 {}
29+
| ---^^^
30+
| |
31+
| the label
32+
33+
error: expected `while`, `for`, `loop` or `{` after a label
34+
--> $DIR/labeled-no-colon-expr.rs:8:9
35+
|
36+
LL | 'l4 0;
37+
| ^ expected `while`, `for`, `loop` or `{` after a label
38+
39+
error: labeled expression must be followed by `:`
40+
--> $DIR/labeled-no-colon-expr.rs:8:9
41+
|
42+
LL | 'l4 0;
43+
| --- ^
44+
| |
45+
| the label
46+
47+
error: cannot use a `block` macro fragment here
48+
--> $DIR/labeled-no-colon-expr.rs:13:17
49+
|
50+
LL | 'l5 $b;
51+
| ----^^
52+
| |
53+
| the `block` fragment is within this context
54+
...
55+
LL | m!({});
56+
| ------- in this macro invocation
57+
|
58+
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
59+
60+
error: labeled expression must be followed by `:`
61+
--> $DIR/labeled-no-colon-expr.rs:16:8
62+
|
63+
LL | 'l5 $b;
64+
| --- the label
65+
...
66+
LL | m!({});
67+
| ^^
68+
69+
error: aborting due to 8 previous errors
70+

src/test/ui/parser/regions-out-of-scope-slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ fn foo(cond: bool) {
44
let mut x;
55

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error: expected `:`, found `[`
2-
--> $DIR/regions-out-of-scope-slice.rs:7:19
1+
error: borrow expressions cannot be annotated with lifetimes
2+
--> $DIR/regions-out-of-scope-slice.rs:7:13
33
|
44
LL | x = &'blk [1,2,3];
5-
| ^ expected `:`
5+
| ^----^^^^^^^^
6+
| |
7+
| annotated with lifetime here
8+
| help: remove the lifetime annotation
69

710
error: aborting due to previous error
811

src/test/ui/parser/trait-object-lifetime-parens.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ fn check<'a>() {
88
let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
99
let _: Box<('a) + Trait>;
1010
//~^ ERROR expected type, found `'a`
11-
//~| ERROR expected `:`, found `)`
11+
//~| ERROR expected `while`, `for`, `loop` or `{` after a label
12+
//~| ERROR expected expression, found `)`
1213
}
1314

1415
fn main() {}

src/test/ui/parser/trait-object-lifetime-parens.stderr

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ error: parenthesized lifetime bounds are not supported
1010
LL | let _: Box<Trait + ('a)>;
1111
| ^^^^ help: remove the parentheses
1212

13-
error: expected `:`, found `)`
13+
error: expected `while`, `for`, `loop` or `{` after a label
1414
--> $DIR/trait-object-lifetime-parens.rs:9:19
1515
|
1616
LL | let _: Box<('a) + Trait>;
17-
| ^ expected `:`
17+
| ^ expected `while`, `for`, `loop` or `{` after a label
18+
19+
error: expected expression, found `)`
20+
--> $DIR/trait-object-lifetime-parens.rs:9:19
21+
|
22+
LL | let _: Box<('a) + Trait>;
23+
| ^ expected expression
1824

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

27-
error: aborting due to 4 previous errors
33+
error: aborting due to 5 previous errors
2834

0 commit comments

Comments
 (0)