Repository: rust-analyzer/rust-analyzer (rust)

Issue:
box_syntax/pattern not supported
```rust
let x: Box<i32> = box 1i32;
let box y = x;
```
cc https://github.com/rust-lang/rust/issues/49733

Pull request description:
fix: box_syntax/pattern
Closes #1412 
r? @matklad 

Patch:
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 725fb99f66..41be283d00 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -74,6 +74,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
         T![if] => if_expr(p),
 
         T![loop] => loop_expr(p, None),
+        T![box] => box_expr(p, None),
         T![for] => for_expr(p, None),
         T![while] => while_expr(p, None),
         T![try] => try_block_expr(p, None),
@@ -507,3 +508,17 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     block(p);
     m.complete(p, TRY_EXPR)
 }
+
+// test box_expr
+// fn foo() {
+//     let x = box 1i32;
+// }
+fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
+    assert!(p.at(T![box]));
+    let m = m.unwrap_or_else(|| p.start());
+    p.bump();
+    if p.at_ts(EXPR_FIRST) {
+        expr(p);
+    }
+    m.complete(p, BOX_EXPR)
+}
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 16ae9da631..46034942a9 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -60,6 +60,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
     let la1 = p.nth(1);
     if la0 == T![ref]
         || la0 == T![mut]
+        || la0 == T![box]
         || (la0 == IDENT && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
     {
         return Some(bind_pat(p, true));
@@ -260,9 +261,11 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) {
 //     let ref mut d = ();
 //     let e @ _ = ();
 //     let ref mut f @ g @ _ = ();
+//     let box i = Box::new(1i32);
 // }
 fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     let m = p.start();
+    p.eat(T![box]);
     p.eat(T![ref]);
     p.eat(T![mut]);
     name(p);
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 036415eacd..374fd5aec5 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -104,6 +104,7 @@ pub enum SyntaxKind {
     MOVE_KW,
     RETURN_KW,
     TRY_KW,
+    BOX_KW,
     AUTO_KW,
     DEFAULT_KW,
     EXISTENTIAL_KW,
@@ -187,6 +188,7 @@ pub enum SyntaxKind {
     NAMED_FIELD_LIST,
     NAMED_FIELD,
     TRY_BLOCK_EXPR,
+    BOX_EXPR,
     CALL_EXPR,
     INDEX_EXPR,
     METHOD_CALL_EXPR,
@@ -335,6 +337,7 @@ macro_rules! T {
     (move) => { $crate::SyntaxKind::MOVE_KW };
     (return) => { $crate::SyntaxKind::RETURN_KW };
     (try) => { $crate::SyntaxKind::TRY_KW };
+    (box) => { $crate::SyntaxKind::BOX_KW };
     (auto) => { $crate::SyntaxKind::AUTO_KW };
     (default) => { $crate::SyntaxKind::DEFAULT_KW };
     (existential) => { $crate::SyntaxKind::EXISTENTIAL_KW };
@@ -394,6 +397,7 @@ impl SyntaxKind {
             | MOVE_KW
             | RETURN_KW
             | TRY_KW
+            | BOX_KW
             | AUTO_KW
             | DEFAULT_KW
             | EXISTENTIAL_KW
@@ -567,6 +571,7 @@ impl SyntaxKind {
             MOVE_KW => &SyntaxInfo { name: "MOVE_KW" },
             RETURN_KW => &SyntaxInfo { name: "RETURN_KW" },
             TRY_KW => &SyntaxInfo { name: "TRY_KW" },
+            BOX_KW => &SyntaxInfo { name: "BOX_KW" },
             AUTO_KW => &SyntaxInfo { name: "AUTO_KW" },
             DEFAULT_KW => &SyntaxInfo { name: "DEFAULT_KW" },
             EXISTENTIAL_KW => &SyntaxInfo { name: "EXISTENTIAL_KW" },
@@ -650,6 +655,7 @@ impl SyntaxKind {
             NAMED_FIELD_LIST => &SyntaxInfo { name: "NAMED_FIELD_LIST" },
             NAMED_FIELD => &SyntaxInfo { name: "NAMED_FIELD" },
             TRY_BLOCK_EXPR => &SyntaxInfo { name: "TRY_BLOCK_EXPR" },
+            BOX_EXPR => &SyntaxInfo { name: "BOX_EXPR" },
             CALL_EXPR => &SyntaxInfo { name: "CALL_EXPR" },
             INDEX_EXPR => &SyntaxInfo { name: "INDEX_EXPR" },
             METHOD_CALL_EXPR => &SyntaxInfo { name: "METHOD_CALL_EXPR" },
@@ -745,6 +751,7 @@ impl SyntaxKind {
             "move" => MOVE_KW,
             "return" => RETURN_KW,
             "try" => TRY_KW,
+            "box" => BOX_KW,
             _ => return None,
         };
         Some(kw)
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index eab55058b9..6c075a700f 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -96,6 +96,7 @@ Grammar(
         "move",
         "return",
         "try",
+        "box",
     ],
     contextual_keywords: [
         "auto",
@@ -192,6 +193,7 @@ Grammar(
         "NAMED_FIELD_LIST",
         "NAMED_FIELD",
         "TRY_BLOCK_EXPR",
+        "BOX_EXPR",
 
         // postfix
         "CALL_EXPR",
diff --git a/docs/user/README.md b/docs/user/README.md
index d563301928..af8a99a474 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -92,13 +92,7 @@ to load path and require it in `init.el`
 ## Vim and NeoVim
 
 * Install coc.nvim by following the instructions at [coc.nvim]
-  - You will need nodejs installed.
-  - You may want to include some of the sample vim configurations [from here][coc-vim-conf]
-  - Note that if you use a plugin manager other than `vim-plug`, you may need to manually
-    checkout the `release` branch wherever your plugin manager cloned it. Otherwise you will
-    get errors about a missing javascript file.
 * Add rust analyzer using: [coc.nvim wiki][coc-wiki]
-  - Use `:CocConfig` in command mode to edit the config file.
 
 ```jsonc
  "languageserver": {
@@ -107,26 +101,11 @@ to load path and require it in `init.el`
     "filetypes": ["rust"],
     "rootPatterns": ["Cargo.toml"]
   }
- }
-```
-
-For those not familiar with js, the whole file should be enclosed in `{` and `}`, with all of your config options in between. So for example, if rust-analyzer was your only language server, you could do the following:
-
-```jsonc
-{
- "languageserver": {
-  "rust": {
-    "command": "ra_lsp_server",
-    "filetypes": ["rust"],
-    "rootPatterns": ["Cargo.toml"]
-  }
- }
 }
 ```
 
 [coc.nvim]: https://github.com/neoclide/coc.nvim
 [coc-wiki]: https://github.com/neoclide/coc.nvim/wiki/Language-servers#rust
-[coc-vim-conf]: https://github.com/neoclide/coc.nvim/#example-vim-configuration
 
 
 ## Sublime Text 3


Test patch:
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.rs
index 820a9e72ce..5a93469af5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.rs
@@ -5,4 +5,5 @@ fn main() {
     let ref mut d = ();
     let e @ _ = ();
     let ref mut f @ g @ _ = ();
+    let box i = Box::new(1i32);
 }
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.txt
index ab0f88507e..189254a19a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 146)
-  FN_DEF@[0; 145)
+SOURCE_FILE@[0; 178)
+  FN_DEF@[0; 177)
     FN_KW@[0; 2) "fn"
     WHITESPACE@[2; 3) " "
     NAME@[3; 7)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 146)
       L_PAREN@[7; 8) "("
       R_PAREN@[8; 9) ")"
     WHITESPACE@[9; 10) " "
-    BLOCK@[10; 145)
+    BLOCK@[10; 177)
       L_CURLY@[10; 11) "{"
       WHITESPACE@[11; 16) "\n    "
       LET_STMT@[16; 27)
@@ -122,6 +122,35 @@ SOURCE_FILE@[0; 146)
           L_PAREN@[140; 141) "("
           R_PAREN@[141; 142) ")"
         SEMI@[142; 143) ";"
-      WHITESPACE@[143; 144) "\n"
-      R_CURLY@[144; 145) "}"
-  WHITESPACE@[145; 146) "\n"
+      WHITESPACE@[143; 148) "\n    "
+      LET_STMT@[148; 175)
+        LET_KW@[148; 151) "let"
+        WHITESPACE@[151; 152) " "
+        BIND_PAT@[152; 157)
+          BOX_KW@[152; 155) "box"
+          WHITESPACE@[155; 156) " "
+          NAME@[156; 157)
+            IDENT@[156; 157) "i"
+        WHITESPACE@[157; 158) " "
+        EQ@[158; 159) "="
+        WHITESPACE@[159; 160) " "
+        CALL_EXPR@[160; 174)
+          PATH_EXPR@[160; 168)
+            PATH@[160; 168)
+              PATH@[160; 163)
+                PATH_SEGMENT@[160; 163)
+                  NAME_REF@[160; 163)
+                    IDENT@[160; 163) "Box"
+              COLONCOLON@[163; 165) "::"
+              PATH_SEGMENT@[165; 168)
+                NAME_REF@[165; 168)
+                  IDENT@[165; 168) "new"
+          ARG_LIST@[168; 174)
+            L_PAREN@[168; 169) "("
+            LITERAL@[169; 173)
+              INT_NUMBER@[169; 173) "1i32"
+            R_PAREN@[173; 174) ")"
+        SEMI@[174; 175) ";"
+      WHITESPACE@[175; 176) "\n"
+      R_CURLY@[176; 177) "}"
+  WHITESPACE@[177; 178) "\n"
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.rs
new file mode 100644
index 0000000000..e69c81e22a
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    let x = box 1i32;
+}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.txt
new file mode 100644
index 0000000000..f4eeb7e24e
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0132_box_expr.txt
@@ -0,0 +1,31 @@
+SOURCE_FILE@[0; 35)
+  FN_DEF@[0; 34)
+    FN_KW@[0; 2) "fn"
+    WHITESPACE@[2; 3) " "
+    NAME@[3; 6)
+      IDENT@[3; 6) "foo"
+    PARAM_LIST@[6; 8)
+      L_PAREN@[6; 7) "("
+      R_PAREN@[7; 8) ")"
+    WHITESPACE@[8; 9) " "
+    BLOCK@[9; 34)
+      L_CURLY@[9; 10) "{"
+      WHITESPACE@[10; 15) "\n    "
+      LET_STMT@[15; 32)
+        LET_KW@[15; 18) "let"
+        WHITESPACE@[18; 19) " "
+        BIND_PAT@[19; 20)
+          NAME@[19; 20)
+            IDENT@[19; 20) "x"
+        WHITESPACE@[20; 21) " "
+        EQ@[21; 22) "="
+        WHITESPACE@[22; 23) " "
+        BOX_EXPR@[23; 31)
+          BOX_KW@[23; 26) "box"
+          WHITESPACE@[26; 27) " "
+          LITERAL@[27; 31)
+            INT_NUMBER@[27; 31) "1i32"
+        SEMI@[31; 32) ";"
+      WHITESPACE@[32; 33) "\n"
+      R_CURLY@[33; 34) "}"
+  WHITESPACE@[34; 35) "\n"