Unnamed repository; edit this file 'description' to name the repository.
Validate `let` expressions
Emit an error if they're found in an invalid position.
Chayim Refael Friedman 2022-02-21
parent a1b7169 · commit 821b791
-rw-r--r--crates/syntax/src/validation.rs31
-rw-r--r--crates/syntax/test_data/parser/validation/invalid_let_expr.rast216
-rw-r--r--crates/syntax/test_data/parser/validation/invalid_let_expr.rs14
3 files changed, 261 insertions, 0 deletions
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 8dc47e0bd3..3ea5844c95 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -38,6 +38,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
+ ast::LetExpr(it) => validate_let_expr(it, &mut errors),
_ => (),
}
}
@@ -343,3 +344,33 @@ fn validate_const(const_: ast::Const, errors: &mut Vec<SyntaxError>) {
errors.push(SyntaxError::new("const globals cannot be mutable", mut_token.text_range()));
}
}
+
+fn validate_let_expr(let_: ast::LetExpr, errors: &mut Vec<SyntaxError>) {
+ let mut token = let_.syntax().clone();
+ loop {
+ token = match token.parent() {
+ Some(it) => it,
+ None => break,
+ };
+
+ if ast::ParenExpr::can_cast(token.kind()) {
+ continue;
+ } else if let Some(it) = ast::BinExpr::cast(token.clone()) {
+ if it.op_kind() == Some(ast::BinaryOp::LogicOp(ast::LogicOp::And)) {
+ continue;
+ }
+ } else if ast::IfExpr::can_cast(token.kind())
+ || ast::WhileExpr::can_cast(token.kind())
+ || ast::MatchGuard::can_cast(token.kind())
+ {
+ // It must be part of the condition since the expressions are inside a block.
+ return;
+ }
+
+ break;
+ }
+ errors.push(SyntaxError::new(
+ "`let` expressions are not supported here",
+ let_.syntax().text_range(),
+ ));
+}
diff --git a/crates/syntax/test_data/parser/validation/invalid_let_expr.rast b/crates/syntax/test_data/parser/validation/invalid_let_expr.rast
new file mode 100644
index 0000000000..5b37b59783
--- /dev/null
+++ b/crates/syntax/test_data/parser/validation/invalid_let_expr.rast
@@ -0,0 +1,216 @@
+error 29..41: `let` expressions are not supported here
+error 67..79: `let` expressions are not supported here
+error 126..138: `let` expressions are not supported here
diff --git a/crates/syntax/test_data/parser/validation/invalid_let_expr.rs b/crates/syntax/test_data/parser/validation/invalid_let_expr.rs
new file mode 100644
index 0000000000..1515ae5334
--- /dev/null
+++ b/crates/syntax/test_data/parser/validation/invalid_let_expr.rs
@@ -0,0 +1,14 @@
+fn foo() {
+ const _: () = let _ = None;
+
+ let _ = if true { (let _ = None) };
+
+ if true && (let _ = None) {
+ (let _ = None);
+ while let _ = None {
+ match None {
+ _ if let _ = None => { let _ = None; }
+ }
+ }
+ }
+}