Repository: rust-analyzer/rust-analyzer
Pull request #1847 (2019-09-14 23:03:45)

Allow an underscore as the identifier in `const` items
[RFC 2526](https://github.com/rust-lang/rust/issues/54912) was recently stabilized, meaning `const _: i32 = 5;` is now a valid item.

ecstatic-morse: @matklad I think more work needs to be done in the AST, since `ConstDef` is declared as a `NameOwner` in `grammar.ron`, but it now only has a name sometimes. Perhaps you could point me in the right direction?

Patch:
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index eff9d67e49..4dd80d4431 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -258,7 +258,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
         }
         T![enum] => nominal::enum_def(p, m),
         T![use] => use_item::use_item(p, m),
-        T![const] if (la == IDENT || la == T![mut]) => consts::const_def(p, m),
+        T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
         T![static] => consts::static_def(p, m),
         // test extern_block
         // extern {}
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
index e115463333..63e0e6e0c0 100644
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ b/crates/ra_parser/src/grammar/items/consts.rs
@@ -12,7 +12,16 @@ fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
     assert!(p.at(kw));
     p.bump_any();
     p.eat(T![mut]); // FIXME: validator to forbid const mut
-    name(p);
+
+    // Allow `_` in place of an identifier in a `const`.
+    let is_const_underscore = kw == T![const] && p.eat(T![_]);
+    if !is_const_underscore {
+        name(p);
+    }
+
+    // test_err static_underscore
+    // static _: i32 = 5;
+
     types::ascription(p);
     if p.eat(T![=]) {
         expressions::expr(p);


Test patch:
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.rs b/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.rs
new file mode 100644
index 0000000000..df8cecb432
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.rs
@@ -0,0 +1,1 @@
+static _: i32 = 5;
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.txt b/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.txt
new file mode 100644
index 0000000000..28f75a3418
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/err/0013_static_underscore.txt
@@ -0,0 +1,21 @@
+SOURCE_FILE@[0; 19)
+  STATIC_DEF@[0; 18)
+    STATIC_KW@[0; 6) "static"
+    WHITESPACE@[6; 7) " "
+    ERROR@[7; 8)
+      UNDERSCORE@[7; 8) "_"
+    COLON@[8; 9) ":"
+    WHITESPACE@[9; 10) " "
+    PATH_TYPE@[10; 13)
+      PATH@[10; 13)
+        PATH_SEGMENT@[10; 13)
+          NAME_REF@[10; 13)
+            IDENT@[10; 13) "i32"
+    WHITESPACE@[13; 14) " "
+    EQ@[14; 15) "="
+    WHITESPACE@[15; 16) " "
+    LITERAL@[16; 17)
+      INT_NUMBER@[16; 17) "5"
+    SEMI@[17; 18) ";"
+  WHITESPACE@[18; 19) "\n"
+error 7: expected a name
diff --git a/crates/ra_syntax/test_data/parser/ok/0024_const_item.rs b/crates/ra_syntax/test_data/parser/ok/0024_const_item.rs
index 7446859b5a..a806a209dc 100644
--- a/crates/ra_syntax/test_data/parser/ok/0024_const_item.rs
+++ b/crates/ra_syntax/test_data/parser/ok/0024_const_item.rs
@@ -1,2 +1,3 @@
+const _: u32 = 0;
 const FOO: u32 = 92;
 const mut BAR: u32 = 62;
diff --git a/crates/ra_syntax/test_data/parser/ok/0024_const_item.txt b/crates/ra_syntax/test_data/parser/ok/0024_const_item.txt
index dea8a3a978..abe9f851b6 100644
--- a/crates/ra_syntax/test_data/parser/ok/0024_const_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0024_const_item.txt
@@ -1,41 +1,59 @@
-SOURCE_FILE@[0; 46)
-  CONST_DEF@[0; 20)
+SOURCE_FILE@[0; 64)
+  CONST_DEF@[0; 17)
     CONST_KW@[0; 5) "const"
     WHITESPACE@[5; 6) " "
-    NAME@[6; 9)
-      IDENT@[6; 9) "FOO"
-    COLON@[9; 10) ":"
-    WHITESPACE@[10; 11) " "
-    PATH_TYPE@[11; 14)
-      PATH@[11; 14)
-        PATH_SEGMENT@[11; 14)
-          NAME_REF@[11; 14)
-            IDENT@[11; 14) "u32"
+    UNDERSCORE@[6; 7) "_"
+    COLON@[7; 8) ":"
+    WHITESPACE@[8; 9) " "
+    PATH_TYPE@[9; 12)
+      PATH@[9; 12)
+        PATH_SEGMENT@[9; 12)
+          NAME_REF@[9; 12)
+            IDENT@[9; 12) "u32"
+    WHITESPACE@[12; 13) " "
+    EQ@[13; 14) "="
     WHITESPACE@[14; 15) " "
-    EQ@[15; 16) "="
-    WHITESPACE@[16; 17) " "
-    LITERAL@[17; 19)
-      INT_NUMBER@[17; 19) "92"
-    SEMI@[19; 20) ";"
-  WHITESPACE@[20; 21) "\n"
-  CONST_DEF@[21; 45)
-    CONST_KW@[21; 26) "const"
-    WHITESPACE@[26; 27) " "
-    MUT_KW@[27; 30) "mut"
-    WHITESPACE@[30; 31) " "
-    NAME@[31; 34)
-      IDENT@[31; 34) "BAR"
-    COLON@[34; 35) ":"
-    WHITESPACE@[35; 36) " "
-    PATH_TYPE@[36; 39)
-      PATH@[36; 39)
-        PATH_SEGMENT@[36; 39)
-          NAME_REF@[36; 39)
-            IDENT@[36; 39) "u32"
-    WHITESPACE@[39; 40) " "
-    EQ@[40; 41) "="
-    WHITESPACE@[41; 42) " "
-    LITERAL@[42; 44)
-      INT_NUMBER@[42; 44) "62"
-    SEMI@[44; 45) ";"
-  WHITESPACE@[45; 46) "\n"
+    LITERAL@[15; 16)
+      INT_NUMBER@[15; 16) "0"
+    SEMI@[16; 17) ";"
+  WHITESPACE@[17; 18) "\n"
+  CONST_DEF@[18; 38)
+    CONST_KW@[18; 23) "const"
+    WHITESPACE@[23; 24) " "
+    NAME@[24; 27)
+      IDENT@[24; 27) "FOO"
+    COLON@[27; 28) ":"
+    WHITESPACE@[28; 29) " "
+    PATH_TYPE@[29; 32)
+      PATH@[29; 32)
+        PATH_SEGMENT@[29; 32)
+          NAME_REF@[29; 32)
+            IDENT@[29; 32) "u32"
+    WHITESPACE@[32; 33) " "
+    EQ@[33; 34) "="
+    WHITESPACE@[34; 35) " "
+    LITERAL@[35; 37)
+      INT_NUMBER@[35; 37) "92"
+    SEMI@[37; 38) ";"
+  WHITESPACE@[38; 39) "\n"
+  CONST_DEF@[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"
+    SEMI@[62; 63) ";"
+  WHITESPACE@[63; 64) "\n"