Repository: rust-analyzer/rust-analyzer
Pull request #1735 (2019-08-25 10:13:22)

:arrow_up: vfs


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 84f9f8ccd1..e2938b5f8c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1080,12 +1080,13 @@ dependencies = [
 name = "ra_batch"
 version = "0.1.0"
 dependencies = [
+ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_db 0.1.0",
  "ra_hir 0.1.0",
  "ra_ide_api 0.1.0",
  "ra_project_model 0.1.0",
- "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_vfs_glob 0.1.0",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1191,7 +1192,7 @@ dependencies = [
  "ra_project_model 0.1.0",
  "ra_syntax 0.1.0",
  "ra_text_edit 0.1.0",
- "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_vfs_glob 0.1.0",
  "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1300,7 +1301,7 @@ dependencies = [
 
 [[package]]
 name = "ra_vfs"
-version = "0.2.8"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1318,7 +1319,7 @@ name = "ra_vfs_glob"
 version = "0.1.0"
 dependencies = [
  "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2120,7 +2121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
 "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum ra_rustc_lexer 0.1.0-pre.3 (registry+https://github.com/rust-lang/crates.io-index)" = "04371af481820ff8d35c7d12b503eb09cf9e1bd246269bf4a33e3d8c54fa3a4a"
-"checksum ra_vfs 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9e891866e1bb03f50a28cc01e3f244a62107c301ae674ba06b2e7a9b310ae75a"
+"checksum ra_vfs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc8b709e0b7ceec822513451b610df1b9370b01953a8bc545a041a6b3bfef01"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
diff --git a/crates/ra_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index 8e23826a41..5fc2703ee9 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -7,8 +7,9 @@ authors = ["rust-analyzer developers"]
 [dependencies]
 log = "0.4.5"
 rustc-hash = "1.0"
+crossbeam-channel = "0.3.5"
 
-ra_vfs = "0.2.0"
+ra_vfs = "0.3.0"
 ra_vfs_glob = { path = "../ra_vfs_glob" }
 ra_db = { path = "../ra_db" }
 ra_ide_api = { path = "../ra_ide_api" }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index f458ea3003..4e5bad0443 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -2,10 +2,11 @@ use std::{collections::HashSet, error::Error, path::Path};
 
 use rustc_hash::FxHashMap;
 
+use crossbeam_channel::{unbounded, Receiver};
 use ra_db::{CrateGraph, FileId, SourceRootId};
 use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags};
 use ra_project_model::{PackageRoot, ProjectWorkspace};
-use ra_vfs::{RootEntry, Vfs, VfsChange};
+use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask};
 use ra_vfs_glob::RustPackageFilterBuilder;
 
 type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
@@ -21,6 +22,8 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
     let root = std::env::current_dir()?.join(root);
     let ws = ProjectWorkspace::discover(root.as_ref())?;
     let project_roots = ws.to_roots();
+    let (sender, receiver) = unbounded();
+    let sender = Box::new(move |t| sender.send(t).unwrap());
     let (mut vfs, roots) = Vfs::new(
         project_roots
             .iter()
@@ -33,6 +36,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
                 )
             })
             .collect(),
+        sender,
     );
     let crate_graph = ws.to_crate_graph(&mut |path: &Path| {
         let vfs_file = vfs.load(path);
@@ -53,7 +57,7 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
             (source_root_id, project_root)
         })
         .collect::<FxHashMap<_, _>>();
-    let host = load(&source_roots, crate_graph, &mut vfs);
+    let host = load(&source_roots, crate_graph, &mut vfs, receiver);
     Ok((host, source_roots))
 }
 
@@ -61,6 +65,7 @@ pub fn load(
     source_roots: &FxHashMap<SourceRootId, PackageRoot>,
     crate_graph: CrateGraph,
     vfs: &mut Vfs,
+    receiver: Receiver<VfsTask>,
 ) -> AnalysisHost {
     let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
     let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
@@ -68,7 +73,6 @@ pub fn load(
     analysis_change.set_crate_graph(crate_graph);
 
     // wait until Vfs has loaded all roots
-    let receiver = vfs.task_receiver().clone();
     let mut roots_loaded = HashSet::new();
     for task in receiver {
         vfs.handle_task(task);
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 475dd5766e..301109cb8d 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -143,31 +143,3 @@ impl AstDiagnostic for MissingFields {
         ast::RecordFieldList::cast(node).unwrap()
     }
 }
-
-#[derive(Debug)]
-pub struct MissingOkInTailExpr {
-    pub file: HirFileId,
-    pub expr: AstPtr<ast::Expr>,
-}
-
-impl Diagnostic for MissingOkInTailExpr {
-    fn message(&self) -> String {
-        "wrap return expression in Ok".to_string()
-    }
-    fn source(&self) -> Source<SyntaxNodePtr> {
-        Source { file_id: self.file, ast: self.expr.into() }
-    }
-    fn as_any(&self) -> &(dyn Any + Send + 'static) {
-        self
-    }
-}
-
-impl AstDiagnostic for MissingOkInTailExpr {
-    type AST = ast::Expr;
-
-    fn ast(&self, db: &impl HirDatabase) -> Self::AST {
-        let root = db.parse_or_expand(self.file).unwrap();
-        let node = self.source().ast.to_node(&root);
-        ast::Expr::cast(node).unwrap()
-    }
-}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 7cdc7555c5..9e85849084 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -1020,7 +1020,6 @@ where
             }
 
             // FIXME: implement
-            ast::Pat::BoxPat(_) => Pat::Missing,
             ast::Pat::LiteralPat(_) => Pat::Missing,
             ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
         };
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 5d9d59ff89..62f7d41f5d 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -6,14 +6,11 @@ use ra_syntax::ast::{AstNode, RecordLit};
 use super::{Expr, ExprId, RecordLitField};
 use crate::{
     adt::AdtDef,
-    diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
+    diagnostics::{DiagnosticSink, MissingFields},
     expr::AstPtr,
-    name,
-    path::{PathKind, PathSegment},
-    ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
-    Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution,
+    ty::InferenceResult,
+    Function, HasSource, HirDatabase, Name, Path,
 };
-use ra_syntax::ast;
 
 pub(crate) struct ExprValidator<'a, 'b: 'a> {
     func: Function,
@@ -32,17 +29,11 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
 
     pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) {
         let body = self.func.body(db);
-
         for e in body.exprs() {
             if let (id, Expr::RecordLit { path, fields, spread }) = e {
                 self.validate_record_literal(id, path, fields, *spread, db);
             }
         }
-
-        let body_expr = &body[body.body_expr()];
-        if let Expr::Block { statements: _, tail: Some(t) } = body_expr {
-            self.validate_results_in_tail_expr(*t, db);
-        }
     }
 
     fn validate_record_literal(
@@ -96,42 +87,4 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
             })
         }
     }
-
-    fn validate_results_in_tail_expr(&mut self, id: ExprId, db: &impl HirDatabase) {
-        let mismatch = match self.infer.type_mismatch_for_expr(id) {
-            Some(m) => m,
-            None => return,
-        };
-
-        let std_result_path = Path {
-            kind: PathKind::Abs,
-            segments: vec![
-                PathSegment { name: name::STD, args_and_bindings: None },
-                PathSegment { name: name::RESULT_MOD, args_and_bindings: None },
-                PathSegment { name: name::RESULT_TYPE, args_and_bindings: None },
-            ],
-        };
-
-        let resolver = self.func.resolver(db);
-        let std_result_enum =
-            match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() {
-                PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e,
-                _ => return,
-            };
-
-        let std_result_ctor = TypeCtor::Adt(AdtDef::Enum(std_result_enum));
-        let params = match &mismatch.expected {
-            Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters,
-            _ => return,
-        };
-
-        if params.len() == 2 && &params[0] == &mismatch.actual {
-            let source_map = self.func.body_source_map(db);
-            let file_id = self.func.source(db).file_id;
-
-            if let Some(expr) = source_map.expr_syntax(id).and_then(|n| n.cast::<ast::Expr>()) {
-                self.sink.push(MissingOkInTailExpr { file: file_id, expr });
-            }
-        }
-    }
 }
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 9c4822d917..6d14eea8ec 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -120,8 +120,6 @@ pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")
 pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
 pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
 pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
-pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result"));
-pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result"));
 pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
 
 fn resolve_name(text: &SmolStr) -> SmolStr {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index d94e8154b0..b33de5687c 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -106,13 +106,6 @@ impl Default for BindingMode {
     }
 }
 
-/// A mismatch between an expected and an inferred type.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct TypeMismatch {
-    pub expected: Ty,
-    pub actual: Ty,
-}
-
 /// The result of type inference: A mapping from expressions and patterns to types.
 #[derive(Clone, PartialEq, Eq, Debug, Default)]
 pub struct InferenceResult {
@@ -127,7 +120,6 @@ pub struct InferenceResult {
     diagnostics: Vec<InferenceDiagnostic>,
     pub(super) type_of_expr: ArenaMap<ExprId, Ty>,
     pub(super) type_of_pat: ArenaMap<PatId, Ty>,
-    pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
 }
 
 impl InferenceResult {
@@ -149,9 +141,6 @@ impl InferenceResult {
     pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<ImplItem> {
         self.assoc_resolutions.get(&id.into()).copied()
     }
-    pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
-        self.type_mismatches.get(expr)
-    }
     pub(crate) fn add_diagnostics(
         &self,
         db: &impl HirDatabase,
@@ -1356,15 +1345,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         };
         // use a new type variable if we got Ty::Unknown here
         let ty = self.insert_type_vars_shallow(ty);
-        let could_unify = self.unify(&ty, &expected.ty);
+        self.unify(&ty, &expected.ty);
         let ty = self.resolve_ty_as_possible(&mut vec![], ty);
         self.write_expr_ty(tgt_expr, ty.clone());
-        if !could_unify {
-            self.result.type_mismatches.insert(
-                tgt_expr,
-                TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
-            );
-        }
         ty
     }
 
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 1a4882824f..c2b959cb3c 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -75,19 +75,6 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
             severity: Severity::Error,
             fix: Some(fix),
         })
-    })
-    .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
-        let node = d.ast(db);
-        let mut builder = TextEditBuilder::default();
-        let replacement = format!("Ok({})", node.syntax());
-        builder.replace(node.syntax().text_range(), replacement);
-        let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, builder.finish());
-        res.borrow_mut().push(Diagnostic {
-            range: d.highlight_range(),
-            message: d.message(),
-            severity: Severity::Error,
-            fix: Some(fix),
-        })
     });
     if let Some(m) = source_binder::module_from_file_id(db, file_id) {
         m.diagnostics(db, &mut sink);
@@ -184,11 +171,10 @@ fn check_struct_shorthand_initialization(
 #[cfg(test)]
 mod tests {
     use insta::assert_debug_snapshot_matches;
-    use join_to_string::join;
     use ra_syntax::SourceFile;
     use test_utils::assert_eq_text;
 
-    use crate::mock_analysis::{analysis_and_position, single_file};
+    use crate::mock_analysis::single_file;
 
     use super::*;
 
@@ -217,48 +203,6 @@ mod tests {
         assert_eq_text!(after, &actual);
     }
 
-    /// Takes a multi-file input fixture with annotated cursor positions,
-    /// and checks that:
-    ///  * a diagnostic is produced
-    ///  * this diagnostic touches the input cursor position
-    ///  * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
-    fn check_apply_diagnostic_fix_from_position(fixture: &str, after: &str) {
-        let (analysis, file_position) = analysis_and_position(fixture);
-        let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap();
-        let mut fix = diagnostic.fix.unwrap();
-        let edit = fix.source_file_edits.pop().unwrap().edit;
-        let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
-        let actual = edit.apply(&target_file_contents);
-
-        // Strip indent and empty lines from `after`, to match the behaviour of
-        // `parse_fixture` called from `analysis_and_position`.
-        let margin = fixture
-            .lines()
-            .filter(|it| it.trim_start().starts_with("//-"))
-            .map(|it| it.len() - it.trim_start().len())
-            .next()
-            .expect("empty fixture");
-        let after = join(after.lines().filter_map(|line| {
-            if line.len() > margin {
-                Some(&line[margin..])
-            } else {
-                None
-            }
-        }))
-        .separator("\n")
-        .suffix("\n")
-        .to_string();
-
-        assert_eq_text!(&after, &actual);
-        assert!(
-            diagnostic.range.start() <= file_position.offset
-                && diagnostic.range.end() >= file_position.offset,
-            "diagnostic range {} does not touch cursor position {}",
-            diagnostic.range,
-            file_position.offset
-        );
-    }
-
     fn check_apply_diagnostic_fix(before: &str, after: &str) {
         let (analysis, file_id) = single_file(before);
         let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
@@ -268,169 +212,12 @@ mod tests {
         assert_eq_text!(after, &actual);
     }
 
-    /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
-    /// apply to the file containing the cursor.
-    fn check_no_diagnostic_for_target_file(fixture: &str) {
-        let (analysis, file_position) = analysis_and_position(fixture);
-        let diagnostics = analysis.diagnostics(file_position.file_id).unwrap();
-        assert_eq!(diagnostics.len(), 0);
-    }
-
     fn check_no_diagnostic(content: &str) {
         let (analysis, file_id) = single_file(content);
         let diagnostics = analysis.diagnostics(file_id).unwrap();
         assert_eq!(diagnostics.len(), 0);
     }
 
-    #[test]
-    fn test_wrap_return_type() {
-        let before = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn div(x: i32, y: i32) -> Result<i32, String> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                x / y<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn div(x: i32, y: i32) -> Result<i32, String> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                Ok(x / y)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_handles_generic_functions() {
-        let before = r#"
-            //- /main.rs
-            use std::result::Result::{self, Ok, Err};
-
-            fn div<T>(x: T) -> Result<T, i32> {
-                if x == 0 {
-                    return Err(7);
-                }
-                <|>x
-            }
-
-            //- /std/lib.rs
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::result::Result::{self, Ok, Err};
-
-            fn div<T>(x: T) -> Result<T, i32> {
-                if x == 0 {
-                    return Err(7);
-                }
-                Ok(x)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_handles_type_aliases() {
-        let before = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            type MyResult<T> = Result<T, String>;
-
-            fn div(x: i32, y: i32) -> MyResult<i32> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                x <|>/ y
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        let after = r#"
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            type MyResult<T> = Result<T, String>;
-            fn div(x: i32, y: i32) -> MyResult<i32> {
-                if y == 0 {
-                    return Err("div by zero".into());
-                }
-                Ok(x / y)
-            }
-        "#;
-        check_apply_diagnostic_fix_from_position(before, after);
-    }
-
-    #[test]
-    fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
-        let content = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            fn foo() -> Result<String, i32> {
-                0<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        check_no_diagnostic_for_target_file(content);
-    }
-
-    #[test]
-    fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
-        let content = r#"
-            //- /main.rs
-            use std::{string::String, result::Result::{self, Ok, Err}};
-
-            enum SomeOtherEnum {
-                Ok(i32),
-                Err(String),
-            }
-
-            fn foo() -> SomeOtherEnum {
-                0<|>
-            }
-
-            //- /std/lib.rs
-            pub mod string {
-                pub struct String { }
-            }
-            pub mod result {
-                pub enum Result<T, E> { Ok(T), Err(E) }
-            }
-        "#;
-        check_no_diagnostic_for_target_file(content);
-    }
-
     #[test]
     fn test_fill_struct_fields_empty() {
         let before = r"
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index afeac0d8a4..e271c257bc 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -16,7 +16,7 @@ lsp-types = { version = "0.60.0", features = ["proposed"] }
 rustc-hash = "1.0"
 parking_lot = "0.9.0"
 
-ra_vfs = "0.2.7"
+ra_vfs = "0.3.0"
 thread_worker = { path = "../thread_worker" }
 ra_syntax = { path = "../ra_syntax" }
 ra_text_edit = { path = "../ra_text_edit" }
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index ce25ff162a..45bd52769b 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -217,7 +217,7 @@ fn main_loop_inner(
                 Err(RecvError) => Err("client exited without shutdown")?,
             },
             recv(task_receiver) -> task => Event::Task(task.unwrap()),
-            recv(state.vfs.read().task_receiver()) -> task => match task {
+            recv(state.task_receiver) -> task => match task {
                 Ok(task) => Event::Vfs(task),
                 Err(RecvError) => Err("vfs died")?,
             },
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 6696dff71c..cc79644698 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -3,6 +3,7 @@ use std::{
     sync::Arc,
 };
 
+use crossbeam_channel::{unbounded, Receiver};
 use gen_lsp_server::ErrorCode;
 use lsp_types::Url;
 use parking_lot::RwLock;
@@ -10,7 +11,7 @@ use ra_ide_api::{
     Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
     SourceRootId,
 };
-use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot};
+use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask};
 use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
 use relative_path::RelativePathBuf;
 
@@ -39,6 +40,7 @@ pub struct WorldState {
     pub workspaces: Arc<Vec<ProjectWorkspace>>,
     pub analysis_host: AnalysisHost,
     pub vfs: Arc<RwLock<Vfs>>,
+    pub task_receiver: Receiver<VfsTask>,
     pub latest_requests: Arc<RwLock<LatestRequests>>,
 }
 
@@ -80,8 +82,9 @@ impl WorldState {
                 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter())
             }));
         }
-
-        let (mut vfs, vfs_roots) = Vfs::new(roots);
+        let (task_sender, task_receiver) = unbounded();
+        let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
+        let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender);
         let roots_to_scan = vfs_roots.len();
         for r in vfs_roots {
             let vfs_root_path = vfs.root2path(r);
@@ -109,6 +112,7 @@ impl WorldState {
             workspaces: Arc::new(workspaces),
             analysis_host,
             vfs: Arc::new(RwLock::new(vfs)),
+            task_receiver,
             latest_requests: Default::default(),
         }
     }
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index bc942ae010..ab8fb9f6e9 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -414,6 +414,8 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
 //         X | Y if Z => (),
 //         | X | Y if Z => (),
 //         | X => (),
+//         box X => (),
+//         Some(box X) => (),
 //     };
 // }
 fn match_arm(p: &mut Parser) -> BlockLike {
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index eae70ab85f..8979aa499a 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -56,33 +56,37 @@ const PAT_RECOVERY_SET: TokenSet =
     token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
 
 fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
-    // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
-    // (T![x]).
-    let is_path_or_macro_pat =
-        |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
-
-    let m = match p.nth(0) {
-        T![box] => box_pat(p),
-        T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true),
+    let la0 = p.nth(0);
+    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));
+    }
+    if paths::is_use_path_start(p) {
+        return Some(path_pat(p));
+    }
 
-        _ if paths::is_use_path_start(p) => path_pat(p),
-        _ if is_literal_pat_start(p) => literal_pat(p),
+    if is_literal_pat_start(p) {
+        return Some(literal_pat(p));
+    }
 
+    let m = match la0 {
         T![_] => placeholder_pat(p),
         T![&] => ref_pat(p),
         T!['('] => tuple_pat(p),
         T!['['] => slice_pat(p),
-
         _ => {
             p.err_recover("expected pattern", recovery_set);
             return None;
         }
     };
-
     Some(m)
 }
 
-fn is_literal_pat_start(p: &Parser) -> bool {
+fn is_literal_pat_start(p: &mut Parser) -> bool {
     p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
         || p.at_ts(expressions::LITERAL_FIRST)
 }
@@ -161,9 +165,6 @@ fn record_field_pat_list(p: &mut Parser) {
             T![..] => p.bump(),
             IDENT if p.nth(1) == T![:] => record_field_pat(p),
             T!['{'] => error_block(p, "expected ident"),
-            T![box] => {
-                box_pat(p);
-            }
             _ => {
                 bind_pat(p, false);
             }
@@ -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);
@@ -271,17 +274,3 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
     }
     m.complete(p, BIND_PAT)
 }
-
-// test box_pat
-// fn main() {
-//     let box i = ();
-//     let box Outer { box i, j: box Inner(box &x) } = ();
-//     let box ref mut i = ();
-// }
-fn box_pat(p: &mut Parser) -> CompletedMarker {
-    assert!(p.at(T![box]));
-    let m = p.start();
-    p.bump();
-    pattern(p);
-    m.complete(p, BOX_PAT)
-}
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 8ba29ebf83..f15e98e685 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -149,7 +149,6 @@ pub enum SyntaxKind {
     IMPL_TRAIT_TYPE,
     DYN_TRAIT_TYPE,
     REF_PAT,
-    BOX_PAT,
     BIND_PAT,
     PLACEHOLDER_PAT,
     PATH_PAT,
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 90480b6ca5..07cc3e0dba 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -307,33 +307,6 @@ impl BlockExpr {
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BoxPat {
-    pub(crate) syntax: SyntaxNode,
-}
-impl AstNode for BoxPat {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        match kind {
-            BOX_PAT => true,
-            _ => false,
-        }
-    }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        if Self::can_cast(syntax.kind()) {
-            Some(Self { syntax })
-        } else {
-            None
-        }
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        &self.syntax
-    }
-}
-impl BoxPat {
-    pub fn pat(&self) -> Option<Pat> {
-        AstChildren::new(&self.syntax).next()
-    }
-}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct BreakExpr {
     pub(crate) syntax: SyntaxNode,
 }
@@ -2090,7 +2063,6 @@ impl ParenType {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Pat {
     RefPat(RefPat),
-    BoxPat(BoxPat),
     BindPat(BindPat),
     PlaceholderPat(PlaceholderPat),
     PathPat(PathPat),
@@ -2106,11 +2078,6 @@ impl From<RefPat> for Pat {
         Pat::RefPat(node)
     }
 }
-impl From<BoxPat> for Pat {
-    fn from(node: BoxPat) -> Pat {
-        Pat::BoxPat(node)
-    }
-}
 impl From<BindPat> for Pat {
     fn from(node: BindPat) -> Pat {
         Pat::BindPat(node)
@@ -2159,15 +2126,14 @@ impl From<LiteralPat> for Pat {
 impl AstNode for Pat {
     fn can_cast(kind: SyntaxKind) -> bool {
         match kind {
-            REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | RECORD_PAT
-            | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
+            REF_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT
+            | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
             _ => false,
         }
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
             REF_PAT => Pat::RefPat(RefPat { syntax }),
-            BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
             BIND_PAT => Pat::BindPat(BindPat { syntax }),
             PLACEHOLDER_PAT => Pat::PlaceholderPat(PlaceholderPat { syntax }),
             PATH_PAT => Pat::PathPat(PathPat { syntax }),
@@ -2184,7 +2150,6 @@ impl AstNode for Pat {
     fn syntax(&self) -> &SyntaxNode {
         match self {
             Pat::RefPat(it) => &it.syntax,
-            Pat::BoxPat(it) => &it.syntax,
             Pat::BindPat(it) => &it.syntax,
             Pat::PlaceholderPat(it) => &it.syntax,
             Pat::PathPat(it) => &it.syntax,
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 1836862fe0..4659192cdb 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -158,7 +158,6 @@ Grammar(
         "DYN_TRAIT_TYPE",
 
         "REF_PAT",
-        "BOX_PAT",
         "BIND_PAT",
         "PLACEHOLDER_PAT",
         "PATH_PAT",
@@ -524,7 +523,6 @@ Grammar(
         ),
 
         "RefPat": ( options: [ "Pat" ]),
-        "BoxPat": ( options: [ "Pat" ]),
         "BindPat": (
             options: [ "Pat" ],
             traits: ["NameOwner"]
@@ -554,7 +552,6 @@ Grammar(
         "Pat": (
             enum: [
                 "RefPat",
-                "BoxPat",
                 "BindPat",
                 "PlaceholderPat",
                 "PathPat",
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 992034ef0f..d24660ac3a 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -31,13 +31,6 @@ impl SyntaxNodePtr {
     pub fn kind(self) -> SyntaxKind {
         self.kind
     }
-
-    pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> {
-        if !N::can_cast(self.kind()) {
-            return None;
-        }
-        Some(AstPtr { raw: self, _ty: PhantomData })
-    }
 }
 
 /// Like `SyntaxNodePtr`, but remembers the type of node
diff --git a/crates/ra_vfs_glob/Cargo.toml b/crates/ra_vfs_glob/Cargo.toml
index 0390d7da16..09ba3d3bfe 100644
--- a/crates/ra_vfs_glob/Cargo.toml
+++ b/crates/ra_vfs_glob/Cargo.toml
@@ -5,5 +5,5 @@ version = "0.1.0"
 authors = ["rust-analyzer developers"]
 
 [dependencies]
-ra_vfs = "0.2.0"
+ra_vfs = "0.3.0"
 globset = "0.4.4"


Test patch:
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
deleted file mode 100644
index d3fa2e468c..0000000000
--- a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let ref box i = ();
-    let mut box i = ();
-    let ref mut box i = ();
-}
-
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
deleted file mode 100644
index 0cdca4b555..0000000000
--- a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-SOURCE_FILE@[0; 91)
-  FN_DEF@[0; 89)
-    FN_KW@[0; 2) "fn"
-    WHITESPACE@[2; 3) " "
-    NAME@[3; 7)
-      IDENT@[3; 7) "main"
-    PARAM_LIST@[7; 9)
-      L_PAREN@[7; 8) "("
-      R_PAREN@[8; 9) ")"
-    WHITESPACE@[9; 10) " "
-    BLOCK@[10; 89)
-      L_CURLY@[10; 11) "{"
-      WHITESPACE@[11; 16) "\n    "
-      LET_STMT@[16; 27)
-        LET_KW@[16; 19) "let"
-        WHITESPACE@[19; 20) " "
-        BIND_PAT@[20; 27)
-          REF_KW@[20; 23) "ref"
-          WHITESPACE@[23; 24) " "
-          ERROR@[24; 27)
-            BOX_KW@[24; 27) "box"
-      WHITESPACE@[27; 28) " "
-      EXPR_STMT@[28; 35)
-        BIN_EXPR@[28; 34)
-          PATH_EXPR@[28; 29)
-            PATH@[28; 29)
-              PATH_SEGMENT@[28; 29)
-                NAME_REF@[28; 29)
-                  IDENT@[28; 29) "i"
-          WHITESPACE@[29; 30) " "
-          EQ@[30; 31) "="
-          WHITESPACE@[31; 32) " "
-          TUPLE_EXPR@[32; 34)
-            L_PAREN@[32; 33) "("
-            R_PAREN@[33; 34) ")"
-        SEMI@[34; 35) ";"
-      WHITESPACE@[35; 40) "\n    "
-      LET_STMT@[40; 51)
-        LET_KW@[40; 43) "let"
-        WHITESPACE@[43; 44) " "
-        BIND_PAT@[44; 51)
-          MUT_KW@[44; 47) "mut"
-          WHITESPACE@[47; 48) " "
-          ERROR@[48; 51)
-            BOX_KW@[48; 51) "box"
-      WHITESPACE@[51; 52) " "
-      EXPR_STMT@[52; 59)
-        BIN_EXPR@[52; 58)
-          PATH_EXPR@[52; 53)
-            PATH@[52; 53)
-              PATH_SEGMENT@[52; 53)
-                NAME_REF@[52; 53)
-                  IDENT@[52; 53) "i"
-          WHITESPACE@[53; 54) " "
-          EQ@[54; 55) "="
-          WHITESPACE@[55; 56) " "
-          TUPLE_EXPR@[56; 58)
-            L_PAREN@[56; 57) "("
-            R_PAREN@[57; 58) ")"
-        SEMI@[58; 59) ";"
-      WHITESPACE@[59; 64) "\n    "
-      LET_STMT@[64; 79)
-        LET_KW@[64; 67) "let"
-        WHITESPACE@[67; 68) " "
-        BIND_PAT@[68; 79)
-          REF_KW@[68; 71) "ref"
-          WHITESPACE@[71; 72) " "
-          MUT_KW@[72; 75) "mut"
-          WHITESPACE@[75; 76) " "
-          ERROR@[76; 79)
-            BOX_KW@[76; 79) "box"
-      WHITESPACE@[79; 80) " "
-      EXPR_STMT@[80; 87)
-        BIN_EXPR@[80; 86)
-          PATH_EXPR@[80; 81)
-            PATH@[80; 81)
-              PATH_SEGMENT@[80; 81)
-                NAME_REF@[80; 81)
-                  IDENT@[80; 81) "i"
-          WHITESPACE@[81; 82) " "
-          EQ@[82; 83) "="
-          WHITESPACE@[83; 84) " "
-          TUPLE_EXPR@[84; 86)
-            L_PAREN@[84; 85) "("
-            R_PAREN@[85; 86) ")"
-        SEMI@[86; 87) ";"
-      WHITESPACE@[87; 88) "\n"
-      R_CURLY@[88; 89) "}"
-  WHITESPACE@[89; 91) "\n\n"
-error 24: expected a name
-error 27: expected SEMI
-error 48: expected a name
-error 51: expected SEMI
-error 76: expected a name
-error 79: expected SEMI
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
index 9e009e24f4..2d476278d1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rs
@@ -5,5 +5,7 @@ fn foo() {
         X | Y if Z => (),
         | X | Y if Z => (),
         | X => (),
+        box X => (),
+        Some(box X) => (),
     };
 }
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
index c2f256ac39..35f0237826 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 167)
-  FN_DEF@[0; 166)
+SOURCE_FILE@[0; 215)
+  FN_DEF@[0; 214)
     FN_KW@[0; 2) "fn"
     WHITESPACE@[2; 3) " "
     NAME@[3; 6)
@@ -8,18 +8,18 @@ SOURCE_FILE@[0; 167)
       L_PAREN@[6; 7) "("
       R_PAREN@[7; 8) ")"
     WHITESPACE@[8; 9) " "
-    BLOCK@[9; 166)
+    BLOCK@[9; 214)
       L_CURLY@[9; 10) "{"
       WHITESPACE@[10; 15) "\n    "
-      EXPR_STMT@[15; 164)
-        MATCH_EXPR@[15; 163)
+      EXPR_STMT@[15; 212)
+        MATCH_EXPR@[15; 211)
           MATCH_KW@[15; 20) "match"
           WHITESPACE@[20; 21) " "
           TUPLE_EXPR@[21; 23)
             L_PAREN@[21; 22) "("
             R_PAREN@[22; 23) ")"
           WHITESPACE@[23; 24) " "
-          MATCH_ARM_LIST@[24; 163)
+          MATCH_ARM_LIST@[24; 211)
             L_CURLY@[24; 25) "{"
             WHITESPACE@[25; 34) "\n        "
             MATCH_ARM@[34; 41)
@@ -141,9 +141,44 @@ SOURCE_FILE@[0; 167)
                 L_PAREN@[154; 155) "("
                 R_PAREN@[155; 156) ")"
             COMMA@[156; 157) ","
-            WHITESPACE@[157; 162) "\n    "
-            R_CURLY@[162; 163) "}"
-        SEMI@[163; 164) ";"
-      WHITESPACE@[164; 165) "\n"
-      R_CURLY@[165; 166) "}"
-  WHITESPACE@[166; 167) "\n"
+            WHITESPACE@[157; 166) "\n        "
+            MATCH_ARM@[166; 177)
+              BIND_PAT@[166; 171)
+                BOX_KW@[166; 169) "box"
+                WHITESPACE@[169; 170) " "
+                NAME@[170; 171)
+                  IDENT@[170; 171) "X"
+              WHITESPACE@[171; 172) " "
+              FAT_ARROW@[172; 174) "=>"
+              WHITESPACE@[174; 175) " "
+              TUPLE_EXPR@[175; 177)
+                L_PAREN@[175; 176) "("
+                R_PAREN@[176; 177) ")"
+            COMMA@[177; 178) ","
+            WHITESPACE@[178; 187) "\n        "
+            MATCH_ARM@[187; 204)
+              TUPLE_STRUCT_PAT@[187; 198)
+                PATH@[187; 191)
+                  PATH_SEGMENT@[187; 191)
+                    NAME_REF@[187; 191)
+                      IDENT@[187; 191) "Some"
+                L_PAREN@[191; 192) "("
+                BIND_PAT@[192; 197)
+                  BOX_KW@[192; 195) "box"
+                  WHITESPACE@[195; 196) " "
+                  NAME@[196; 197)
+                    IDENT@[196; 197) "X"
+                R_PAREN@[197; 198) ")"
+              WHITESPACE@[198; 199) " "
+              FAT_ARROW@[199; 201) "=>"
+              WHITESPACE@[201; 202) " "
+              TUPLE_EXPR@[202; 204)
+                L_PAREN@[202; 203) "("
+                R_PAREN@[203; 204) ")"
+            COMMA@[204; 205) ","
+            WHITESPACE@[205; 210) "\n    "
+            R_CURLY@[210; 211) "}"
+        SEMI@[211; 212) ";"
+      WHITESPACE@[212; 213) "\n"
+      R_CURLY@[213; 214) "}"
+  WHITESPACE@[214; 215) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
index 820a9e72ce..5a93469af5 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rs
+++ b/crates/ra_syntax/test_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/test_data/parser/inline/ok/0112_bind_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
index ab0f88507e..189254a19a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.txt
+++ b/crates/ra_syntax/test_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/test_data/parser/inline/ok/0143_box_pat.rs b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
deleted file mode 100644
index 9d458aa1e6..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let box i = ();
-    let box Outer { box i, j: box Inner(box &x) } = ();
-    let box ref mut i = ();
-}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
deleted file mode 100644
index f0db58143c..0000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-SOURCE_FILE@[0; 118)
-  FN_DEF@[0; 117)
-    FN_KW@[0; 2) "fn"
-    WHITESPACE@[2; 3) " "
-    NAME@[3; 7)
-      IDENT@[3; 7) "main"
-    PARAM_LIST@[7; 9)
-      L_PAREN@[7; 8) "("
-      R_PAREN@[8; 9) ")"
-    WHITESPACE@[9; 10) " "
-    BLOCK@[10; 117)
-      L_CURLY@[10; 11) "{"
-      WHITESPACE@[11; 16) "\n    "
-      LET_STMT@[16; 31)
-        LET_KW@[16; 19) "let"
-        WHITESPACE@[19; 20) " "
-        BOX_PAT@[20; 25)
-          BOX_KW@[20; 23) "box"
-          WHITESPACE@[23; 24) " "
-          BIND_PAT@[24; 25)
-            NAME@[24; 25)
-              IDENT@[24; 25) "i"
-        WHITESPACE@[25; 26) " "
-        EQ@[26; 27) "="
-        WHITESPACE@[27; 28) " "
-        TUPLE_EXPR@[28; 30)
-          L_PAREN@[28; 29) "("
-          R_PAREN@[29; 30) ")"
-        SEMI@[30; 31) ";"
-      WHITESPACE@[31; 36) "\n    "
-      LET_STMT@[36; 87)
-        LET_KW@[36; 39) "let"
-        WHITESPACE@[39; 40) " "
-        BOX_PAT@[40; 81)
-          BOX_KW@[40; 43) "box"
-          WHITESPACE@[43; 44) " "
-          RECORD_PAT@[44; 81)
-            PATH@[44; 49)
-              PATH_SEGMENT@[44; 49)
-                NAME_REF@[44; 49)
-                  IDENT@[44; 49) "Outer"
-            WHITESPACE@[49; 50) " "
-            RECORD_FIELD_PAT_LIST@[50; 81)
-              L_CURLY@[50; 51) "{"
-              WHITESPACE@[51; 52) " "
-              BOX_PAT@[52; 57)
-                BOX_KW@[52; 55) "box"
-                WHITESPACE@[55; 56) " "
-                BIND_PAT@[56; 57)
-                  NAME@[56; 57)
-                    IDENT@[56; 57) "i"
-              COMMA@[57; 58) ","
-              WHITESPACE@[58; 59) " "
-              RECORD_FIELD_PAT@[59; 79)
-                NAME@[59; 60)
-                  IDENT@[59; 60) "j"
-                COLON@[60; 61) ":"
-                WHITESPACE@[61; 62) " "
-                BOX_PAT@[62; 79)
-                  BOX_KW@[62; 65) "box"
-                  WHITESPACE@[65; 66) " "
-                  TUPLE_STRUCT_PAT@[66; 79)
-                    PATH@[66; 71)
-                      PATH_SEGMENT@[66; 71)
-                        NAME_REF@[66; 71)
-                          IDENT@[66; 71) "Inner"
-                    L_PAREN@[71; 72) "("
-                    BOX_PAT@[72; 78)
-                      BOX_KW@[72; 75) "box"
-                      WHITESPACE@[75; 76) " "
-                      REF_PAT@[76; 78)
-                        AMP@[76; 77) "&"
-                        BIND_PAT@[77; 78)
-                          NAME@[77; 78)
-                            IDENT@[77; 78) "x"
-                    R_PAREN@[78; 79) ")"
-              WHITESPACE@[79; 80) " "
-              R_CURLY@[80; 81) "}"
-        WHITESPACE@[81; 82) " "
-        EQ@[82; 83) "="
-        WHITESPACE@[83; 84) " "
-        TUPLE_EXPR@[84; 86)
-          L_PAREN@[84; 85) "("
-          R_PAREN@[85; 86) ")"
-        SEMI@[86; 87) ";"
-      WHITESPACE@[87; 92) "\n    "
-      LET_STMT@[92; 115)
-        LET_KW@[92; 95) "let"
-        WHITESPACE@[95; 96) " "
-        BOX_PAT@[96; 109)
-          BOX_KW@[96; 99) "box"
-          WHITESPACE@[99; 100) " "
-          BIND_PAT@[100; 109)
-            REF_KW@[100; 103) "ref"
-            WHITESPACE@[103; 104) " "
-            MUT_KW@[104; 107) "mut"
-            WHITESPACE@[107; 108) " "
-            NAME@[108; 109)
-              IDENT@[108; 109) "i"
-        WHITESPACE@[109; 110) " "
-        EQ@[110; 111) "="
-        WHITESPACE@[111; 112) " "
-        TUPLE_EXPR@[112; 114)
-          L_PAREN@[112; 113) "("
-          R_PAREN@[113; 114) ")"
-        SEMI@[114; 115) ";"
-      WHITESPACE@[115; 116) "\n"
-      R_CURLY@[116; 117) "}"
-  WHITESPACE@[117; 118) "\n"