Unnamed repository; edit this file 'description' to name the repository.
Validate `let` expressions
Emit an error if they're found in an invalid position.
| -rw-r--r-- | crates/syntax/src/validation.rs | 31 | ||||
| -rw-r--r-- | crates/syntax/test_data/parser/validation/invalid_let_expr.rast | 216 | ||||
| -rw-r--r-- | crates/syntax/test_data/parser/validation/invalid_let_expr.rs | 14 |
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 @@ + [email protected] "fn"
+ [email protected] " "
+ [email protected] "foo"
+ [email protected] "("
+ [email protected] ")"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] "\n "
+ [email protected] "const"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] ":"
+ [email protected] " "
+ [email protected] "("
+ [email protected] ")"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] ";"
+ [email protected] "\n\n "
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "if"
+ [email protected] " "
+ [email protected] "true"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] " "
+ [email protected] "("
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] ")"
+ [email protected] " "
+ [email protected] "}"
+ [email protected] ";"
+ [email protected] "\n\n "
+ [email protected] "if"
+ [email protected] " "
+ [email protected] "true"
+ [email protected] " "
+ [email protected] "&&"
+ [email protected] " "
+ [email protected] "("
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] ")"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] "\n "
+ [email protected] "("
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] ")"
+ [email protected] ";"
+ [email protected] "\n "
+ [email protected] "while"
+ [email protected] " "
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] "\n "
+ [email protected] "match"
+ [email protected] " "
+ [email protected] "None"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] "\n "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "if"
+ [email protected] " "
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] " "
+ [email protected] "=>"
+ [email protected] " "
+ [email protected] "{"
+ [email protected] " "
+ [email protected] "let"
+ [email protected] " "
+ [email protected] "_"
+ [email protected] " "
+ [email protected] "="
+ [email protected] " "
+ [email protected] "None"
+ [email protected] ";"
+ [email protected] " "
+ [email protected] "}"
+ [email protected] "\n "
+ [email protected] "}"
+ [email protected] "\n "
+ [email protected] "}"
+ [email protected] "\n "
+ [email protected] "}"
+ [email protected] "\n"
+ [email protected] "}"
+ [email protected] "\n"
+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; } + } + } + } +} |