Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9997c51

Browse files
authoredJul 12, 2022
Rollup merge of #98633 - c410-f3r:yet-another-let-chain, r=estebank
Fix last `let_chains` blocker In order to forbid things like `let x = (let y = 1);` or `if let a = 1 && { let x = let y = 1; } {}`, the parser **HAS** to know the context of `let`. This context thing is not a surprise in the parser because you can see **a lot** of ad hoc fixes mixing parsing logic with validation logic creating code that looks more like spaghetti with tomato sauce. To make things even greater, a new ad hoc fix was added to only allow `let`s in a valid `let_chains` context by checking the previously processed token. This was the only solution I could think of and believe me, I thought about it for a long time 👍 In the long term, it should be preferable to segregate different responsibilities or create a more robust and cleaner parser framework. cc #94927 cc #53667
2 parents 7615366 + 1c3bab2 commit 9997c51

File tree

9 files changed

+827
-301
lines changed

9 files changed

+827
-301
lines changed
 

‎compiler/rustc_parse/src/parser/expr.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,7 +1393,9 @@ impl<'a> Parser<'a> {
13931393
self.parse_yield_expr(attrs)
13941394
} else if self.is_do_yeet() {
13951395
self.parse_yeet_expr(attrs)
1396-
} else if self.eat_keyword(kw::Let) {
1396+
} else if self.check_keyword(kw::Let) {
1397+
self.manage_let_chains_context();
1398+
self.bump();
13971399
self.parse_let_expr(attrs)
13981400
} else if self.eat_keyword(kw::Underscore) {
13991401
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs))
@@ -2355,16 +2357,30 @@ impl<'a> Parser<'a> {
23552357
Ok(cond)
23562358
}
23572359

2360+
// Checks if `let` is in an invalid position like `let x = let y = 1;` or
2361+
// if the current `let` is in a let_chains context but nested in another
2362+
// expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`.
2363+
//
2364+
// This method expects that the current token is `let`.
2365+
fn manage_let_chains_context(&mut self) {
2366+
debug_assert!(matches!(self.token.kind, TokenKind::Ident(kw::Let, _)));
2367+
let is_in_a_let_chains_context_but_nested_in_other_expr = self.let_expr_allowed
2368+
&& !matches!(
2369+
self.prev_token.kind,
2370+
TokenKind::AndAnd
2371+
| TokenKind::CloseDelim(Delimiter::Brace)
2372+
| TokenKind::Ident(kw::If, _)
2373+
| TokenKind::Ident(kw::While, _)
2374+
);
2375+
if !self.let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr {
2376+
self.struct_span_err(self.token.span, "expected expression, found `let` statement")
2377+
.emit();
2378+
}
2379+
}
2380+
23582381
/// Parses a `let $pat = $expr` pseudo-expression.
23592382
/// The `let` token has already been eaten.
23602383
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
2361-
if !self.let_expr_allowed {
2362-
self.struct_span_err(
2363-
self.prev_token.span,
2364-
"expected expression, found `let` statement",
2365-
)
2366-
.emit();
2367-
}
23682384
let lo = self.prev_token.span;
23692385
let pat = self.parse_pat_allow_top_alt(
23702386
None,

‎src/test/ui/rfc-2294-if-let-guard/feature-gate.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ fn _if_let_guard() {
99

1010
() if (let 0 = 1) => {}
1111
//~^ ERROR `let` expressions in this position are unstable
12+
//~| ERROR expected expression, found `let` statement
1213

1314
() if (((let 0 = 1))) => {}
1415
//~^ ERROR `let` expressions in this position are unstable
16+
//~| ERROR expected expression, found `let` statement
1517

1618
() if true && let 0 = 1 => {}
1719
//~^ ERROR `if let` guards are experimental
@@ -23,13 +25,17 @@ fn _if_let_guard() {
2325

2426
() if (let 0 = 1) && true => {}
2527
//~^ ERROR `let` expressions in this position are unstable
28+
//~| ERROR expected expression, found `let` statement
2629

2730
() if true && (let 0 = 1) => {}
2831
//~^ ERROR `let` expressions in this position are unstable
32+
//~| ERROR expected expression, found `let` statement
2933

3034
() if (let 0 = 1) && (let 0 = 1) => {}
3135
//~^ ERROR `let` expressions in this position are unstable
3236
//~| ERROR `let` expressions in this position are unstable
37+
//~| ERROR expected expression, found `let` statement
38+
//~| ERROR expected expression, found `let` statement
3339

3440
() if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
3541
//~^ ERROR `if let` guards are experimental
@@ -38,6 +44,7 @@ fn _if_let_guard() {
3844
//~| ERROR `let` expressions in this position are unstable
3945
//~| ERROR `let` expressions in this position are unstable
4046
//~| ERROR `let` expressions in this position are unstable
47+
//~| ERROR expected expression, found `let` statement
4148

4249
() if let Range { start: _, end: _ } = (true..true) && false => {}
4350
//~^ ERROR `if let` guards are experimental

‎src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,59 @@
11
error: expected expression, found `let` statement
2-
--> $DIR/feature-gate.rs:59:16
2+
--> $DIR/feature-gate.rs:10:16
3+
|
4+
LL | () if (let 0 = 1) => {}
5+
| ^^^
6+
7+
error: expected expression, found `let` statement
8+
--> $DIR/feature-gate.rs:14:18
9+
|
10+
LL | () if (((let 0 = 1))) => {}
11+
| ^^^
12+
13+
error: expected expression, found `let` statement
14+
--> $DIR/feature-gate.rs:26:16
15+
|
16+
LL | () if (let 0 = 1) && true => {}
17+
| ^^^
18+
19+
error: expected expression, found `let` statement
20+
--> $DIR/feature-gate.rs:30:24
21+
|
22+
LL | () if true && (let 0 = 1) => {}
23+
| ^^^
24+
25+
error: expected expression, found `let` statement
26+
--> $DIR/feature-gate.rs:34:16
27+
|
28+
LL | () if (let 0 = 1) && (let 0 = 1) => {}
29+
| ^^^
30+
31+
error: expected expression, found `let` statement
32+
--> $DIR/feature-gate.rs:34:31
33+
|
34+
LL | () if (let 0 = 1) && (let 0 = 1) => {}
35+
| ^^^
36+
37+
error: expected expression, found `let` statement
38+
--> $DIR/feature-gate.rs:40:42
39+
|
40+
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
41+
| ^^^
42+
43+
error: expected expression, found `let` statement
44+
--> $DIR/feature-gate.rs:66:16
345
|
446
LL | use_expr!((let 0 = 1 && 0 == 0));
547
| ^^^
648

749
error: expected expression, found `let` statement
8-
--> $DIR/feature-gate.rs:62:16
50+
--> $DIR/feature-gate.rs:69:16
951
|
1052
LL | use_expr!((let 0 = 1));
1153
| ^^^
1254

1355
error: no rules expected the token `let`
14-
--> $DIR/feature-gate.rs:71:15
56+
--> $DIR/feature-gate.rs:78:15
1557
|
1658
LL | macro_rules! use_expr {
1759
| --------------------- when calling this macro
@@ -30,7 +72,7 @@ LL | () if let 0 = 1 => {}
3072
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
3173

3274
error[E0658]: `if let` guards are experimental
33-
--> $DIR/feature-gate.rs:16:12
75+
--> $DIR/feature-gate.rs:18:12
3476
|
3577
LL | () if true && let 0 = 1 => {}
3678
| ^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +82,7 @@ LL | () if true && let 0 = 1 => {}
4082
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
4183

4284
error[E0658]: `if let` guards are experimental
43-
--> $DIR/feature-gate.rs:20:12
85+
--> $DIR/feature-gate.rs:22:12
4486
|
4587
LL | () if let 0 = 1 && true => {}
4688
| ^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +92,7 @@ LL | () if let 0 = 1 && true => {}
5092
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
5193

5294
error[E0658]: `if let` guards are experimental
53-
--> $DIR/feature-gate.rs:34:12
95+
--> $DIR/feature-gate.rs:40:12
5496
|
5597
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
5698
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +102,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
60102
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
61103

62104
error[E0658]: `if let` guards are experimental
63-
--> $DIR/feature-gate.rs:42:12
105+
--> $DIR/feature-gate.rs:49:12
64106
|
65107
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
66108
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,7 +112,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
70112
= help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
71113

72114
error[E0658]: `if let` guards are experimental
73-
--> $DIR/feature-gate.rs:67:12
115+
--> $DIR/feature-gate.rs:74:12
74116
|
75117
LL | () if let 0 = 1 => {}
76118
| ^^^^^^^^^^^^
@@ -89,7 +131,7 @@ LL | () if (let 0 = 1) => {}
89131
= help: add `#![feature(let_chains)]` to the crate attributes to enable
90132

91133
error[E0658]: `let` expressions in this position are unstable
92-
--> $DIR/feature-gate.rs:13:18
134+
--> $DIR/feature-gate.rs:14:18
93135
|
94136
LL | () if (((let 0 = 1))) => {}
95137
| ^^^^^^^^^
@@ -98,7 +140,7 @@ LL | () if (((let 0 = 1))) => {}
98140
= help: add `#![feature(let_chains)]` to the crate attributes to enable
99141

100142
error[E0658]: `let` expressions in this position are unstable
101-
--> $DIR/feature-gate.rs:16:23
143+
--> $DIR/feature-gate.rs:18:23
102144
|
103145
LL | () if true && let 0 = 1 => {}
104146
| ^^^^^^^^^
@@ -107,7 +149,7 @@ LL | () if true && let 0 = 1 => {}
107149
= help: add `#![feature(let_chains)]` to the crate attributes to enable
108150

109151
error[E0658]: `let` expressions in this position are unstable
110-
--> $DIR/feature-gate.rs:20:15
152+
--> $DIR/feature-gate.rs:22:15
111153
|
112154
LL | () if let 0 = 1 && true => {}
113155
| ^^^^^^^^^
@@ -116,7 +158,7 @@ LL | () if let 0 = 1 && true => {}
116158
= help: add `#![feature(let_chains)]` to the crate attributes to enable
117159

118160
error[E0658]: `let` expressions in this position are unstable
119-
--> $DIR/feature-gate.rs:24:16
161+
--> $DIR/feature-gate.rs:26:16
120162
|
121163
LL | () if (let 0 = 1) && true => {}
122164
| ^^^^^^^^^
@@ -125,7 +167,7 @@ LL | () if (let 0 = 1) && true => {}
125167
= help: add `#![feature(let_chains)]` to the crate attributes to enable
126168

127169
error[E0658]: `let` expressions in this position are unstable
128-
--> $DIR/feature-gate.rs:27:24
170+
--> $DIR/feature-gate.rs:30:24
129171
|
130172
LL | () if true && (let 0 = 1) => {}
131173
| ^^^^^^^^^
@@ -134,7 +176,7 @@ LL | () if true && (let 0 = 1) => {}
134176
= help: add `#![feature(let_chains)]` to the crate attributes to enable
135177

136178
error[E0658]: `let` expressions in this position are unstable
137-
--> $DIR/feature-gate.rs:30:16
179+
--> $DIR/feature-gate.rs:34:16
138180
|
139181
LL | () if (let 0 = 1) && (let 0 = 1) => {}
140182
| ^^^^^^^^^
@@ -143,7 +185,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
143185
= help: add `#![feature(let_chains)]` to the crate attributes to enable
144186

145187
error[E0658]: `let` expressions in this position are unstable
146-
--> $DIR/feature-gate.rs:30:31
188+
--> $DIR/feature-gate.rs:34:31
147189
|
148190
LL | () if (let 0 = 1) && (let 0 = 1) => {}
149191
| ^^^^^^^^^
@@ -152,7 +194,7 @@ LL | () if (let 0 = 1) && (let 0 = 1) => {}
152194
= help: add `#![feature(let_chains)]` to the crate attributes to enable
153195

154196
error[E0658]: `let` expressions in this position are unstable
155-
--> $DIR/feature-gate.rs:34:15
197+
--> $DIR/feature-gate.rs:40:15
156198
|
157199
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
158200
| ^^^^^^^^^
@@ -161,7 +203,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
161203
= help: add `#![feature(let_chains)]` to the crate attributes to enable
162204

163205
error[E0658]: `let` expressions in this position are unstable
164-
--> $DIR/feature-gate.rs:34:28
206+
--> $DIR/feature-gate.rs:40:28
165207
|
166208
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
167209
| ^^^^^^^^^
@@ -170,7 +212,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
170212
= help: add `#![feature(let_chains)]` to the crate attributes to enable
171213

172214
error[E0658]: `let` expressions in this position are unstable
173-
--> $DIR/feature-gate.rs:34:42
215+
--> $DIR/feature-gate.rs:40:42
174216
|
175217
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
176218
| ^^^^^^^^^
@@ -179,7 +221,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
179221
= help: add `#![feature(let_chains)]` to the crate attributes to enable
180222

181223
error[E0658]: `let` expressions in this position are unstable
182-
--> $DIR/feature-gate.rs:34:55
224+
--> $DIR/feature-gate.rs:40:55
183225
|
184226
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
185227
| ^^^^^^^^^
@@ -188,7 +230,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
188230
= help: add `#![feature(let_chains)]` to the crate attributes to enable
189231

190232
error[E0658]: `let` expressions in this position are unstable
191-
--> $DIR/feature-gate.rs:34:68
233+
--> $DIR/feature-gate.rs:40:68
192234
|
193235
LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {}
194236
| ^^^^^^^^^
@@ -197,7 +239,7 @@ LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 =
197239
= help: add `#![feature(let_chains)]` to the crate attributes to enable
198240

199241
error[E0658]: `let` expressions in this position are unstable
200-
--> $DIR/feature-gate.rs:42:15
242+
--> $DIR/feature-gate.rs:49:15
201243
|
202244
LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
203245
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -206,7 +248,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {}
206248
= help: add `#![feature(let_chains)]` to the crate attributes to enable
207249

208250
error[E0658]: `let` expressions in this position are unstable
209-
--> $DIR/feature-gate.rs:59:16
251+
--> $DIR/feature-gate.rs:66:16
210252
|
211253
LL | use_expr!((let 0 = 1 && 0 == 0));
212254
| ^^^^^^^^^
@@ -215,14 +257,14 @@ LL | use_expr!((let 0 = 1 && 0 == 0));
215257
= help: add `#![feature(let_chains)]` to the crate attributes to enable
216258

217259
error[E0658]: `let` expressions in this position are unstable
218-
--> $DIR/feature-gate.rs:62:16
260+
--> $DIR/feature-gate.rs:69:16
219261
|
220262
LL | use_expr!((let 0 = 1));
221263
| ^^^^^^^^^
222264
|
223265
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
224266
= help: add `#![feature(let_chains)]` to the crate attributes to enable
225267

226-
error: aborting due to 25 previous errors
268+
error: aborting due to 32 previous errors
227269

228270
For more information about this error, try `rustc --explain E0658`.

‎src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs

Lines changed: 123 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,61 @@ fn main() {}
2828
fn _if() {
2929
if (let 0 = 1) {}
3030
//~^ ERROR `let` expressions are not supported here
31+
//~| ERROR expected expression, found `let` statement
3132

3233
if (((let 0 = 1))) {}
3334
//~^ ERROR `let` expressions are not supported here
35+
//~| ERROR expected expression, found `let` statement
3436

3537
if (let 0 = 1) && true {}
3638
//~^ ERROR `let` expressions are not supported here
39+
//~| ERROR expected expression, found `let` statement
3740

3841
if true && (let 0 = 1) {}
3942
//~^ ERROR `let` expressions are not supported here
43+
//~| ERROR expected expression, found `let` statement
4044

4145
if (let 0 = 1) && (let 0 = 1) {}
4246
//~^ ERROR `let` expressions are not supported here
4347
//~| ERROR `let` expressions are not supported here
48+
//~| ERROR expected expression, found `let` statement
49+
//~| ERROR expected expression, found `let` statement
4450

4551
if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
4652
//~^ ERROR `let` expressions are not supported here
4753
//~| ERROR `let` expressions are not supported here
4854
//~| ERROR `let` expressions are not supported here
55+
//~| ERROR expected expression, found `let` statement
4956
}
5057

5158
fn _while() {
5259
while (let 0 = 1) {}
5360
//~^ ERROR `let` expressions are not supported here
61+
//~| ERROR expected expression, found `let` statement
5462

5563
while (((let 0 = 1))) {}
5664
//~^ ERROR `let` expressions are not supported here
65+
//~| ERROR expected expression, found `let` statement
5766

5867
while (let 0 = 1) && true {}
5968
//~^ ERROR `let` expressions are not supported here
69+
//~| ERROR expected expression, found `let` statement
6070

6171
while true && (let 0 = 1) {}
6272
//~^ ERROR `let` expressions are not supported here
73+
//~| ERROR expected expression, found `let` statement
6374

6475
while (let 0 = 1) && (let 0 = 1) {}
6576
//~^ ERROR `let` expressions are not supported here
6677
//~| ERROR `let` expressions are not supported here
78+
//~| ERROR expected expression, found `let` statement
79+
//~| ERROR expected expression, found `let` statement
6780

6881
while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {}
6982
//~^ ERROR `let` expressions are not supported here
7083
//~| ERROR `let` expressions are not supported here
7184
//~| ERROR `let` expressions are not supported here
85+
//~| ERROR expected expression, found `let` statement
7286
}
7387

7488
fn _macros() {
@@ -89,39 +103,64 @@ fn _macros() {
89103
}
90104

91105
fn nested_within_if_expr() {
92-
if &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
93-
//~^ ERROR mismatched types
106+
if &let 0 = 0 {}
107+
//~^ ERROR `let` expressions are not supported here
108+
//~| ERROR mismatched types
109+
//~| ERROR expected expression, found `let` statement
94110

95-
if !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
96-
if *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
97-
//~^ ERROR type `bool` cannot be dereferenced
98-
if -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
99-
//~^ ERROR cannot apply unary operator `-` to type `bool`
111+
if !let 0 = 0 {}
112+
//~^ ERROR `let` expressions are not supported here
113+
//~| ERROR expected expression, found `let` statement
114+
if *let 0 = 0 {}
115+
//~^ ERROR `let` expressions are not supported here
116+
//~| ERROR type `bool` cannot be dereferenced
117+
//~| ERROR expected expression, found `let` statement
118+
if -let 0 = 0 {}
119+
//~^ ERROR `let` expressions are not supported here
120+
//~| ERROR cannot apply unary operator `-` to type `bool`
121+
//~| ERROR expected expression, found `let` statement
100122

101123
fn _check_try_binds_tighter() -> Result<(), ()> {
102124
if let 0 = 0? {}
103125
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
104126
Ok(())
105127
}
106-
if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here
107-
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
128+
if (let 0 = 0)? {}
129+
//~^ ERROR `let` expressions are not supported here
130+
//~| ERROR the `?` operator can only be applied to values that implement `Try`
108131
//~| ERROR the `?` operator can only be used in a function that returns `Result`
132+
//~| ERROR expected expression, found `let` statement
109133

110-
if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
111-
if (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
112-
if true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
113-
if true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
134+
if true || let 0 = 0 {}
135+
//~^ ERROR `let` expressions are not supported here
136+
//~| ERROR expected expression, found `let` statement
137+
if (true || let 0 = 0) {}
138+
//~^ ERROR `let` expressions are not supported here
139+
//~| ERROR expected expression, found `let` statement
140+
if true && (true || let 0 = 0) {}
141+
//~^ ERROR `let` expressions are not supported here
142+
//~| ERROR expected expression, found `let` statement
143+
if true || (true && let 0 = 0) {}
144+
//~^ ERROR `let` expressions are not supported here
114145

115146
let mut x = true;
116-
if x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
117-
//~^ ERROR mismatched types
147+
if x = let 0 = 0 {}
148+
//~^ ERROR `let` expressions are not supported here
149+
//~| ERROR mismatched types
150+
//~| ERROR expected expression, found `let` statement
118151

119-
if true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
120-
//~^ ERROR mismatched types
121-
if ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
122-
//~^ ERROR mismatched types
123-
if (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
124-
//~^ ERROR mismatched types
152+
if true..(let 0 = 0) {}
153+
//~^ ERROR `let` expressions are not supported here
154+
//~| ERROR mismatched types
155+
//~| ERROR expected expression, found `let` statement
156+
if ..(let 0 = 0) {}
157+
//~^ ERROR `let` expressions are not supported here
158+
//~| ERROR mismatched types
159+
//~| ERROR expected expression, found `let` statement
160+
if (let 0 = 0).. {}
161+
//~^ ERROR `let` expressions are not supported here
162+
//~| ERROR mismatched types
163+
//~| ERROR expected expression, found `let` statement
125164

126165
// Binds as `(let ... = true)..true &&/|| false`.
127166
if let Range { start: _, end: _ } = true..true && false {}
@@ -151,42 +190,68 @@ fn nested_within_if_expr() {
151190

152191
if let true = let true = true {}
153192
//~^ ERROR `let` expressions are not supported here
193+
//~| ERROR expected expression, found `let` statement
154194
}
155195

156196
fn nested_within_while_expr() {
157-
while &let 0 = 0 {} //~ ERROR `let` expressions are not supported here
158-
//~^ ERROR mismatched types
197+
while &let 0 = 0 {}
198+
//~^ ERROR `let` expressions are not supported here
199+
//~| ERROR mismatched types
200+
//~| ERROR expected expression, found `let` statement
159201

160-
while !let 0 = 0 {} //~ ERROR `let` expressions are not supported here
161-
while *let 0 = 0 {} //~ ERROR `let` expressions are not supported here
162-
//~^ ERROR type `bool` cannot be dereferenced
163-
while -let 0 = 0 {} //~ ERROR `let` expressions are not supported here
164-
//~^ ERROR cannot apply unary operator `-` to type `bool`
202+
while !let 0 = 0 {}
203+
//~^ ERROR `let` expressions are not supported here
204+
//~| ERROR expected expression, found `let` statement
205+
while *let 0 = 0 {}
206+
//~^ ERROR `let` expressions are not supported here
207+
//~| ERROR type `bool` cannot be dereferenced
208+
//~| ERROR expected expression, found `let` statement
209+
while -let 0 = 0 {}
210+
//~^ ERROR `let` expressions are not supported here
211+
//~| ERROR cannot apply unary operator `-` to type `bool`
212+
//~| ERROR expected expression, found `let` statement
165213

166214
fn _check_try_binds_tighter() -> Result<(), ()> {
167215
while let 0 = 0? {}
168216
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
169217
Ok(())
170218
}
171-
while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here
172-
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
219+
while (let 0 = 0)? {}
220+
//~^ ERROR `let` expressions are not supported here
221+
//~| ERROR the `?` operator can only be applied to values that implement `Try`
173222
//~| ERROR the `?` operator can only be used in a function that returns `Result`
223+
//~| ERROR expected expression, found `let` statement
174224

175-
while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here
176-
while (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
177-
while true && (true || let 0 = 0) {} //~ ERROR `let` expressions are not supported here
178-
while true || (true && let 0 = 0) {} //~ ERROR `let` expressions are not supported here
225+
while true || let 0 = 0 {}
226+
//~^ ERROR `let` expressions are not supported here
227+
//~| ERROR expected expression, found `let` statement
228+
while (true || let 0 = 0) {}
229+
//~^ ERROR `let` expressions are not supported here
230+
//~| ERROR expected expression, found `let` statement
231+
while true && (true || let 0 = 0) {}
232+
//~^ ERROR `let` expressions are not supported here
233+
//~| ERROR expected expression, found `let` statement
234+
while true || (true && let 0 = 0) {}
235+
//~^ ERROR `let` expressions are not supported here
179236

180237
let mut x = true;
181-
while x = let 0 = 0 {} //~ ERROR `let` expressions are not supported here
182-
//~^ ERROR mismatched types
238+
while x = let 0 = 0 {}
239+
//~^ ERROR `let` expressions are not supported here
240+
//~| ERROR mismatched types
241+
//~| ERROR expected expression, found `let` statement
183242

184-
while true..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
185-
//~^ ERROR mismatched types
186-
while ..(let 0 = 0) {} //~ ERROR `let` expressions are not supported here
187-
//~^ ERROR mismatched types
188-
while (let 0 = 0).. {} //~ ERROR `let` expressions are not supported here
189-
//~^ ERROR mismatched types
243+
while true..(let 0 = 0) {}
244+
//~^ ERROR `let` expressions are not supported here
245+
//~| ERROR mismatched types
246+
//~| ERROR expected expression, found `let` statement
247+
while ..(let 0 = 0) {}
248+
//~^ ERROR `let` expressions are not supported here
249+
//~| ERROR mismatched types
250+
//~| ERROR expected expression, found `let` statement
251+
while (let 0 = 0).. {}
252+
//~^ ERROR `let` expressions are not supported here
253+
//~| ERROR mismatched types
254+
//~| ERROR expected expression, found `let` statement
190255

191256
// Binds as `(let ... = true)..true &&/|| false`.
192257
while let Range { start: _, end: _ } = true..true && false {}
@@ -216,6 +281,7 @@ fn nested_within_while_expr() {
216281

217282
while let true = let true = true {}
218283
//~^ ERROR `let` expressions are not supported here
284+
//~| ERROR expected expression, found `let` statement
219285
}
220286

221287
fn not_error_because_clarified_intent() {
@@ -316,15 +382,18 @@ fn inside_const_generic_arguments() {
316382
impl<const B: bool> A<{B}> { const O: u32 = 5; }
317383

318384
if let A::<{
319-
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
385+
true && let 1 = 1
386+
//~^ ERROR `let` expressions are not supported here
320387
}>::O = 5 {}
321388

322389
while let A::<{
323-
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
390+
true && let 1 = 1
391+
//~^ ERROR `let` expressions are not supported here
324392
}>::O = 5 {}
325393

326394
if A::<{
327-
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
395+
true && let 1 = 1
396+
//~^ ERROR `let` expressions are not supported here
328397
}>::O == 5 {}
329398

330399
// In the cases above we have `ExprKind::Block` to help us out.
@@ -345,28 +414,37 @@ fn with_parenthesis() {
345414

346415
if (let Some(a) = opt && true) {
347416
//~^ ERROR `let` expressions are not supported here
417+
//~| ERROR expected expression, found `let` statement
348418
}
349419

350420
if (let Some(a) = opt) && true {
351421
//~^ ERROR `let` expressions are not supported here
422+
//~| ERROR expected expression, found `let` statement
352423
}
353424
if (let Some(a) = opt) && (let Some(b) = a) {
354425
//~^ ERROR `let` expressions are not supported here
355426
//~| ERROR `let` expressions are not supported here
427+
//~| ERROR expected expression, found `let` statement
428+
//~| ERROR expected expression, found `let` statement
356429
}
357430
if let Some(a) = opt && (true && true) {
358431
}
359432

360433
if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
361434
//~^ ERROR `let` expressions are not supported here
362435
//~| ERROR `let` expressions are not supported here
436+
//~| ERROR expected expression, found `let` statement
437+
//~| ERROR expected expression, found `let` statement
363438
}
364439
if (let Some(a) = opt && (let Some(b) = a)) && true {
365440
//~^ ERROR `let` expressions are not supported here
366441
//~| ERROR `let` expressions are not supported here
442+
//~| ERROR expected expression, found `let` statement
443+
//~| ERROR expected expression, found `let` statement
367444
}
368445
if (let Some(a) = opt && (true)) && true {
369446
//~^ ERROR `let` expressions are not supported here
447+
//~| ERROR expected expression, found `let` statement
370448
}
371449

372450
if (true && (true)) && let Some(a) = opt {

‎src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr

Lines changed: 506 additions & 212 deletions
Large diffs are not rendered by default.

‎src/test/ui/rfc-2497-if-let-chains/feature-gate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ fn _if() {
1919

2020
if let Range { start: _, end: _ } = (true..true) && false {}
2121
//~^ ERROR `let` expressions in this position are unstable [E0658]
22+
23+
if let 1 = 1 && let true = { true } && false {
24+
//~^ ERROR `let` expressions in this position are unstable [E0658]
25+
//~| ERROR `let` expressions in this position are unstable [E0658]
26+
}
2227
}
2328

2429
fn _while() {

‎src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
error: expected expression, found `let` statement
2-
--> $DIR/feature-gate.rs:50:20
2+
--> $DIR/feature-gate.rs:55:20
33
|
44
LL | #[cfg(FALSE)] (let 0 = 1);
55
| ^^^
66

77
error: expected expression, found `let` statement
8-
--> $DIR/feature-gate.rs:40:17
8+
--> $DIR/feature-gate.rs:45:17
99
|
1010
LL | noop_expr!((let 0 = 1));
1111
| ^^^
1212

1313
error: no rules expected the token `let`
14-
--> $DIR/feature-gate.rs:53:15
14+
--> $DIR/feature-gate.rs:58:15
1515
|
1616
LL | macro_rules! use_expr {
1717
| --------------------- when calling this macro
@@ -47,7 +47,25 @@ LL | if let Range { start: _, end: _ } = (true..true) && false {}
4747
= help: add `#![feature(let_chains)]` to the crate attributes to enable
4848

4949
error[E0658]: `let` expressions in this position are unstable
50-
--> $DIR/feature-gate.rs:27:19
50+
--> $DIR/feature-gate.rs:23:8
51+
|
52+
LL | if let 1 = 1 && let true = { true } && false {
53+
| ^^^^^^^^^
54+
|
55+
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
56+
= help: add `#![feature(let_chains)]` to the crate attributes to enable
57+
58+
error[E0658]: `let` expressions in this position are unstable
59+
--> $DIR/feature-gate.rs:23:21
60+
|
61+
LL | if let 1 = 1 && let true = { true } && false {
62+
| ^^^^^^^^^^^^^^^^^^^
63+
|
64+
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
65+
= help: add `#![feature(let_chains)]` to the crate attributes to enable
66+
67+
error[E0658]: `let` expressions in this position are unstable
68+
--> $DIR/feature-gate.rs:32:19
5169
|
5270
LL | while true && let 0 = 1 {}
5371
| ^^^^^^^^^
@@ -56,7 +74,7 @@ LL | while true && let 0 = 1 {}
5674
= help: add `#![feature(let_chains)]` to the crate attributes to enable
5775

5876
error[E0658]: `let` expressions in this position are unstable
59-
--> $DIR/feature-gate.rs:30:11
77+
--> $DIR/feature-gate.rs:35:11
6078
|
6179
LL | while let 0 = 1 && true {}
6280
| ^^^^^^^^^
@@ -65,7 +83,7 @@ LL | while let 0 = 1 && true {}
6583
= help: add `#![feature(let_chains)]` to the crate attributes to enable
6684

6785
error[E0658]: `let` expressions in this position are unstable
68-
--> $DIR/feature-gate.rs:33:11
86+
--> $DIR/feature-gate.rs:38:11
6987
|
7088
LL | while let Range { start: _, end: _ } = (true..true) && false {}
7189
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,7 +92,7 @@ LL | while let Range { start: _, end: _ } = (true..true) && false {}
7492
= help: add `#![feature(let_chains)]` to the crate attributes to enable
7593

7694
error[E0658]: `let` expressions in this position are unstable
77-
--> $DIR/feature-gate.rs:50:20
95+
--> $DIR/feature-gate.rs:55:20
7896
|
7997
LL | #[cfg(FALSE)] (let 0 = 1);
8098
| ^^^^^^^^^
@@ -83,14 +101,14 @@ LL | #[cfg(FALSE)] (let 0 = 1);
83101
= help: add `#![feature(let_chains)]` to the crate attributes to enable
84102

85103
error[E0658]: `let` expressions in this position are unstable
86-
--> $DIR/feature-gate.rs:40:17
104+
--> $DIR/feature-gate.rs:45:17
87105
|
88106
LL | noop_expr!((let 0 = 1));
89107
| ^^^^^^^^^
90108
|
91109
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
92110
= help: add `#![feature(let_chains)]` to the crate attributes to enable
93111

94-
error: aborting due to 11 previous errors
112+
error: aborting due to 13 previous errors
95113

96114
For more information about this error, try `rustc --explain E0658`.
Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
1-
// check-pass
2-
// known-bug
3-
41
#![feature(let_chains)]
52

63
fn main() {
74
let _opt = Some(1i32);
85

6+
#[cfg(FALSE)]
7+
{
8+
let _ = &&let Some(x) = Some(42);
9+
//~^ ERROR expected expression, found `let` statement
10+
}
11+
#[cfg(FALSE)]
12+
{
13+
if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
14+
//~^ ERROR expected expression, found `let` statement
15+
//~| ERROR expected expression, found `let` statement
16+
true
17+
}
18+
}
19+
920
#[cfg(FALSE)]
1021
{
1122
if let Some(elem) = _opt && {
1223
[1, 2, 3][let _ = ()];
24+
//~^ ERROR expected expression, found `let` statement
1325
true
1426
} {
1527
}
1628
}
29+
30+
#[cfg(FALSE)]
31+
{
32+
if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
33+
//~^ ERROR expected expression, found `let` statement
34+
true
35+
}
36+
}
37+
#[cfg(FALSE)]
38+
{
39+
if let a = 1 && {
40+
let x = let y = 1;
41+
//~^ ERROR expected expression, found `let` statement
42+
} {
43+
}
44+
}
1745
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: expected expression, found `let` statement
2+
--> $DIR/invalid-let-in-a-valid-let-context.rs:8:19
3+
|
4+
LL | let _ = &&let Some(x) = Some(42);
5+
| ^^^
6+
7+
error: expected expression, found `let` statement
8+
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:47
9+
|
10+
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
11+
| ^^^
12+
13+
error: expected expression, found `let` statement
14+
--> $DIR/invalid-let-in-a-valid-let-context.rs:13:57
15+
|
16+
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 {
17+
| ^^^
18+
19+
error: expected expression, found `let` statement
20+
--> $DIR/invalid-let-in-a-valid-let-context.rs:23:23
21+
|
22+
LL | [1, 2, 3][let _ = ()];
23+
| ^^^
24+
25+
error: expected expression, found `let` statement
26+
--> $DIR/invalid-let-in-a-valid-let-context.rs:32:47
27+
|
28+
LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 {
29+
| ^^^
30+
31+
error: expected expression, found `let` statement
32+
--> $DIR/invalid-let-in-a-valid-let-context.rs:40:21
33+
|
34+
LL | let x = let y = 1;
35+
| ^^^
36+
37+
error: aborting due to 6 previous errors
38+

0 commit comments

Comments
 (0)
Please sign in to comment.