From 70d43c3faf6cc4e6fe4833c6375d05e54874ca0d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 24 Jan 2021 02:17:41 +0100 Subject: Add validation for mutable const items --- crates/parser/src/grammar/items/consts.rs | 2 +- crates/syntax/src/validation.rs | 16 ++++++++++++++- .../parser/err/0047_mutable_const_item.rast | 22 +++++++++++++++++++++ .../parser/err/0047_mutable_const_item.rs | 1 + .../test_data/parser/ok/0024_const_item.rast | 23 +--------------------- .../syntax/test_data/parser/ok/0024_const_item.rs | 1 - 6 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 crates/syntax/test_data/parser/err/0047_mutable_const_item.rast create mode 100644 crates/syntax/test_data/parser/err/0047_mutable_const_item.rs diff --git a/crates/parser/src/grammar/items/consts.rs b/crates/parser/src/grammar/items/consts.rs index eb7d1f828..12130df40 100644 --- a/crates/parser/src/grammar/items/consts.rs +++ b/crates/parser/src/grammar/items/consts.rs @@ -13,7 +13,7 @@ pub(super) fn konst(p: &mut Parser, m: Marker) { fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) { assert!(p.at(kw)); p.bump(kw); - p.eat(T![mut]); // FIXME: validator to forbid const mut + p.eat(T![mut]); // Allow `_` in place of an identifier in a `const`. let is_const_underscore = kw == T![const] && p.eat(T![_]); diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 7694e8834..3e216fb70 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -1,4 +1,6 @@ -//! FIXME: write short doc here +//! This module implements syntax validation that the parser doesn't handle. +//! +//! A failed validation emits a diagnostic. mod block; @@ -92,6 +94,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec { match_ast! { match node { ast::Literal(it) => validate_literal(it, &mut errors), + ast::Const(it) => validate_const(it, &mut errors), ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors), ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors), ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors), @@ -362,3 +365,14 @@ fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec) { )); } } + +fn validate_const(const_: ast::Const, errors: &mut Vec) { + if let Some(mut_token) = const_ + .const_token() + .and_then(|t| t.next_token()) + .and_then(|t| algo::skip_trivia_token(t, Direction::Next)) + .filter(|t| t.kind() == T![mut]) + { + errors.push(SyntaxError::new("const globals cannot be mutable", mut_token.text_range())); + } +} diff --git a/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast new file mode 100644 index 000000000..c7eb312c9 --- /dev/null +++ b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rast @@ -0,0 +1,22 @@ +SOURCE_FILE@0..24 + CONST@0..23 + CONST_KW@0..5 "const" + WHITESPACE@5..6 " " + MUT_KW@6..9 "mut" + WHITESPACE@9..10 " " + NAME@10..13 + IDENT@10..13 "FOO" + COLON@13..14 ":" + WHITESPACE@14..15 " " + TUPLE_TYPE@15..17 + L_PAREN@15..16 "(" + R_PAREN@16..17 ")" + WHITESPACE@17..18 " " + EQ@18..19 "=" + WHITESPACE@19..20 " " + TUPLE_EXPR@20..22 + L_PAREN@20..21 "(" + R_PAREN@21..22 ")" + SEMICOLON@22..23 ";" + WHITESPACE@23..24 "\n" +error 6..9: const globals cannot be mutable diff --git a/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs new file mode 100644 index 000000000..b34336f3f --- /dev/null +++ b/crates/syntax/test_data/parser/err/0047_mutable_const_item.rs @@ -0,0 +1 @@ +const mut FOO: () = (); diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rast b/crates/syntax/test_data/parser/ok/0024_const_item.rast index dd1b9c9a0..b89ed6f98 100644 --- a/crates/syntax/test_data/parser/ok/0024_const_item.rast +++ b/crates/syntax/test_data/parser/ok/0024_const_item.rast @@ -1,4 +1,4 @@ -SOURCE_FILE@0..64 +SOURCE_FILE@0..39 CONST@0..17 CONST_KW@0..5 "const" WHITESPACE@5..6 " " @@ -36,24 +36,3 @@ SOURCE_FILE@0..64 INT_NUMBER@35..37 "92" SEMICOLON@37..38 ";" WHITESPACE@38..39 "\n" - CONST@39..63 - CONST_KW@39..44 "const" - WHITESPACE@44..45 " " - MUT_KW@45..48 "mut" - WHITESPACE@48..49 " " - NAME@49..52 - IDENT@49..52 "BAR" - COLON@52..53 ":" - WHITESPACE@53..54 " " - PATH_TYPE@54..57 - PATH@54..57 - PATH_SEGMENT@54..57 - NAME_REF@54..57 - IDENT@54..57 "u32" - WHITESPACE@57..58 " " - EQ@58..59 "=" - WHITESPACE@59..60 " " - LITERAL@60..62 - INT_NUMBER@60..62 "62" - SEMICOLON@62..63 ";" - WHITESPACE@63..64 "\n" diff --git a/crates/syntax/test_data/parser/ok/0024_const_item.rs b/crates/syntax/test_data/parser/ok/0024_const_item.rs index a806a209d..1f2ffa0da 100644 --- a/crates/syntax/test_data/parser/ok/0024_const_item.rs +++ b/crates/syntax/test_data/parser/ok/0024_const_item.rs @@ -1,3 +1,2 @@ const _: u32 = 0; const FOO: u32 = 92; -const mut BAR: u32 = 62; -- cgit v1.2.3