Skip to content

Commit 821b791

Browse files
Validate let expressions
Emit an error if they're found in an invalid position.
1 parent a1b7169 commit 821b791

File tree

3 files changed

+261
-0
lines changed

3 files changed

+261
-0
lines changed

crates/syntax/src/validation.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
3838
ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
3939
ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
4040
ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
41+
ast::LetExpr(it) => validate_let_expr(it, &mut errors),
4142
_ => (),
4243
}
4344
}
@@ -343,3 +344,33 @@ fn validate_const(const_: ast::Const, errors: &mut Vec<SyntaxError>) {
343344
errors.push(SyntaxError::new("const globals cannot be mutable", mut_token.text_range()));
344345
}
345346
}
347+
348+
fn validate_let_expr(let_: ast::LetExpr, errors: &mut Vec<SyntaxError>) {
349+
let mut token = let_.syntax().clone();
350+
loop {
351+
token = match token.parent() {
352+
Some(it) => it,
353+
None => break,
354+
};
355+
356+
if ast::ParenExpr::can_cast(token.kind()) {
357+
continue;
358+
} else if let Some(it) = ast::BinExpr::cast(token.clone()) {
359+
if it.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) {
360+
continue;
361+
}
362+
} else if ast::IfExpr::can_cast(token.kind())
363+
|| ast::WhileExpr::can_cast(token.kind())
364+
|| ast::MatchGuard::can_cast(token.kind())
365+
{
366+
// It must be part of the condition since the expressions are inside a block.
367+
return;
368+
}
369+
370+
break;
371+
}
372+
errors.push(SyntaxError::new(
373+
"`let` expressions are not supported here",
374+
let_.syntax().text_range(),
375+
));
376+
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
65+
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
86+
87+
88+
89+
90+
91+
92+
93+
94+
95+
96+
97+
98+
99+
100+
101+
102+
103+
104+
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
144+
145+
146+
147+
148+
149+
150+
151+
152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+
174+
175+
176+
177+
178+
179+
180+
181+
182+
183+
184+
185+
186+
187+
188+
189+
190+
191+
192+
193+
194+
195+
196+
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
211+
212+
213+
214+
error 29..41: `let` expressions are not supported here
215+
error 67..79: `let` expressions are not supported here
216+
error 126..138: `let` expressions are not supported here
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn foo() {
2+
const _: () = let _ = None;
3+
4+
let _ = if true { (let _ = None) };
5+
6+
if true && (let _ = None) {
7+
(let _ = None);
8+
while let _ = None {
9+
match None {
10+
_ if let _ = None => { let _ = None; }
11+
}
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)