Skip to content

Commit 1fc6dbc

Browse files
Change expr_trailing_brace to an exhaustive match to force new expression kinds to specify whether they contain a brace
Add inline const and other possible curly brace expressions to expr_trailing_brace Add tests for `}` before `else` in `let...else` error Change to explicit cases for expressions with optional values when being checked for trailing braces Add tests for more complex cases of `}` before `else` in `let..else` statement Move other possible `}` cases into separate arm and add FIXME for future reference
1 parent 2fdd9ed commit 1fc6dbc

File tree

3 files changed

+428
-3
lines changed

3 files changed

+428
-3
lines changed

compiler/rustc_ast/src/util/classify.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,44 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
4040
| Range(_, Some(e), _)
4141
| Ret(Some(e))
4242
| Unary(_, e)
43-
| Yield(Some(e)) => {
43+
| Yield(Some(e))
44+
| Yeet(Some(e))
45+
| Become(e) => {
4446
expr = e;
4547
}
4648
Closure(closure) => {
4749
expr = &closure.body;
4850
}
4951
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
50-
| TryBlock(..) | While(..) => break Some(expr),
51-
_ => break None,
52+
| TryBlock(..) | While(..) | ConstBlock(_) => break Some(expr),
53+
54+
// FIXME: These can end in `}`, but changing these would break stable code.
55+
InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => {
56+
break None;
57+
}
58+
59+
Break(_, None)
60+
| Range(_, None, _)
61+
| Ret(None)
62+
| Yield(None)
63+
| Array(_)
64+
| Call(_, _)
65+
| MethodCall(_)
66+
| Tup(_)
67+
| Lit(_)
68+
| Cast(_, _)
69+
| Type(_, _)
70+
| Await(_, _)
71+
| Field(_, _)
72+
| Index(_, _, _)
73+
| Underscore
74+
| Path(_, _)
75+
| Continue(_)
76+
| Repeat(_, _)
77+
| Paren(_)
78+
| Try(_)
79+
| Yeet(None)
80+
| Err => break None,
5281
}
5382
}
5483
}
+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#![feature(inline_const)]
2+
#![feature(yeet_expr)]
3+
#![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete
4+
#![feature(explicit_tail_calls)]
5+
6+
fn a() {
7+
let foo = {
8+
1
9+
} else {
10+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
11+
return;
12+
};
13+
}
14+
15+
fn b() {
16+
let foo = for i in 1..2 {
17+
break;
18+
} else {
19+
//~^ ERROR `for...else` loops are not supported
20+
return;
21+
};
22+
}
23+
24+
fn c() {
25+
let foo = if true {
26+
1
27+
} else {
28+
0
29+
} else {
30+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
31+
return;
32+
};
33+
}
34+
35+
fn d() {
36+
let foo = loop {
37+
break;
38+
} else {
39+
//~^ ERROR loop...else` loops are not supported
40+
return;
41+
};
42+
}
43+
44+
fn e() {
45+
let foo = match true {
46+
true => 1,
47+
false => 0
48+
} else {
49+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
50+
return;
51+
};
52+
}
53+
54+
struct X {a: i32}
55+
fn f() {
56+
let foo = X {
57+
a: 1
58+
} else {
59+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
60+
return;
61+
};
62+
}
63+
64+
fn g() {
65+
let foo = while false {
66+
break;
67+
} else {
68+
//~^ ERROR `while...else` loops are not supported
69+
return;
70+
};
71+
}
72+
73+
fn h() {
74+
let foo = const {
75+
1
76+
} else {
77+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
78+
return;
79+
};
80+
}
81+
82+
fn i() {
83+
let foo = &{
84+
1
85+
} else {
86+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
87+
return;
88+
};
89+
}
90+
91+
fn j() {
92+
let bar = 0;
93+
let foo = bar = {
94+
1
95+
} else {
96+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
97+
return;
98+
};
99+
}
100+
101+
fn k() {
102+
let foo = 1 + {
103+
1
104+
} else {
105+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
106+
return;
107+
};
108+
}
109+
110+
fn l() {
111+
let foo = 1..{
112+
1
113+
} else {
114+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
115+
return;
116+
};
117+
}
118+
119+
fn m() {
120+
let foo = return {
121+
()
122+
} else {
123+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
124+
return;
125+
};
126+
}
127+
128+
fn n() {
129+
let foo = -{
130+
1
131+
} else {
132+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
133+
return;
134+
};
135+
}
136+
137+
fn o() -> Result<(), ()> {
138+
let foo = do yeet {
139+
()
140+
} else {
141+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
142+
return Ok(());
143+
};
144+
}
145+
146+
fn p() {
147+
let foo = become {
148+
()
149+
} else {
150+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
151+
return;
152+
};
153+
}
154+
155+
fn q() {
156+
let foo = |x: i32| {
157+
x
158+
} else {
159+
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
160+
return;
161+
};
162+
}
163+
164+
fn main() {}

0 commit comments

Comments
 (0)