Repository: rust-analyzer/rust-analyzer
Pull request #4962 (2020-06-20 11:28:29)

Implement APIs for parsing expressions, types, paths, patterns and items

davidlattimore: Just discovered that parsing `a + b` as a path "succeeded", resulting in the path `a`. I added a test for this and fixed by checking that the TokenSource as at EOF after parsing finished.
bors[bot]: :v: davidlattimore can now approve this pull request. To approve and merge a pull request, simply reply with `bors r+`. More detailed instructions are available [here](https://bors.tech/documentation/getting-started/#reviewing-pull-requests).

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index e5cf487a53..f6d5b900f6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -640,9 +640,9 @@ dependencies = [
 
 [[package]]
 name = "lsp-server"
-version = "0.3.3"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53b4ace8ebe5d2aff3687ce0ed507f6020d6a47a7de2b0d3d664ea237ffb0c62"
+checksum = "dccec31bfd027ac0dd288a78e19005fd89624d9099456e284b5241316a6c3072"
 dependencies = [
  "crossbeam-channel",
  "log",
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs
index 190c509130..c7ce0c42f7 100644
--- a/crates/paths/src/lib.rs
+++ b/crates/paths/src/lib.rs
@@ -2,7 +2,7 @@
 //! relative paths.
 use std::{
     convert::{TryFrom, TryInto},
-    io, ops,
+    ops,
     path::{Component, Path, PathBuf},
 };
 
@@ -46,9 +46,6 @@ impl TryFrom<&str> for AbsPathBuf {
 }
 
 impl AbsPathBuf {
-    pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
-        path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
-    }
     pub fn as_path(&self) -> &AbsPath {
         AbsPath::new_unchecked(self.0.as_path())
     }
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index e6af990355..bf26048f2a 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -254,12 +254,12 @@ impl CrateGraph {
             return false;
         }
 
-        if target == from {
-            return true;
-        }
-
         for dep in &self[from].dependencies {
             let crate_id = dep.crate_id;
+            if crate_id == target {
+                return true;
+            }
+
             if self.dfs_find(target, crate_id, visited) {
                 return true;
             }
@@ -369,7 +369,7 @@ mod tests {
     use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
 
     #[test]
-    fn detect_cyclic_dependency_indirect() {
+    fn it_should_panic_because_of_cycle_dependencies() {
         let mut graph = CrateGraph::default();
         let crate1 = graph.add_crate_root(
             FileId(1u32),
@@ -403,31 +403,6 @@ mod tests {
         assert!(graph.add_dep(crate3, CrateName::new("crate1").unwrap(), crate1).is_err());
     }
 
-    #[test]
-    fn detect_cyclic_dependency_direct() {
-        let mut graph = CrateGraph::default();
-        let crate1 = graph.add_crate_root(
-            FileId(1u32),
-            Edition2018,
-            None,
-            CfgOptions::default(),
-            Env::default(),
-            Default::default(),
-            Default::default(),
-        );
-        let crate2 = graph.add_crate_root(
-            FileId(2u32),
-            Edition2018,
-            None,
-            CfgOptions::default(),
-            Env::default(),
-            Default::default(),
-            Default::default(),
-        );
-        assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
-        assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err());
-    }
-
     #[test]
     fn it_works() {
         let mut graph = CrateGraph::default();
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index ffd5278ecb..1a9f6cc768 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -26,8 +26,8 @@ use hir_ty::{
     autoderef,
     display::{HirDisplayError, HirFormatter},
     expr::ExprValidator,
-    method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
-    TraitEnvironment, Ty, TyDefId, TypeCtor,
+    method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
+    TyDefId, TypeCtor,
 };
 use ra_db::{CrateId, CrateName, Edition, FileId};
 use ra_prof::profile;
@@ -186,22 +186,6 @@ impl ModuleDef {
 
         module.visibility_of(db, self)
     }
-
-    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
-        match self {
-            ModuleDef::Adt(it) => Some(it.name(db)),
-            ModuleDef::Trait(it) => Some(it.name(db)),
-            ModuleDef::Function(it) => Some(it.name(db)),
-            ModuleDef::EnumVariant(it) => Some(it.name(db)),
-            ModuleDef::TypeAlias(it) => Some(it.name(db)),
-
-            ModuleDef::Module(it) => it.name(db),
-            ModuleDef::Const(it) => it.name(db),
-            ModuleDef::Static(it) => it.name(db),
-
-            ModuleDef::BuiltinType(it) => Some(it.as_name()),
-        }
-    }
 }
 
 pub use hir_def::{
@@ -1375,27 +1359,6 @@ impl Type {
         Some(adt.into())
     }
 
-    pub fn as_dyn_trait(&self) -> Option<Trait> {
-        self.ty.value.dyn_trait().map(Into::into)
-    }
-
-    pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
-        self.ty.value.impl_trait_bounds(db).map(|it| {
-            it.into_iter()
-                .filter_map(|pred| match pred {
-                    hir_ty::GenericPredicate::Implemented(trait_ref) => {
-                        Some(Trait::from(trait_ref.trait_))
-                    }
-                    _ => None,
-                })
-                .collect()
-        })
-    }
-
-    pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
-        self.ty.value.associated_type_parent_trait(db).map(Into::into)
-    }
-
     // FIXME: provide required accessors such that it becomes implementable from outside.
     pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
         match (&self.ty.value, &other.ty.value) {
@@ -1417,80 +1380,6 @@ impl Type {
             ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
         }
     }
-
-    pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
-        // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
-        // We need a different order here.
-
-        fn walk_substs(
-            db: &dyn HirDatabase,
-            type_: &Type,
-            substs: &Substs,
-            cb: &mut impl FnMut(Type),
-        ) {
-            for ty in substs.iter() {
-                walk_type(db, &type_.derived(ty.clone()), cb);
-            }
-        }
-
-        fn walk_bounds(
-            db: &dyn HirDatabase,
-            type_: &Type,
-            bounds: &[GenericPredicate],
-            cb: &mut impl FnMut(Type),
-        ) {
-            for pred in bounds {
-                match pred {
-                    GenericPredicate::Implemented(trait_ref) => {
-                        cb(type_.clone());
-                        walk_substs(db, type_, &trait_ref.substs, cb);
-                    }
-                    _ => (),
-                }
-            }
-        }
-
-        fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
-            let ty = type_.ty.value.strip_references();
-            match ty {
-                Ty::Apply(ApplicationTy { ctor, parameters }) => {
-                    match ctor {
-                        TypeCtor::Adt(_) => {
-                            cb(type_.derived(ty.clone()));
-                        }
-                        TypeCtor::AssociatedType(_) => {
-                            if let Some(_) = ty.associated_type_parent_trait(db) {
-                                cb(type_.derived(ty.clone()));
-                            }
-                        }
-                        _ => (),
-                    }
-
-                    // adt params, tuples, etc...
-                    walk_substs(db, type_, parameters, cb);
-                }
-                Ty::Opaque(opaque_ty) => {
-                    if let Some(bounds) = ty.impl_trait_bounds(db) {
-                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
-                    }
-
-                    walk_substs(db, type_, &opaque_ty.parameters, cb);
-                }
-                Ty::Placeholder(_) => {
-                    if let Some(bounds) = ty.impl_trait_bounds(db) {
-                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
-                    }
-                }
-                Ty::Dyn(bounds) => {
-                    walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
-                }
-
-                _ => (),
-            }
-        }
-
-        walk_type(db, self, &mut cb);
-    }
 }
 
 impl HirDisplay for Type {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index b25dac28ec..b6b665de1f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -16,7 +16,7 @@ pub use hir_expand::db::{
 pub use hir_ty::db::{
     AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
     GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
-    HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery,
+    HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsForTraitQuery,
     ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery,
     InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
     TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery,
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 6a49c424a0..a232a58567 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -6,9 +6,9 @@ use std::{cell::RefCell, fmt, iter::successors};
 
 use hir_def::{
     resolver::{self, HasResolver, Resolver},
-    AsMacroCall, TraitId, VariantId,
+    AsMacroCall, TraitId,
 };
-use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo};
+use hir_expand::{hygiene::Hygiene, ExpansionInfo};
 use hir_ty::associated_type_shorthand_candidates;
 use itertools::Itertools;
 use ra_db::{FileId, FileRange};
@@ -104,13 +104,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         tree
     }
 
-    pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST {
-        let file_id = d.source().file_id;
-        let root = self.db.parse_or_expand(file_id).unwrap();
-        self.cache(root, file_id);
-        d.ast(self.db)
-    }
-
     pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
         let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);
         let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
@@ -254,10 +247,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.analyze(path.syntax()).resolve_path(self.db, path)
     }
 
-    pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
-        self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
-    }
-
     pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
         let src = self.find_file(path.syntax().clone());
         Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 757d1e397f..7c6bbea13c 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -313,16 +313,6 @@ impl SourceAnalyzer {
         })?;
         Some(macro_call_id.as_file())
     }
-
-    pub(crate) fn resolve_variant(
-        &self,
-        db: &dyn HirDatabase,
-        record_lit: ast::RecordLit,
-    ) -> Option<VariantId> {
-        let infer = self.infer.as_ref()?;
-        let expr_id = self.expr_id(db, &record_lit.into())?;
-        infer.variant_resolution_for_expr(expr_id)
-    }
 }
 
 fn scope_for(
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index af2a717c9d..edc59e5a80 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -159,7 +159,7 @@ pub struct TypeAliasId(salsa::InternId);
 type TypeAliasLoc = AssocItemLoc<ast::TypeAliasDef>;
 impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct ImplId(salsa::InternId);
 type ImplLoc = ItemLoc<ast::ImplDef>;
 impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index b8f6aac8f2..77baa4c696 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -36,8 +36,8 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
 
     // populate external prelude
     for dep in &crate_graph[def_map.krate].dependencies {
-        log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
         let dep_def_map = db.crate_def_map(dep.crate_id);
+        log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
         def_map.extern_prelude.insert(
             dep.as_name(),
             ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 7889b8d2cc..bf71d38d6b 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,15 +3,15 @@
 use std::sync::Arc;
 
 use hir_def::{
-    db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TypeParamId,
-    VariantId,
+    db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId,
+    TypeParamId, VariantId,
 };
 use ra_arena::map::ArenaMap;
 use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
 use ra_prof::profile;
 
 use crate::{
-    method_resolution::CrateImplDefs,
+    method_resolution::{CrateImplDefs, TyFingerprint},
     traits::{chalk, AssocTyValue, Impl},
     Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
     ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
@@ -70,8 +70,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)]
     fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>;
 
-    #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)]
-    fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>;
+    #[salsa::invoke(crate::traits::impls_for_trait_query)]
+    fn impls_for_trait(
+        &self,
+        krate: CrateId,
+        trait_: TraitId,
+        self_ty_fp: Option<TyFingerprint>,
+    ) -> Arc<[ImplId]>;
 
     // Interned IDs for Chalk integration
     #[salsa::interned]
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index ebd9cb08f9..2c7298714d 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,7 +6,7 @@ use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile};
 use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
 use stdx::format_to;
 
-pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm, path::Path};
+pub use hir_def::{diagnostics::UnresolvedModule, expr::MatchArm};
 pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
 
 #[derive(Debug)]
@@ -29,16 +29,6 @@ impl Diagnostic for NoSuchField {
     }
 }
 
-impl AstDiagnostic for NoSuchField {
-    type AST = ast::RecordField;
-
-    fn ast(&self, db: &impl AstDatabase) -> Self::AST {
-        let root = db.parse_or_expand(self.source().file_id).unwrap();
-        let node = self.source().value.to_node(&root);
-        ast::RecordField::cast(node).unwrap()
-    }
-}
-
 #[derive(Debug)]
 pub struct MissingFields {
     pub file: HirFileId,
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index a9565a58d1..9fd310f69a 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -10,12 +10,12 @@ use hir_def::{
     resolver::resolver_for_expr,
     AdtId, AssocContainerId, FieldId, Lookup,
 };
-use hir_expand::name::{name, Name};
+use hir_expand::name::Name;
 use ra_syntax::ast::RangeOp;
 
 use crate::{
     autoderef, method_resolution, op,
-    traits::{FnTrait, InEnvironment},
+    traits::InEnvironment,
     utils::{generics, variant_data, Generics},
     ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
     TraitRef, Ty, TypeCtor,
@@ -63,58 +63,6 @@ impl<'a> InferenceContext<'a> {
         self.resolve_ty_as_possible(ty)
     }
 
-    fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
-        let krate = self.resolver.krate()?;
-        let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
-        let output_assoc_type =
-            self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
-        let generic_params = generics(self.db.upcast(), fn_once_trait.into());
-        if generic_params.len() != 2 {
-            return None;
-        }
-
-        let mut param_builder = Substs::builder(num_args);
-        let mut arg_tys = vec![];
-        for _ in 0..num_args {
-            let arg = self.table.new_type_var();
-            param_builder = param_builder.push(arg.clone());
-            arg_tys.push(arg);
-        }
-        let parameters = param_builder.build();
-        let arg_ty = Ty::Apply(ApplicationTy {
-            ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
-            parameters,
-        });
-        let substs = Substs::build_for_generics(&generic_params)
-            .push(ty.clone())
-            .push(arg_ty.clone())
-            .build();
-
-        let trait_env = Arc::clone(&self.trait_env);
-        let implements_fn_trait =
-            Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
-        let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
-            value: implements_fn_trait.clone(),
-            environment: trait_env,
-        });
-        if self.db.trait_solve(krate, goal.value).is_some() {
-            self.obligations.push(implements_fn_trait);
-            let output_proj_ty =
-                crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
-            let return_ty = self.normalize_projection_ty(output_proj_ty);
-            Some((arg_tys, return_ty))
-        } else {
-            None
-        }
-    }
-
-    pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
-        match ty.callable_sig(self.db) {
-            Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
-            None => self.callable_sig_from_fn_trait(ty, num_args),
-        }
-    }
-
     fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
         let body = Arc::clone(&self.body); // avoid borrow checker problem
         let ty = match &body[tgt_expr] {
@@ -250,23 +198,14 @@ impl<'a> InferenceContext<'a> {
             }
             Expr::Call { callee, args } => {
                 let callee_ty = self.infer_expr(*callee, &Expectation::none());
-                let canonicalized = self.canonicalizer().canonicalize_ty(callee_ty.clone());
-                let mut derefs = autoderef(
-                    self.db,
-                    self.resolver.krate(),
-                    InEnvironment {
-                        value: canonicalized.value.clone(),
-                        environment: self.trait_env.clone(),
-                    },
-                );
-                let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
-                    .find_map(|callee_deref_ty| {
-                        self.callable_sig(
-                            &canonicalized.decanonicalize_ty(callee_deref_ty.value),
-                            args.len(),
-                        )
-                    })
-                    .unwrap_or((Vec::new(), Ty::Unknown));
+                let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) {
+                    Some(sig) => (sig.params().to_vec(), sig.ret().clone()),
+                    None => {
+                        // Not callable
+                        // FIXME: report an error
+                        (Vec::new(), Ty::Unknown)
+                    }
+                };
                 self.register_obligations_for_call(&callee_ty);
                 self.check_call_arguments(args, &param_tys);
                 self.normalize_associated_types_in(ret_ty)
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 80d7ed10ec..1ad0d83971 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -81,7 +81,7 @@ impl<'a> InferenceContext<'a> {
                 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
                 let substs = Substs::type_params_for_generics(&generics);
                 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
-                if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
+                if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() {
                     let ty = self.db.value_ty(struct_id.into()).subst(&substs);
                     return Some(ty);
                 } else {
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index f222323249..2b9372b4b1 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -73,7 +73,6 @@ pub use lower::{
 pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
 
 pub use chalk_ir::{BoundVar, DebruijnIndex};
-use itertools::Itertools;
 
 /// A type constructor or type name: this might be something like the primitive
 /// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -816,11 +815,6 @@ impl Ty {
         }
     }
 
-    /// If this is a `dyn Trait`, returns that trait.
-    pub fn dyn_trait(&self) -> Option<TraitId> {
-        self.dyn_trait_ref().map(|it| it.trait_)
-    }
-
     fn builtin_deref(&self) -> Option<Ty> {
         match self {
             Ty::Apply(a_ty) => match a_ty.ctor {
@@ -873,56 +867,13 @@ impl Ty {
         }
     }
 
-    pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
-        match self {
-            Ty::Opaque(opaque_ty) => {
-                let predicates = match opaque_ty.opaque_ty_id {
-                    OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
-                        db.return_type_impl_traits(func).map(|it| {
-                            let data = (*it)
-                                .as_ref()
-                                .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
-                            data.clone().subst(&opaque_ty.parameters)
-                        })
-                    }
-                };
-
-                predicates.map(|it| it.value)
-            }
-            Ty::Placeholder(id) => {
-                let generic_params = db.generic_params(id.parent);
-                let param_data = &generic_params.types[id.local_id];
-                match param_data.provenance {
-                    hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
-                        let predicates = db
-                            .generic_predicates_for_param(*id)
-                            .into_iter()
-                            .map(|pred| pred.value.clone())
-                            .collect_vec();
-
-                        Some(predicates)
-                    }
-                    _ => None,
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
+    /// If this is a `dyn Trait`, returns that trait.
+    pub fn dyn_trait(&self) -> Option<TraitId> {
         match self {
-            Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => {
-                match type_alias_id.lookup(db.upcast()).container {
-                    AssocContainerId::TraitId(trait_id) => Some(trait_id),
-                    _ => None,
-                }
-            }
-            Ty::Projection(projection_ty) => {
-                match projection_ty.associated_ty.lookup(db.upcast()).container {
-                    AssocContainerId::TraitId(trait_id) => Some(trait_id),
-                    _ => None,
-                }
-            }
+            Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
+                GenericPredicate::Implemented(tr) => Some(tr.trait_),
+                _ => None,
+            }),
             _ => None,
         }
     }
@@ -1106,5 +1057,5 @@ pub struct ReturnTypeImplTraits {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct ReturnTypeImplTrait {
-    pub bounds: Binders<Vec<GenericPredicate>>,
+    pub(crate) bounds: Binders<Vec<GenericPredicate>>,
 }
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index d5154f436e..42713928f4 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -337,17 +337,17 @@ impl Ty {
                     TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
                 let ty = if remaining_segments.len() == 1 {
                     let segment = remaining_segments.first().unwrap();
-                    let found = associated_type_by_name_including_super_traits(
-                        ctx.db,
-                        trait_ref.clone(),
+                    let associated_ty = associated_type_by_name_including_super_traits(
+                        ctx.db.upcast(),
+                        trait_ref.trait_,
                         &segment.name,
                     );
-                    match found {
-                        Some((super_trait_ref, associated_ty)) => {
+                    match associated_ty {
+                        Some(associated_ty) => {
                             // FIXME handle type parameters on the segment
                             Ty::Projection(ProjectionTy {
                                 associated_ty,
-                                parameters: super_trait_ref.substs,
+                                parameters: trait_ref.substs,
                             })
                         }
                         None => {
@@ -467,9 +467,6 @@ impl Ty {
                             }
                             TypeParamLoweringMode::Variable => t.substs.clone(),
                         };
-                        // We need to shift in the bound vars, since
-                        // associated_type_shorthand_candidates does not do that
-                        let substs = substs.shift_bound_vars(ctx.in_binders);
                         // FIXME handle type parameters on the segment
                         return Some(Ty::Projection(ProjectionTy {
                             associated_ty,
@@ -709,17 +706,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
         .flat_map(|segment| segment.args_and_bindings.into_iter())
         .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
         .flat_map(move |binding| {
-            let found = associated_type_by_name_including_super_traits(
-                ctx.db,
-                trait_ref.clone(),
+            let associated_ty = associated_type_by_name_including_super_traits(
+                ctx.db.upcast(),
+                trait_ref.trait_,
                 &binding.name,
             );
-            let (super_trait_ref, associated_ty) = match found {
+            let associated_ty = match associated_ty {
                 None => return SmallVec::<[GenericPredicate; 1]>::new(),
                 Some(t) => t,
             };
             let projection_ty =
-                ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
+                ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
             let mut preds = SmallVec::with_capacity(
                 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
             );
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index ed638c195a..e83b394566 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -38,53 +38,18 @@ impl TyFingerprint {
     }
 }
 
-/// A queryable and mergeable collection of impls.
 #[derive(Debug, PartialEq, Eq)]
 pub struct CrateImplDefs {
-    inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
+    impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
     impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
 }
 
 impl CrateImplDefs {
     pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> {
         let _p = profile("impls_in_crate_query");
-        let mut res = CrateImplDefs {
-            inherent_impls: FxHashMap::default(),
-            impls_by_trait: FxHashMap::default(),
-        };
-        res.fill(db, krate);
-
-        Arc::new(res)
-    }
-
-    /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
-    ///
-    /// The full set of impls that can be used by `krate` is the returned map plus all the impls
-    /// from `krate` itself.
-    pub(crate) fn impls_from_deps_query(
-        db: &dyn HirDatabase,
-        krate: CrateId,
-    ) -> Arc<CrateImplDefs> {
-        let _p = profile("impls_from_deps_query");
-        let crate_graph = db.crate_graph();
-        let mut res = CrateImplDefs {
-            inherent_impls: FxHashMap::default(),
-            impls_by_trait: FxHashMap::default(),
-        };
+        let mut res =
+            CrateImplDefs { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() };
 
-        // For each dependency, calculate `impls_from_deps` recursively, then add its own
-        // `impls_in_crate`.
-        // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid
-        // wasting memory.
-        for dep in &crate_graph[krate].dependencies {
-            res.merge(&db.impls_from_deps(dep.crate_id));
-            res.merge(&db.impls_in_crate(dep.crate_id));
-        }
-
-        Arc::new(res)
-    }
-
-    fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) {
         let crate_def_map = db.crate_def_map(krate);
         for (_module_id, module_data) in crate_def_map.modules.iter() {
             for impl_id in module_data.scope.impls() {
@@ -92,7 +57,7 @@ impl CrateImplDefs {
                     Some(tr) => {
                         let self_ty = db.impl_self_ty(impl_id);
                         let self_ty_fp = TyFingerprint::for_impl(&self_ty.value);
-                        self.impls_by_trait
+                        res.impls_by_trait
                             .entry(tr.value.trait_)
                             .or_default()
                             .entry(self_ty_fp)
@@ -102,36 +67,18 @@ impl CrateImplDefs {
                     None => {
                         let self_ty = db.impl_self_ty(impl_id);
                         if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) {
-                            self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id);
+                            res.impls.entry(self_ty_fp).or_default().push(impl_id);
                         }
                     }
                 }
             }
         }
-    }
-
-    fn merge(&mut self, other: &Self) {
-        for (fp, impls) in &other.inherent_impls {
-            let vec = self.inherent_impls.entry(*fp).or_default();
-            vec.extend(impls);
-            vec.sort();
-            vec.dedup();
-        }
 
-        for (trait_, other_map) in &other.impls_by_trait {
-            let map = self.impls_by_trait.entry(*trait_).or_default();
-            for (fp, impls) in other_map {
-                let vec = map.entry(*fp).or_default();
-                vec.extend(impls);
-                vec.sort();
-                vec.dedup();
-            }
-        }
+        Arc::new(res)
     }
-
     pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
         let fingerprint = TyFingerprint::for_impl(ty);
-        fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()
+        fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
     }
 
     pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
@@ -163,7 +110,7 @@ impl CrateImplDefs {
     }
 
     pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
-        self.inherent_impls
+        self.impls
             .values()
             .chain(self.impls_by_trait.values().flat_map(|m| m.values()))
             .flatten()
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 6f43c3a22e..6bc6d474c9 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -2,13 +2,12 @@
 use std::{panic, sync::Arc};
 
 use chalk_ir::cast::Cast;
-use hir_def::{
-    expr::ExprId, lang_item::LangItemTarget, DefWithBodyId, ImplId, TraitId, TypeAliasId,
-};
+use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
 use ra_db::{impl_intern_key, salsa, CrateId};
 use ra_prof::profile;
+use rustc_hash::FxHashSet;
 
-use crate::{db::HirDatabase, DebruijnIndex};
+use crate::{db::HirDatabase, method_resolution::TyFingerprint, DebruijnIndex};
 
 use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
 
@@ -37,6 +36,34 @@ fn create_chalk_solver() -> chalk_solve::Solver<Interner> {
     solver_choice.into_solver()
 }
 
+/// Collects impls for the given trait in the whole dependency tree of `krate`.
+pub(crate) fn impls_for_trait_query(
+    db: &dyn HirDatabase,
+    krate: CrateId,
+    trait_: TraitId,
+    self_ty_fp: Option<TyFingerprint>,
+) -> Arc<[ImplId]> {
+    // FIXME: We could be a lot smarter here - because of the orphan rules and
+    // the fact that the trait and the self type need to be in the dependency
+    // tree of a crate somewhere for an impl to exist, we could skip looking in
+    // a lot of crates completely
+    let mut impls = FxHashSet::default();
+    // We call the query recursively here. On the one hand, this means we can
+    // reuse results from queries for different crates; on the other hand, this
+    // will only ever get called for a few crates near the root of the tree (the
+    // ones the user is editing), so this may actually be a waste of memory. I'm
+    // doing it like this mainly for simplicity for now.
+    for dep in &db.crate_graph()[krate].dependencies {
+        impls.extend(db.impls_for_trait(dep.crate_id, trait_, self_ty_fp).iter());
+    }
+    let crate_impl_defs = db.impls_in_crate(krate);
+    match self_ty_fp {
+        Some(fp) => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp)),
+        None => impls.extend(crate_impl_defs.lookup_impl_defs_for_trait(trait_)),
+    }
+    impls.into_iter().collect()
+}
+
 /// A set of clauses that we assume to be true. E.g. if we are inside this function:
 /// ```rust
 /// fn foo<T: Default>(t: T) {}
@@ -271,14 +298,6 @@ impl FnTrait {
             FnTrait::Fn => "fn",
         }
     }
-
-    pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
-        let target = db.lang_item(krate, self.lang_item_name().into())?;
-        match target {
-            LangItemTarget::TraitId(t) => Some(t),
-            _ => None,
-        }
-    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 6d5f2d46a7..88a422d2cb 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -40,7 +40,7 @@ pub(super) fn get_builtin_impls(
     if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
         for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
         {
-            if let Some(actual_trait) = fn_trait.get_id(db, krate) {
+            if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) {
                 if trait_ == actual_trait {
                     let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
                     if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
@@ -128,7 +128,7 @@ fn check_closure_fn_trait_impl_prerequisites(
     data: super::ClosureFnTraitImplData,
 ) -> bool {
     // the respective Fn/FnOnce/FnMut trait needs to exist
-    if data.fn_trait.get_id(db, krate).is_none() {
+    if get_fn_trait(db, krate, data.fn_trait).is_none() {
         return false;
     }
 
@@ -136,7 +136,7 @@ fn check_closure_fn_trait_impl_prerequisites(
     // the traits having no type params, FnOnce being a supertrait
 
     // the FnOnce trait needs to exist and have an assoc type named Output
-    let fn_once_trait = match (super::FnTrait::FnOnce).get_id(db, krate) {
+    let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) {
         Some(t) => t,
         None => return false,
     };
@@ -151,9 +151,7 @@ fn closure_fn_trait_impl_datum(
     // for some closure |X, Y| -> Z:
     // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
 
-    let trait_ = data
-        .fn_trait
-        .get_id(db, krate) // get corresponding fn trait
+    let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait
         // the existence of the Fn trait has been checked before
         .expect("fn trait for closure impl missing");
 
@@ -213,7 +211,7 @@ fn closure_fn_trait_output_assoc_ty_value(
     let output_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, num_args.into()));
 
     let fn_once_trait =
-        (super::FnTrait::FnOnce).get_id(db, krate).expect("assoc ty value should not exist");
+        get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
 
     let output_ty_id = db
         .trait_data(fn_once_trait)
@@ -362,6 +360,14 @@ fn super_trait_object_unsize_impl_datum(
     BuiltinImplData { num_vars, trait_ref, where_clauses: Vec::new(), assoc_ty_values: Vec::new() }
 }
 
+fn get_fn_trait(db: &dyn HirDatabase, krate: CrateId, fn_trait: super::FnTrait) -> Option<TraitId> {
+    let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
+    match target {
+        LangItemTarget::TraitId(t) => Some(t),
+        _ => None,
+    }
+}
+
 fn get_unsize_trait(db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
     let target = db.lang_item(krate, "unsize".into())?;
     match target {
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 2f35d6d499..a72a82f5a2 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -74,26 +74,14 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
         // Note: Since we're using impls_for_trait, only impls where the trait
         // can be resolved should ever reach Chalk. `impl_datum` relies on that
         // and will panic if the trait can't be resolved.
-        let in_deps = self.db.impls_from_deps(self.krate);
-        let in_self = self.db.impls_in_crate(self.krate);
-        let impl_maps = [in_deps, in_self];
-
-        let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db);
-
-        let mut result: Vec<_> = match self_ty_fp {
-            Some(fp) => impl_maps
-                .iter()
-                .flat_map(|crate_impl_defs| {
-                    crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk)
-                })
-                .collect(),
-            None => impl_maps
-                .iter()
-                .flat_map(|crate_impl_defs| {
-                    crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk)
-                })
-                .collect(),
-        };
+        let mut result: Vec<_> = self
+            .db
+            .impls_for_trait(self.krate, trait_, self_ty_fp)
+            .iter()
+            .copied()
+            .map(Impl::ImplDef)
+            .map(|impl_| impl_.to_chalk(self.db))
+            .collect();
 
         let arg: Option<Ty> =
             parameters.get(1).map(|p| from_chalk(self.db, p.assert_ty_ref(&Interner).clone()));
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
index c45820ff05..f98350bf92 100644
--- a/crates/ra_hir_ty/src/utils.rs
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -143,14 +143,13 @@ pub(super) fn find_super_trait_path(
 }
 
 pub(super) fn associated_type_by_name_including_super_traits(
-    db: &dyn HirDatabase,
-    trait_ref: TraitRef,
+    db: &dyn DefDatabase,
+    trait_: TraitId,
     name: &Name,
-) -> Option<(TraitRef, TypeAliasId)> {
-    all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
-        let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
-        Some((t, assoc_type))
-    })
+) -> Option<TypeAliasId> {
+    all_super_traits(db, trait_)
+        .into_iter()
+        .find_map(|t| db.trait_data(t).associated_type_by_name(name))
 }
 
 pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
@@ -177,7 +176,6 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
     Generics { def, params: db.generic_params(def), parent_generics }
 }
 
-#[derive(Debug)]
 pub(crate) struct Generics {
     def: GenericDefId,
     pub(crate) params: Arc<GenericParams>,
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index a88a978d7c..fd9abb55b1 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -8,7 +8,7 @@ use std::cell::RefCell;
 
 use hir::{
     diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink},
-    HasSource, HirDisplay, Semantics, VariantDef,
+    Semantics,
 };
 use itertools::Itertools;
 use ra_db::SourceDatabase;
@@ -16,7 +16,7 @@ use ra_ide_db::RootDatabase;
 use ra_prof::profile;
 use ra_syntax::{
     algo,
-    ast::{self, edit::IndentLevel, make, AstNode},
+    ast::{self, make, AstNode},
     SyntaxNode, TextRange, T,
 };
 use ra_text_edit::{TextEdit, TextEditBuilder};
@@ -119,16 +119,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
             severity: Severity::Error,
             fix: Some(fix),
         })
-    })
-    .on::<hir::diagnostics::NoSuchField, _>(|d| {
-        res.borrow_mut().push(Diagnostic {
-            range: sema.diagnostics_range(d).range,
-            message: d.message(),
-            severity: Severity::Error,
-            fix: missing_struct_field_fix(&sema, file_id, d),
-        })
     });
-
     if let Some(m) = sema.to_module_def(file_id) {
         m.diagnostics(db, &mut sink);
     };
@@ -136,68 +127,6 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
     res.into_inner()
 }
 
-fn missing_struct_field_fix(
-    sema: &Semantics<RootDatabase>,
-    file_id: FileId,
-    d: &hir::diagnostics::NoSuchField,
-) -> Option<Fix> {
-    let record_expr = sema.ast(d);
-
-    let record_lit = ast::RecordLit::cast(record_expr.syntax().parent()?.parent()?)?;
-    let def_id = sema.resolve_variant(record_lit)?;
-    let module;
-    let record_fields = match VariantDef::from(def_id) {
-        VariantDef::Struct(s) => {
-            module = s.module(sema.db);
-            let source = s.source(sema.db);
-            let fields = source.value.field_def_list()?;
-            record_field_def_list(fields)?
-        }
-        VariantDef::Union(u) => {
-            module = u.module(sema.db);
-            let source = u.source(sema.db);
-            source.value.record_field_def_list()?
-        }
-        VariantDef::EnumVariant(e) => {
-            module = e.module(sema.db);
-            let source = e.source(sema.db);
-            let fields = source.value.field_def_list()?;
-            record_field_def_list(fields)?
-        }
-    };
-
-    let new_field_type = sema.type_of_expr(&record_expr.expr()?)?;
-    let new_field = make::record_field_def(
-        record_expr.field_name()?,
-        make::type_ref(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
-    );
-
-    let last_field = record_fields.fields().last()?;
-    let last_field_syntax = last_field.syntax();
-    let indent = IndentLevel::from_node(last_field_syntax);
-
-    let mut new_field = format!("\n{}{}", indent, new_field);
-
-    let needs_comma = !last_field_syntax.to_string().ends_with(",");
-    if needs_comma {
-        new_field = format!(",{}", new_field);
-    }
-
-    let source_change = SourceFileEdit {
-        file_id,
-        edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field),
-    };
-    let fix = Fix::new("Create field", source_change.into());
-    return Some(fix);
-
-    fn record_field_def_list(field_def_list: ast::FieldDefList) -> Option<ast::RecordFieldDefList> {
-        match field_def_list {
-            ast::FieldDefList::RecordFieldDefList(it) => Some(it),
-            ast::FieldDefList::TupleFieldDefList(_) => None,
-        }
-    }
-}
-
 fn check_unnecessary_braces_in_use_statement(
     acc: &mut Vec<Diagnostic>,
     file_id: FileId,
@@ -862,27 +791,4 @@ fn main() {
             check_struct_shorthand_initialization,
         );
     }
-
-    #[test]
-    fn test_add_field_from_usage() {
-        check_apply_diagnostic_fix(
-            r"
-            fn main() {
-                Foo { bar: 3, baz: false};
-            }
-            struct Foo {
-                bar: i32
-            }
-            ",
-            r"
-            fn main() {
-                Foo { bar: 3, baz: false};
-            }
-            struct Foo {
-                bar: i32,
-                baz: bool
-            }
-            ",
-        )
-    }
 }
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index d870e4cbce..ad78b76712 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -2,7 +2,7 @@ use std::iter::once;
 
 use hir::{
     Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay,
-    Module, ModuleDef, ModuleSource, Semantics,
+    ModuleDef, ModuleSource, Semantics,
 };
 use itertools::Itertools;
 use ra_db::SourceDatabase;
@@ -13,9 +13,7 @@ use ra_ide_db::{
 use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset};
 
 use crate::{
-    display::{
-        macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav,
-    },
+    display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav},
     runnables::runnable,
     FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
 };
@@ -26,21 +24,19 @@ pub struct HoverConfig {
     pub implementations: bool,
     pub run: bool,
     pub debug: bool,
-    pub goto_type_def: bool,
 }
 
 impl Default for HoverConfig {
     fn default() -> Self {
-        Self { implementations: true, run: true, debug: true, goto_type_def: true }
+        Self { implementations: true, run: true, debug: true }
     }
 }
 
 impl HoverConfig {
-    pub const NO_ACTIONS: Self =
-        Self { implementations: false, run: false, debug: false, goto_type_def: false };
+    pub const NO_ACTIONS: Self = Self { implementations: false, run: false, debug: false };
 
     pub fn any(&self) -> bool {
-        self.implementations || self.runnable() || self.goto_type_def
+        self.implementations || self.runnable()
     }
 
     pub fn none(&self) -> bool {
@@ -56,13 +52,6 @@ impl HoverConfig {
 pub enum HoverAction {
     Runnable(Runnable),
     Implementaion(FilePosition),
-    GoToType(Vec<HoverGotoTypeData>),
-}
-
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct HoverGotoTypeData {
-    pub mod_path: String,
-    pub nav: NavigationTarget,
 }
 
 /// Contains the results when hovering over an item
@@ -149,10 +138,6 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
                 res.push_action(action);
             }
 
-            if let Some(action) = goto_type_action(db, name_kind) {
-                res.push_action(action);
-            }
-
             return Some(RangeInfo::new(range, res));
         }
     }
@@ -233,44 +218,6 @@ fn runnable_action(
     }
 }
 
-fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
-    match def {
-        Definition::Local(it) => {
-            let mut targets: Vec<ModuleDef> = Vec::new();
-            let mut push_new_def = |item: ModuleDef| {
-                if !targets.contains(&item) {
-                    targets.push(item);
-                }
-            };
-
-            it.ty(db).walk(db, |t| {
-                if let Some(adt) = t.as_adt() {
-                    push_new_def(adt.into());
-                } else if let Some(trait_) = t.as_dyn_trait() {
-                    push_new_def(trait_.into());
-                } else if let Some(traits) = t.as_impl_traits(db) {
-                    traits.into_iter().for_each(|it| push_new_def(it.into()));
-                } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
-                    push_new_def(trait_.into());
-                }
-            });
-
-            let targets = targets
-                .into_iter()
-                .filter_map(|it| {
-                    Some(HoverGotoTypeData {
-                        mod_path: mod_path(db, &it)?,
-                        nav: it.try_to_nav(db)?,
-                    })
-                })
-                .collect();
-
-            Some(HoverAction::GoToType(targets))
-        }
-        _ => None,
-    }
-}
-
 fn hover_text(
     docs: Option<String>,
     desc: Option<String>,
@@ -301,31 +248,25 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
     .map(|name| name.to_string())
 }
 
-fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String {
-    once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string))
-        .chain(
-            module
-                .path_to_root(db)
-                .into_iter()
-                .rev()
-                .map(|it| it.name(db).map(|name| name.to_string())),
-        )
-        .chain(once(name))
-        .flatten()
-        .join("::")
-}
-
-// returns None only for ModuleDef::BuiltinType
-fn mod_path(db: &RootDatabase, item: &ModuleDef) -> Option<String> {
-    Some(determine_mod_path(db, item.module(db)?, item.name(db).map(|name| name.to_string())))
-}
-
-fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
-    def.module(db).map(|module| determine_mod_path(db, module, definition_owner_name(db, def)))
+fn determine_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
+    let mod_path = def.module(db).map(|module| {
+        once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string))
+            .chain(
+                module
+                    .path_to_root(db)
+                    .into_iter()
+                    .rev()
+                    .map(|it| it.name(db).map(|name| name.to_string())),
+            )
+            .chain(once(definition_owner_name(db, def)))
+            .flatten()
+            .join("::")
+    });
+    mod_path
 }
 
 fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> {
-    let mod_path = definition_mod_path(db, &def);
+    let mod_path = determine_mod_path(db, &def);
     return match def {
         Definition::Macro(it) => {
             let src = it.source(db);
@@ -1369,1045 +1310,4 @@ fn func(foo: i32) { if true { <|>foo; }; }
             ]
             "###);
     }
-
-    #[test]
-    fn test_hover_struct_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            struct S{ f1: u32 }
-
-            fn main() {
-                let s<|>t = S{ f1:0 };
-            }
-            ",
-            &["S"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..19,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    7..8,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_generic_struct_has_goto_type_actions() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            struct Arg(u32);
-            struct S<T>{ f1: T }
-
-            fn main() {
-                let s<|>t = S{ f1:Arg(0) };
-            }
-            ",
-            &["S<Arg>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 17..37,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    24..25,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Arg",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..16,
-                                name: "Arg",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    7..10,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct Arg",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_generic_struct_has_flattened_goto_type_actions() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            struct Arg(u32);
-            struct S<T>{ f1: T }
-
-            fn main() {
-                let s<|>t = S{ f1: S{ f1: Arg(0) } };
-            }
-            ",
-            &["S<S<Arg>>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 17..37,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    24..25,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Arg",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..16,
-                                name: "Arg",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    7..10,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct Arg",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_tuple_has_goto_type_actions() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            struct A(u32);
-            struct B(u32);
-            mod M {
-                pub struct C(u32);
-            }
-
-            fn main() {
-                let s<|>t = (A(1), B(2), M::C(3) );
-            }
-            ",
-            &["(A, B, C)"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "A",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..14,
-                                name: "A",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    7..8,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct A",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "B",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 15..29,
-                                name: "B",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    22..23,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct B",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "M::C",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 42..60,
-                                name: "C",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    53..54,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "pub struct C",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-               "###);
-    }
-
-    #[test]
-    fn test_hover_return_impl_trait_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo {}
-
-            fn foo() -> impl Foo {}
-
-            fn main() {
-                let s<|>t = foo();
-            }
-            ",
-            &["impl Foo"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_generic_return_impl_trait_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo<T> {}
-            struct S;
-
-            fn foo() -> impl Foo<S> {}
-
-            fn main() {
-                let s<|>t = foo();
-            }
-            ",
-            &["impl Foo<S>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..15,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 16..25,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    23..24,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_return_impl_traits_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo {}
-            trait Bar {}
-
-            fn foo() -> impl Foo + Bar {}
-
-            fn main() {
-                let s<|>t = foo();
-            }
-            ",
-            &["impl Foo + Bar"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Bar",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 13..25,
-                                name: "Bar",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    19..22,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Bar",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_generic_return_impl_traits_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo<T> {}
-            trait Bar<T> {}
-            struct S1 {}
-            struct S2 {}
-
-            fn foo() -> impl Foo<S1> + Bar<S2> {}
-
-            fn main() {
-                let s<|>t = foo();
-            }
-            ",
-            &["impl Foo<S1> + Bar<S2>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..15,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Bar",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 16..31,
-                                name: "Bar",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    22..25,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Bar",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S1",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 32..44,
-                                name: "S1",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    39..41,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S1",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S2",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 45..57,
-                                name: "S2",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    52..54,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S2",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-               "###);
-    }
-
-    #[test]
-    fn test_hover_arg_impl_trait_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait Foo {}
-            fn foo(ar<|>g: &impl Foo) {}
-            ",
-            &["&impl Foo"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_arg_impl_traits_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait Foo {}
-            trait Bar<T> {}
-            struct S{}
-
-            fn foo(ar<|>g: &impl Foo + Bar<S>) {}
-            ",
-            &["&impl Foo + Bar<S>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Bar",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 13..28,
-                                name: "Bar",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    19..22,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Bar",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 29..39,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    36..37,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait Foo<T> {}
-            struct S {}
-            fn foo(ar<|>g: &impl Foo<S>) {}
-            ",
-            &["&impl Foo<S>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..15,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 16..27,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    23..24,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_dyn_return_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo {}
-            struct S;
-            impl Foo for S {}
-
-            struct B<T>{}
-
-            fn foo() -> B<dyn Foo> {}
-
-            fn main() {
-                let s<|>t = foo();
-            }
-            ",
-            &["B<dyn Foo>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "B",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 41..54,
-                                name: "B",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    48..49,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct B",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_dyn_arg_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait Foo {}
-            fn foo(ar<|>g: &dyn Foo) {}
-            ",
-            &["&dyn Foo"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..12,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_generic_dyn_arg_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait Foo<T> {}
-            struct S {}
-            fn foo(ar<|>g: &dyn Foo<S>) {}
-            ",
-            &["&dyn Foo<S>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..15,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 16..27,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    23..24,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_goto_type_action_links_order() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /lib.rs
-            trait ImplTrait<T> {}
-            trait DynTrait<T> {}
-            struct B<T> {}
-            struct S {}
-
-            fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
-            ",
-            &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "ImplTrait",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..21,
-                                name: "ImplTrait",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..15,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait ImplTrait",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "B",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 43..57,
-                                name: "B",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    50..51,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct B",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "DynTrait",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 22..42,
-                                name: "DynTrait",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    28..36,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait DynTrait",
-                                ),
-                                docs: None,
-                            },
-                        },
-                        HoverGotoTypeData {
-                            mod_path: "S",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 58..69,
-                                name: "S",
-                                kind: STRUCT_DEF,
-                                focus_range: Some(
-                                    65..66,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "struct S",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
-
-    #[test]
-    fn test_hover_associated_type_has_goto_type_action() {
-        let (_, actions) = check_hover_result(
-            "
-            //- /main.rs
-            trait Foo {
-                type Item;
-                fn get(self) -> Self::Item {}
-            }
-
-            struct Bar{}
-            struct S{}
-
-            impl Foo for S{
-                type Item = Bar;
-            }
-
-            fn test() -> impl Foo {
-                S{}
-            }
-
-            fn main() {
-                let s<|>t = test().get();
-            }
-            ",
-            &["Foo::Item<impl Foo>"],
-        );
-        assert_debug_snapshot!(actions,
-            @r###"
-            [
-                GoToType(
-                    [
-                        HoverGotoTypeData {
-                            mod_path: "Foo",
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    1,
-                                ),
-                                full_range: 0..62,
-                                name: "Foo",
-                                kind: TRAIT_DEF,
-                                focus_range: Some(
-                                    6..9,
-                                ),
-                                container_name: None,
-                                description: Some(
-                                    "trait Foo",
-                                ),
-                                docs: None,
-                            },
-                        },
-                    ],
-                ),
-            ]
-            "###);
-    }
 }
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index be9ab62c0b..51dc1f041c 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -66,7 +66,7 @@ pub use crate::{
     display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
     expand_macro::ExpandedMacro,
     folding_ranges::{Fold, FoldKind},
-    hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
+    hover::{HoverAction, HoverConfig, HoverResult},
     inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
     references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
     runnables::{Runnable, RunnableKind, TestId},
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 448645bdc3..f8f790e590 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -121,6 +121,7 @@ pub(crate) fn highlight(
                 assert!(current_macro_call == Some(mc));
                 current_macro_call = None;
                 format_string = None;
+                continue;
             }
             _ => (),
         }
@@ -149,7 +150,7 @@ pub(crate) fn highlight(
 
         let range = element.text_range();
 
-        let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT {
+        let element_to_highlight = if current_macro_call.is_some() {
             // Inside a macro -- expand it first
             let token = match element.clone().into_token() {
                 Some(it) if it.parent().kind() == TOKEN_TREE => it,
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs
index 98993d571b..78ee6a5152 100644
--- a/crates/ra_ide_db/src/change.rs
+++ b/crates/ra_ide_db/src/change.rs
@@ -283,7 +283,7 @@ impl RootDatabase {
             hir::db::GenericPredicatesQuery
             hir::db::GenericDefaultsQuery
             hir::db::ImplsInCrateQuery
-            hir::db::ImplsFromDepsQuery
+            hir::db::ImplsForTraitQuery
             hir::db::InternTypeCtorQuery
             hir::db::InternTypeParamIdQuery
             hir::db::InternChalkImplQuery
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 192c610f1c..da0eb09267 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -75,10 +75,6 @@ pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordF
     }
 }
 
-pub fn record_field_def(name: ast::NameRef, ty: ast::TypeRef) -> ast::RecordFieldDef {
-    ast_from_text(&format!("struct S {{ {}: {}, }}", name, ty))
-}
-
 pub fn block_expr(
     stmts: impl IntoIterator<Item = ast::Stmt>,
     tail_expr: Option<ast::Expr>,
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index a33a35cc14..9b76645767 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -168,6 +168,41 @@ impl SourceFile {
     }
 }
 
+impl ast::Path {
+    /// Returns `text`, parsed as a path, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, ra_parser::FragmentKind::Path)
+    }
+}
+
+impl ast::Pat {
+    /// Returns `text`, parsed as a pattern, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, ra_parser::FragmentKind::Pattern)
+    }
+}
+
+impl ast::Expr {
+    /// Returns `text`, parsed as an expression, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, ra_parser::FragmentKind::Expr)
+    }
+}
+
+impl ast::ModuleItem {
+    /// Returns `text`, parsed as an item, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, ra_parser::FragmentKind::Item)
+    }
+}
+
+impl ast::TypeRef {
+    /// Returns `text`, parsed as an type reference, but only if it has no errors.
+    pub fn parse(text: &str) -> Result<Self, ()> {
+        parsing::parse_text_fragment(text, ra_parser::FragmentKind::Type)
+    }
+}
+
 /// Matches a `SyntaxNode` against an `ast` type.
 ///
 /// # Example:
diff --git a/crates/ra_syntax/src/parsing.rs b/crates/ra_syntax/src/parsing.rs
index e5eb808500..0ed3c20ef9 100644
--- a/crates/ra_syntax/src/parsing.rs
+++ b/crates/ra_syntax/src/parsing.rs
@@ -6,13 +6,14 @@ mod text_token_source;
 mod text_tree_sink;
 mod reparsing;
 
-use crate::{syntax_node::GreenNode, SyntaxError};
+use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode};
 use text_token_source::TextTokenSource;
 use text_tree_sink::TextTreeSink;
 
 pub use lexer::*;
 
 pub(crate) use self::reparsing::incremental_reparse;
+use ra_parser::SyntaxKind;
 
 pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
     let (tokens, lexer_errors) = tokenize(&text);
@@ -27,3 +28,32 @@ pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
 
     (tree, parser_errors)
 }
+
+/// Returns `text` parsed as a `T` provided there are no parse errors.
+pub(crate) fn parse_text_fragment<T: AstNode>(
+    text: &str,
+    fragment_kind: ra_parser::FragmentKind,
+) -> Result<T, ()> {
+    let (tokens, lexer_errors) = tokenize(&text);
+    if !lexer_errors.is_empty() {
+        return Err(());
+    }
+
+    let mut token_source = TextTokenSource::new(text, &tokens);
+    let mut tree_sink = TextTreeSink::new(text, &tokens);
+
+    // TextTreeSink assumes that there's at least some root node to which it can attach errors and
+    // tokens. We arbitrarily give it a SourceFile.
+    use ra_parser::TreeSink;
+    tree_sink.start_node(SyntaxKind::SOURCE_FILE);
+    ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind);
+    tree_sink.finish_node();
+
+    let (tree, parser_errors) = tree_sink.finish();
+    use ra_parser::TokenSource;
+    if !parser_errors.is_empty() || token_source.current().kind != SyntaxKind::EOF {
+        return Err(());
+    }
+
+    SyntaxNode::new_root(tree).first_child().and_then(T::cast).ok_or(())
+}
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 2b46e8905b..458089e539 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -32,7 +32,7 @@ threadpool = "1.7.1"
 
 stdx = { path = "../stdx" }
 
-lsp-server = "0.3.3"
+lsp-server = "0.3.2"
 ra_flycheck = { path = "../ra_flycheck" }
 ra_ide = { path = "../ra_ide" }
 ra_prof = { path = "../ra_prof" }
diff --git a/crates/rust-analyzer/build.rs b/crates/rust-analyzer/build.rs
index 5ae76ba308..d4b010c04e 100644
--- a/crates/rust-analyzer/build.rs
+++ b/crates/rust-analyzer/build.rs
@@ -5,14 +5,11 @@ use std::{env, path::PathBuf, process::Command};
 fn main() {
     set_rerun();
 
-    let rev =
-        env::var("RUST_ANALYZER_REV").ok().or_else(rev).unwrap_or_else(|| "???????".to_string());
+    let rev = rev().unwrap_or_else(|| "???????".to_string());
     println!("cargo:rustc-env=REV={}", rev)
 }
 
 fn set_rerun() {
-    println!("cargo:rerun-if-env-changed=RUST_ANALYZER_REV");
-
     let mut manifest_dir = PathBuf::from(
         env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."),
     );
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index aa2c4ae15d..0df7427cb9 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -296,7 +296,6 @@ impl Config {
             set(value, "/hoverActions/implementations", &mut self.hover.implementations);
             set(value, "/hoverActions/run", &mut self.hover.run);
             set(value, "/hoverActions/debug", &mut self.hover.debug);
-            set(value, "/hoverActions/gotoTypeDef", &mut self.hover.goto_type_def);
         } else {
             self.hover = HoverConfig::NO_ACTIONS;
         }
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index d04ef4c613..1527c9947d 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -20,7 +20,7 @@ use stdx::format_to;
 use crate::{
     config::{Config, FilesWatcher},
     diagnostics::{CheckFixes, DiagnosticCollection},
-    main_loop::request_metrics::{LatestRequests, RequestMetrics},
+    main_loop::pending_requests::{CompletedRequest, LatestRequests},
     to_proto::url_from_abs_path,
     vfs_glob::{Glob, RustPackageFilterBuilder},
     LspError, Result,
@@ -55,10 +55,10 @@ pub struct GlobalState {
     pub analysis_host: AnalysisHost,
     pub vfs: Arc<RwLock<Vfs>>,
     pub task_receiver: Receiver<VfsTask>,
+    pub latest_requests: Arc<RwLock<LatestRequests>>,
     pub flycheck: Option<Flycheck>,
     pub diagnostics: DiagnosticCollection,
     pub proc_macro_client: ProcMacroClient,
-    pub(crate) latest_requests: Arc<RwLock<LatestRequests>>,
 }
 
 /// An immutable snapshot of the world's state at a point in time.
@@ -66,8 +66,8 @@ pub struct GlobalStateSnapshot {
     pub config: Config,
     pub workspaces: Arc<Vec<ProjectWorkspace>>,
     pub analysis: Analysis,
+    pub latest_requests: Arc<RwLock<LatestRequests>>,
     pub check_fixes: CheckFixes,
-    pub(crate) latest_requests: Arc<RwLock<LatestRequests>>,
     vfs: Arc<RwLock<Vfs>>,
 }
 
@@ -236,7 +236,7 @@ impl GlobalState {
         self.analysis_host.collect_garbage()
     }
 
-    pub(crate) fn complete_request(&mut self, request: RequestMetrics) {
+    pub fn complete_request(&mut self, request: CompletedRequest) {
         self.latest_requests.write().record(request)
     }
 }
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 64e70955f3..609cb69d3b 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -32,7 +32,7 @@ mod semantic_tokens;
 
 use serde::de::DeserializeOwned;
 
-pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>;
+pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
 pub use crate::{
     caps::server_capabilities,
     main_loop::LspError,
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 674b1323bc..f0aaaa21ea 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -3,7 +3,7 @@
 
 mod handlers;
 mod subscriptions;
-pub(crate) mod request_metrics;
+pub(crate) mod pending_requests;
 
 use std::{
     borrow::Cow,
@@ -17,19 +17,18 @@ use std::{
 };
 
 use crossbeam_channel::{never, select, unbounded, RecvError, Sender};
-use lsp_server::{
-    Connection, ErrorCode, Message, Notification, ReqQueue, Request, RequestId, Response,
-};
+use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
 use lsp_types::{
-    request::Request as _, DidChangeTextDocumentParams, NumberOrString,
-    TextDocumentContentChangeEvent, WorkDoneProgress, WorkDoneProgressBegin,
-    WorkDoneProgressCreateParams, WorkDoneProgressEnd, WorkDoneProgressReport,
+    DidChangeTextDocumentParams, NumberOrString, TextDocumentContentChangeEvent, WorkDoneProgress,
+    WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd,
+    WorkDoneProgressReport,
 };
 use ra_flycheck::{CheckTask, Status};
 use ra_ide::{Canceled, FileId, LineIndex};
 use ra_prof::profile;
 use ra_project_model::{PackageRoot, ProjectWorkspace};
 use ra_vfs::VfsTask;
+use rustc_hash::FxHashSet;
 use serde::{de::DeserializeOwned, Serialize};
 use threadpool::ThreadPool;
 
@@ -39,7 +38,10 @@ use crate::{
     from_proto,
     global_state::{file_id_to_url, GlobalState, GlobalStateSnapshot},
     lsp_ext,
-    main_loop::{request_metrics::RequestMetrics, subscriptions::Subscriptions},
+    main_loop::{
+        pending_requests::{PendingRequest, PendingRequests},
+        subscriptions::Subscriptions,
+    },
     Result,
 };
 
@@ -151,10 +153,9 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
                 register_options: Some(serde_json::to_value(registration_options).unwrap()),
             };
             let params = lsp_types::RegistrationParams { registrations: vec![registration] };
-            let request = loop_state.req_queue.outgoing.register(
-                lsp_types::request::RegisterCapability::METHOD.to_string(),
+            let request = request_new::<lsp_types::request::RegisterCapability>(
+                loop_state.next_request_id(),
                 params,
-                DO_NOTHING,
             );
             connection.sender.send(request.into()).unwrap();
         }
@@ -198,7 +199,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
     global_state.analysis_host.request_cancellation();
     log::info!("waiting for tasks to finish...");
     task_receiver.into_iter().for_each(|task| {
-        on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, &mut global_state)
+        on_task(task, &connection.sender, &mut loop_state.pending_requests, &mut global_state)
     });
     log::info!("...tasks have finished");
     log::info!("joining threadpool...");
@@ -263,18 +264,27 @@ impl fmt::Debug for Event {
     }
 }
 
-type ReqHandler = fn(&mut GlobalState, Response);
-const DO_NOTHING: ReqHandler = |_, _| ();
-type Incoming = lsp_server::Incoming<(&'static str, Instant)>;
-
-#[derive(Default)]
+#[derive(Debug, Default)]
 struct LoopState {
-    req_queue: ReqQueue<(&'static str, Instant), ReqHandler>,
+    next_request_id: u64,
+    pending_responses: FxHashSet<RequestId>,
+    pending_requests: PendingRequests,
     subscriptions: Subscriptions,
     workspace_loaded: bool,
     roots_progress_reported: Option<usize>,
     roots_scanned: usize,
     roots_total: usize,
+    configuration_request_id: Option<RequestId>,
+}
+
+impl LoopState {
+    fn next_request_id(&mut self) -> RequestId {
+        self.next_request_id += 1;
+        let res: RequestId = self.next_request_id.into();
+        let inserted = self.pending_responses.insert(res.clone());
+        assert!(inserted);
+        res
+    }
 }
 
 fn loop_turn(
@@ -297,7 +307,7 @@ fn loop_turn(
 
     match event {
         Event::Task(task) => {
-            on_task(task, &connection.sender, &mut loop_state.req_queue.incoming, global_state);
+            on_task(task, &connection.sender, &mut loop_state.pending_requests, global_state);
             global_state.maybe_collect_garbage();
         }
         Event::Vfs(task) => {
@@ -307,7 +317,7 @@ fn loop_turn(
         Event::Msg(msg) => match msg {
             Message::Request(req) => on_request(
                 global_state,
-                &mut loop_state.req_queue.incoming,
+                &mut loop_state.pending_requests,
                 pool,
                 task_sender,
                 &connection.sender,
@@ -318,8 +328,32 @@ fn loop_turn(
                 on_notification(&connection.sender, global_state, loop_state, not)?;
             }
             Message::Response(resp) => {
-                let handler = loop_state.req_queue.outgoing.complete(resp.id.clone());
-                handler(global_state, resp)
+                let removed = loop_state.pending_responses.remove(&resp.id);
+                if !removed {
+                    log::error!("unexpected response: {:?}", resp)
+                }
+
+                if Some(&resp.id) == loop_state.configuration_request_id.as_ref() {
+                    loop_state.configuration_request_id = None;
+                    log::debug!("config update response: '{:?}", resp);
+                    let Response { error, result, .. } = resp;
+
+                    match (error, result) {
+                        (Some(err), _) => {
+                            log::error!("failed to fetch the server settings: {:?}", err)
+                        }
+                        (None, Some(configs)) => {
+                            if let Some(new_config) = configs.get(0) {
+                                let mut config = global_state.config.clone();
+                                config.update(&new_config);
+                                global_state.update_configuration(config);
+                            }
+                        }
+                        (None, None) => {
+                            log::error!("received empty server settings response from the client")
+                        }
+                    }
+                }
             }
         },
     };
@@ -373,19 +407,14 @@ fn loop_turn(
 fn on_task(
     task: Task,
     msg_sender: &Sender<Message>,
-    incoming_requests: &mut Incoming,
+    pending_requests: &mut PendingRequests,
     state: &mut GlobalState,
 ) {
     match task {
         Task::Respond(response) => {
-            if let Some((method, start)) = incoming_requests.complete(response.id.clone()) {
-                let duration = start.elapsed();
-                log::info!("handled req#{} in {:?}", response.id, duration);
-                state.complete_request(RequestMetrics {
-                    id: response.id.clone(),
-                    method: method.to_string(),
-                    duration,
-                });
+            if let Some(completed) = pending_requests.finish(&response.id) {
+                log::info!("handled req#{} in {:?}", completed.id, completed.duration);
+                state.complete_request(completed);
                 msg_sender.send(response.into()).unwrap();
             }
         }
@@ -398,7 +427,7 @@ fn on_task(
 
 fn on_request(
     global_state: &mut GlobalState,
-    incoming_requests: &mut Incoming,
+    pending_requests: &mut PendingRequests,
     pool: &ThreadPool,
     task_sender: &Sender<Task>,
     msg_sender: &Sender<Message>,
@@ -411,7 +440,7 @@ fn on_request(
         global_state,
         task_sender,
         msg_sender,
-        incoming_requests,
+        pending_requests,
         request_received,
     };
     pool_dispatcher
@@ -475,7 +504,12 @@ fn on_notification(
                 NumberOrString::Number(id) => id.into(),
                 NumberOrString::String(id) => id.into(),
             };
-            if let Some(response) = loop_state.req_queue.incoming.cancel(id) {
+            if loop_state.pending_requests.cancel(&id) {
+                let response = Response::new_err(
+                    id,
+                    ErrorCode::RequestCanceled as i32,
+                    "canceled by client".to_string(),
+                );
                 msg_sender.send(response.into()).unwrap()
             }
             return Ok(());
@@ -538,36 +572,18 @@ fn on_notification(
         Ok(_) => {
             // As stated in https://github.com/microsoft/language-server-protocol/issues/676,
             // this notification's parameters should be ignored and the actual config queried separately.
-            let request = loop_state.req_queue.outgoing.register(
-                lsp_types::request::WorkspaceConfiguration::METHOD.to_string(),
+            let request_id = loop_state.next_request_id();
+            let request = request_new::<lsp_types::request::WorkspaceConfiguration>(
+                request_id.clone(),
                 lsp_types::ConfigurationParams {
                     items: vec![lsp_types::ConfigurationItem {
                         scope_uri: None,
                         section: Some("rust-analyzer".to_string()),
                     }],
                 },
-                |global_state, resp| {
-                    log::debug!("config update response: '{:?}", resp);
-                    let Response { error, result, .. } = resp;
-
-                    match (error, result) {
-                        (Some(err), _) => {
-                            log::error!("failed to fetch the server settings: {:?}", err)
-                        }
-                        (None, Some(configs)) => {
-                            if let Some(new_config) = configs.get(0) {
-                                let mut config = global_state.config.clone();
-                                config.update(&new_config);
-                                global_state.update_configuration(config);
-                            }
-                        }
-                        (None, None) => {
-                            log::error!("received empty server settings response from the client")
-                        }
-                    }
-                },
             );
             msg_sender.send(request.into())?;
+            loop_state.configuration_request_id = Some(request_id);
 
             return Ok(());
         }
@@ -736,14 +752,13 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
 
     match (prev, loop_state.workspace_loaded) {
         (None, false) => {
-            let request = loop_state.req_queue.outgoing.register(
-                lsp_types::request::WorkDoneProgressCreate::METHOD.to_string(),
+            let work_done_progress_create = request_new::<lsp_types::request::WorkDoneProgressCreate>(
+                loop_state.next_request_id(),
                 WorkDoneProgressCreateParams {
                     token: lsp_types::ProgressToken::String("rustAnalyzer/startup".into()),
                 },
-                DO_NOTHING,
             );
-            sender.send(request.into()).unwrap();
+            sender.send(work_done_progress_create.into()).unwrap();
             send_startup_progress_notif(
                 sender,
                 WorkDoneProgress::Begin(WorkDoneProgressBegin {
@@ -785,7 +800,7 @@ struct PoolDispatcher<'a> {
     req: Option<Request>,
     pool: &'a ThreadPool,
     global_state: &'a mut GlobalState,
-    incoming_requests: &'a mut Incoming,
+    pending_requests: &'a mut PendingRequests,
     msg_sender: &'a Sender<Message>,
     task_sender: &'a Sender<Task>,
     request_received: Instant,
@@ -814,7 +829,7 @@ impl<'a> PoolDispatcher<'a> {
             result_to_task::<R>(id, result)
         })
         .map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
-        on_task(task, self.msg_sender, self.incoming_requests, self.global_state);
+        on_task(task, self.msg_sender, self.pending_requests, self.global_state);
         Ok(self)
     }
 
@@ -861,7 +876,11 @@ impl<'a> PoolDispatcher<'a> {
                 return None;
             }
         };
-        self.incoming_requests.register(id.clone(), (R::METHOD, self.request_received));
+        self.pending_requests.start(PendingRequest {
+            id: id.clone(),
+            method: R::METHOD.to_string(),
+            received: self.request_received,
+        });
         Some((id, params))
     }
 
@@ -974,6 +993,14 @@ where
     Notification::new(N::METHOD.to_string(), params)
 }
 
+fn request_new<R>(id: RequestId, params: R::Params) -> Request
+where
+    R: lsp_types::request::Request,
+    R::Params: Serialize,
+{
+    Request::new(id, R::METHOD.to_string(), params)
+}
+
 #[cfg(test)]
 mod tests {
     use std::borrow::Cow;
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 2d7e649d2d..b34b529b5c 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -18,8 +18,8 @@ use lsp_types::{
     TextDocumentIdentifier, Url, WorkspaceEdit,
 };
 use ra_ide::{
-    FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query,
-    RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
+    FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, Runnable, RunnableKind,
+    SearchScope, TextEdit,
 };
 use ra_prof::profile;
 use ra_project_model::TargetKind;
@@ -1150,23 +1150,6 @@ fn debug_single_command(runnable: &lsp_ext::Runnable) -> Command {
     }
 }
 
-fn goto_location_command(snap: &GlobalStateSnapshot, nav: &NavigationTarget) -> Option<Command> {
-    let value = if snap.config.client_caps.location_link {
-        let link = to_proto::location_link(snap, None, nav.clone()).ok()?;
-        to_value(link).ok()?
-    } else {
-        let range = FileRange { file_id: nav.file_id(), range: nav.range() };
-        let location = to_proto::location(snap, range).ok()?;
-        to_value(location).ok()?
-    };
-
-    Some(Command {
-        title: nav.name().to_string(),
-        command: "rust-analyzer.gotoLocation".into(),
-        arguments: Some(vec![value]),
-    })
-}
-
 fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink {
     lsp_ext::CommandLink { tooltip: Some(tooltip), command }
 }
@@ -1197,13 +1180,13 @@ fn show_impl_command_link(
     None
 }
 
-fn runnable_action_links(
+fn to_runnable_action(
     snap: &GlobalStateSnapshot,
     file_id: FileId,
     runnable: Runnable,
 ) -> Option<lsp_ext::CommandLinkGroup> {
     let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?;
-    if !snap.config.hover.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) {
+    if should_skip_target(&runnable, cargo_spec.as_ref()) {
         return None;
     }
 
@@ -1225,26 +1208,6 @@ fn runnable_action_links(
     })
 }
 
-fn goto_type_action_links(
-    snap: &GlobalStateSnapshot,
-    nav_targets: &[HoverGotoTypeData],
-) -> Option<lsp_ext::CommandLinkGroup> {
-    if !snap.config.hover.goto_type_def || nav_targets.is_empty() {
-        return None;
-    }
-
-    Some(lsp_ext::CommandLinkGroup {
-        title: Some("Go to ".into()),
-        commands: nav_targets
-            .iter()
-            .filter_map(|it| {
-                goto_location_command(snap, &it.nav)
-                    .map(|cmd| to_command_link(cmd, it.mod_path.clone()))
-            })
-            .collect(),
-    })
-}
-
 fn prepare_hover_actions(
     snap: &GlobalStateSnapshot,
     file_id: FileId,
@@ -1258,8 +1221,7 @@ fn prepare_hover_actions(
         .iter()
         .filter_map(|it| match it {
             HoverAction::Implementaion(position) => show_impl_command_link(snap, position),
-            HoverAction::Runnable(r) => runnable_action_links(snap, file_id, r.clone()),
-            HoverAction::GoToType(targets) => goto_type_action_links(snap, targets),
+            HoverAction::Runnable(r) => to_runnable_action(snap, file_id, r.clone()),
         })
         .collect()
 }
diff --git a/crates/rust-analyzer/src/main_loop/pending_requests.rs b/crates/rust-analyzer/src/main_loop/pending_requests.rs
new file mode 100644
index 0000000000..73b33e4194
--- /dev/null
+++ b/crates/rust-analyzer/src/main_loop/pending_requests.rs
@@ -0,0 +1,75 @@
+//! Data structures that keep track of inflight requests.
+
+use std::time::{Duration, Instant};
+
+use lsp_server::RequestId;
+use rustc_hash::FxHashMap;
+
+#[derive(Debug)]
+pub struct CompletedRequest {
+    pub id: RequestId,
+    pub method: String,
+    pub duration: Duration,
+}
+
+#[derive(Debug)]
+pub(crate) struct PendingRequest {
+    pub(crate) id: RequestId,
+    pub(crate) method: String,
+    pub(crate) received: Instant,
+}
+
+impl From<PendingRequest> for CompletedRequest {
+    fn from(pending: PendingRequest) -> CompletedRequest {
+        CompletedRequest {
+            id: pending.id,
+            method: pending.method,
+            duration: pending.received.elapsed(),
+        }
+    }
+}
+
+#[derive(Debug, Default)]
+pub(crate) struct PendingRequests {
+    map: FxHashMap<RequestId, PendingRequest>,
+}
+
+impl PendingRequests {
+    pub(crate) fn start(&mut self, request: PendingRequest) {
+        let id = request.id.clone();
+        let prev = self.map.insert(id.clone(), request);
+        assert!(prev.is_none(), "duplicate request with id {}", id);
+    }
+    pub(crate) fn cancel(&mut self, id: &RequestId) -> bool {
+        self.map.remove(id).is_some()
+    }
+    pub(crate) fn finish(&mut self, id: &RequestId) -> Option<CompletedRequest> {
+        self.map.remove(id).map(CompletedRequest::from)
+    }
+}
+
+const N_COMPLETED_REQUESTS: usize = 10;
+
+#[derive(Debug, Default)]
+pub struct LatestRequests {
+    // hand-rolling VecDeque here to print things in a nicer way
+    buf: [Option<CompletedRequest>; N_COMPLETED_REQUESTS],
+    idx: usize,
+}
+
+impl LatestRequests {
+    pub(crate) fn record(&mut self, request: CompletedRequest) {
+        // special case: don't track status request itself
+        if request.method == "rust-analyzer/analyzerStatus" {
+            return;
+        }
+        let idx = self.idx;
+        self.buf[idx] = Some(request);
+        self.idx = (idx + 1) % N_COMPLETED_REQUESTS;
+    }
+
+    pub(crate) fn iter(&self) -> impl Iterator<Item = (bool, &CompletedRequest)> {
+        let idx = self.idx;
+        self.buf.iter().enumerate().filter_map(move |(i, req)| Some((i == idx, req.as_ref()?)))
+    }
+}
diff --git a/crates/rust-analyzer/src/main_loop/request_metrics.rs b/crates/rust-analyzer/src/main_loop/request_metrics.rs
deleted file mode 100644
index b1019e2d6f..0000000000
--- a/crates/rust-analyzer/src/main_loop/request_metrics.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//! Records stats about requests
-use std::time::Duration;
-
-use lsp_server::RequestId;
-
-#[derive(Debug)]
-pub(crate) struct RequestMetrics {
-    pub(crate) id: RequestId,
-    pub(crate) method: String,
-    pub(crate) duration: Duration,
-}
-
-const N_COMPLETED_REQUESTS: usize = 10;
-
-#[derive(Debug, Default)]
-pub(crate) struct LatestRequests {
-    // hand-rolling VecDeque here to print things in a nicer way
-    buf: [Option<RequestMetrics>; N_COMPLETED_REQUESTS],
-    idx: usize,
-}
-
-impl LatestRequests {
-    pub(crate) fn record(&mut self, request: RequestMetrics) {
-        // special case: don't track status request itself
-        if request.method == "rust-analyzer/analyzerStatus" {
-            return;
-        }
-        let idx = self.idx;
-        self.buf[idx] = Some(request);
-        self.idx = (idx + 1) % N_COMPLETED_REQUESTS;
-    }
-
-    pub(crate) fn iter(&self) -> impl Iterator<Item = (bool, &RequestMetrics)> {
-        let idx = self.idx;
-        self.buf.iter().enumerate().filter_map(move |(i, req)| Some((i == idx, req.as_ref()?)))
-    }
-}
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index f2ff0e4359..c0356344ca 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -1,4 +1,5 @@
 //! Missing batteries for standard libraries.
+
 use std::{cell::Cell, fmt, time::Instant};
 
 #[inline(always)]
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 724606a3d4..7dc721f7e4 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -2,7 +2,7 @@
 //!
 //! Files which do not belong to any explicitly configured `FileSet` belong to
 //! the default `FileSet`.
-use std::{fmt, iter};
+use std::{cmp, fmt, iter};
 
 use paths::AbsPathBuf;
 use rustc_hash::FxHashMap;
@@ -44,12 +44,6 @@ pub struct FileSetConfig {
     roots: Vec<(AbsPathBuf, usize)>,
 }
 
-impl Default for FileSetConfig {
-    fn default() -> Self {
-        FileSetConfig::builder().build()
-    }
-}
-
 impl FileSetConfig {
     pub fn builder() -> FileSetConfigBuilder {
         FileSetConfigBuilder::default()
@@ -66,19 +60,14 @@ impl FileSetConfig {
         self.n_file_sets
     }
     fn classify(&self, path: &VfsPath) -> usize {
-        let path = match path.as_path() {
-            Some(it) => it,
-            None => return self.len() - 1,
-        };
-        let idx = match self.roots.binary_search_by(|(p, _)| p.as_path().cmp(path)) {
-            Ok(it) => it,
-            Err(it) => it.saturating_sub(1),
-        };
-        if path.starts_with(&self.roots[idx].0) {
-            self.roots[idx].1
-        } else {
-            self.len() - 1
+        for (root, idx) in self.roots.iter() {
+            if let Some(path) = path.as_path() {
+                if path.starts_with(root) {
+                    return *idx;
+                }
+            }
         }
+        self.len() - 1
     }
 }
 
@@ -93,9 +82,6 @@ impl Default for FileSetConfigBuilder {
 }
 
 impl FileSetConfigBuilder {
-    pub fn len(&self) -> usize {
-        self.roots.len()
-    }
     pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) {
         self.roots.push(roots)
     }
@@ -107,7 +93,7 @@ impl FileSetConfigBuilder {
             .enumerate()
             .flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i)))
             .collect();
-        roots.sort();
+        roots.sort_by_key(|(path, _)| cmp::Reverse(path.to_string_lossy().len()));
         FileSetConfig { n_file_sets, roots }
     }
 }
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index 055219b0cd..75ce61cf9d 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -79,9 +79,6 @@ pub enum ChangeKind {
 }
 
 impl Vfs {
-    pub fn len(&self) -> usize {
-        self.data.len()
-    }
     pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
         self.interner.get(path).filter(|&it| self.get(it).is_some())
     }
diff --git a/editors/code/package.json b/editors/code/package.json
index e6ceb235fc..3acc375f67 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -510,11 +510,6 @@
                     "type": "boolean",
                     "default": true
                 },
-                "rust-analyzer.hoverActions.gotoTypeDef": {
-                    "markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
-                    "type": "boolean",
-                    "default": true
-                },
                 "rust-analyzer.linkedProjects": {
                     "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects.  \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
                     "type": "array",
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 48a25495fb..3e9c3aa0e5 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -353,20 +353,6 @@ export function applyActionGroup(_ctx: Ctx): Cmd {
     };
 }
 
-export function gotoLocation(ctx: Ctx): Cmd {
-    return async (locationLink: lc.LocationLink) => {
-        const client = ctx.client;
-        if (client) {
-            const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri);
-            let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange);
-            // collapse the range to a cursor position
-            range = range.with({ end: range.start });
-
-            await vscode.window.showTextDocument(uri, { selection: range });
-        }
-    };
-}
-
 export function resolveCodeAction(ctx: Ctx): Cmd {
     const client = ctx.client;
     return async (params: ra.ResolveCodeActionParams) => {
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 9591d4fe32..d8f0037d4c 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -117,7 +117,7 @@ export class Config {
         return {
             engine: this.get<string>("debug.engine"),
             engineSettings: this.get<object>("debug.engineSettings"),
-            openDebugPane: this.get<boolean>("debug.openDebugPane"),
+            openUpDebugPane: this.get<boolean>("debug.openUpDebugPane"),
             sourceFileMap: sourceFileMap
         };
     }
@@ -135,9 +135,6 @@ export class Config {
         return {
             enable: this.get<boolean>("hoverActions.enable"),
             implementations: this.get<boolean>("hoverActions.implementations"),
-            run: this.get<boolean>("hoverActions.run"),
-            debug: this.get<boolean>("hoverActions.debug"),
-            gotoTypeDef: this.get<boolean>("hoverActions.gotoTypeDef"),
         };
     }
 }
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 61c12dbe07..a0c9b3ab2e 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -82,7 +82,7 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v
     }
 
     debugOutput.clear();
-    if (ctx.config.debug.openDebugPane) {
+    if (ctx.config.debug.openUpDebugPane) {
         debugOutput.show(true);
     }
 
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 670f2ebfd6..a92c676fa2 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -42,16 +42,7 @@ export async function activate(context: vscode.ExtensionContext) {
 
     const config = new Config(context);
     const state = new PersistentState(context.globalState);
-    const serverPath = await bootstrap(config, state).catch(err => {
-        let message = "Failed to bootstrap rust-analyzer.";
-        if (err.code === "EBUSY" || err.code === "ETXTBSY") {
-            message += " Other vscode windows might be using rust-analyzer, " +
-                "you should close them and reload this window to retry.";
-        }
-        message += " Open \"Help > Toggle Developer Tools > Console\" to see the logs";
-        log.error("Bootstrap error", err);
-        throw new Error(message);
-    });
+    const serverPath = await bootstrap(config, state);
 
     const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
     if (workspaceFolder === undefined) {
@@ -109,7 +100,6 @@ export async function activate(context: vscode.ExtensionContext) {
     ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
     ctx.registerCommand('resolveCodeAction', commands.resolveCodeAction);
     ctx.registerCommand('applyActionGroup', commands.applyActionGroup);
-    ctx.registerCommand('gotoLocation', commands.gotoLocation);
 
     ctx.pushCleanup(activateTaskProvider(workspaceFolder));
 
@@ -294,11 +284,6 @@ async function getServer(config: Config, state: PersistentState): Promise<string
     const artifact = release.assets.find(artifact => artifact.name === binaryName);
     assert(!!artifact, `Bad release: ${JSON.stringify(release)}`);
 
-    // Unlinking the exe file before moving new one on its place should prevent ETXTBSY error.
-    await fs.unlink(dest).catch(err => {
-        if (err.code !== "ENOENT") throw err;
-    });
-
     await download(artifact.browser_download_url, dest, "Downloading rust-analyzer server", { mode: 0o755 });
 
     // Patching executable if that's NixOS.
diff --git a/editors/code/src/net.ts b/editors/code/src/net.ts
index 0e7dd29c26..4922139373 100644
--- a/editors/code/src/net.ts
+++ b/editors/code/src/net.ts
@@ -1,9 +1,7 @@
 import fetch from "node-fetch";
 import * as vscode from "vscode";
-import * as stream from "stream";
 import * as fs from "fs";
-import * as os from "os";
-import * as path from "path";
+import * as stream from "stream";
 import * as util from "util";
 import { log, assert } from "./util";
 
@@ -89,7 +87,7 @@ export async function download(
 }
 
 /**
- * Downloads file from `url` and stores it at `destFilePath` with `mode` (unix permissions).
+ * Downloads file from `url` and stores it at `destFilePath` with `destFilePermissions`.
  * `onProgress` callback is called on recieveing each chunk of bytes
  * to track the progress of downloading, it gets the already read and total
  * amount of bytes to read as its parameters.
@@ -120,46 +118,14 @@ async function downloadFile(
         onProgress(readBytes, totalBytes);
     });
 
-    // Put the artifact into a temporary folder to prevent partially downloaded files when user kills vscode
-    await withTempFile(async tempFilePath => {
-        const destFileStream = fs.createWriteStream(tempFilePath, { mode });
-        await pipeline(res.body, destFileStream);
-        await new Promise<void>(resolve => {
-            destFileStream.on("close", resolve);
-            destFileStream.destroy();
-            // This workaround is awaiting to be removed when vscode moves to newer nodejs version:
-            // https://github.com/rust-analyzer/rust-analyzer/issues/3167
-        });
-        await moveFile(tempFilePath, destFilePath);
-    });
-}
-
-async function withTempFile(scope: (tempFilePath: string) => Promise<void>) {
-    // Based on the great article: https://advancedweb.hu/secure-tempfiles-in-nodejs-without-dependencies/
+    const destFileStream = fs.createWriteStream(destFilePath, { mode });
 
-    // `.realpath()` should handle the cases where os.tmpdir() contains symlinks
-    const osTempDir = await fs.promises.realpath(os.tmpdir());
+    await pipeline(res.body, destFileStream);
+    return new Promise<void>(resolve => {
+        destFileStream.on("close", resolve);
+        destFileStream.destroy();
 
-    const tempDir = await fs.promises.mkdtemp(path.join(osTempDir, "rust-analyzer"));
-
-    try {
-        return await scope(path.join(tempDir, "file"));
-    } finally {
-        // We are good citizens :D
-        void fs.promises.rmdir(tempDir, { recursive: true }).catch(log.error);
-    }
-};
-
-async function moveFile(src: fs.PathLike, dest: fs.PathLike) {
-    try {
-        await fs.promises.rename(src, dest);
-    } catch (err) {
-        if (err.code === 'EXDEV') {
-            // We are probably moving the file across partitions/devices
-            await fs.promises.copyFile(src, dest);
-            await fs.promises.unlink(src);
-        } else {
-            log.error(`Failed to rename the file ${src} -> ${dest}`, err);
-        }
-    }
+        // Details on workaround: https://github.com/rust-analyzer/rust-analyzer/pull/3092#discussion_r378191131
+        // Issue at nodejs repo: https://github.com/nodejs/node/issues/31776
+    });
 }


Test patch:
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 4da2e972bd..1f004bd630 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -633,154 +633,3 @@ where
     "###
     );
 }
-
-#[test]
-fn issue_4953() {
-    assert_snapshot!(
-        infer(r#"
-pub struct Foo(pub i64);
-impl Foo {
-    fn test() -> Self { Self(0i64) }
-}
-"#),
-        @r###"
-    59..73 '{ Self(0i64) }': Foo
-    61..65 'Self': Foo(i64) -> Foo
-    61..71 'Self(0i64)': Foo
-    66..70 '0i64': i64
-    "###
-    );
-    assert_snapshot!(
-        infer(r#"
-pub struct Foo<T>(pub T);
-impl Foo<i64> {
-    fn test() -> Self { Self(0i64) }
-}
-"#),
-        @r###"
-    65..79 '{ Self(0i64) }': Foo<i64>
-    67..71 'Self': Foo<i64>(i64) -> Foo<i64>
-    67..77 'Self(0i64)': Foo<i64>
-    72..76 '0i64': i64
-    "###
-    );
-}
-
-#[test]
-fn issue_4931() {
-    assert_snapshot!(
-        infer(r#"
-trait Div<T> {
-    type Output;
-}
-
-trait CheckedDiv: Div<()> {}
-
-trait PrimInt: CheckedDiv<Output = ()> {
-    fn pow(self);
-}
-
-fn check<T: PrimInt>(i: T) {
-    i.pow();
-}
-"#),
-        @r###"
-    118..122 'self': Self
-    149..150 'i': T
-    155..171 '{     ...w(); }': ()
-    161..162 'i': T
-    161..168 'i.pow()': ()
-    "###
-    );
-}
-
-#[test]
-fn issue_4885() {
-    assert_snapshot!(
-        infer(r#"
-#[lang = "coerce_unsized"]
-pub trait CoerceUnsized<T> {}
-
-trait Future {
-    type Output;
-}
-trait Foo<R> {
-    type Bar;
-}
-fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar>
-where
-    K: Foo<R>,
-{
-    bar(key)
-}
-fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
-where
-    K: Foo<R>,
-{
-}
-"#),
-        @r###"
-    137..140 'key': &K
-    199..215 '{     ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
-    205..208 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
-    205..213 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
-    209..212 'key': &K
-    229..232 'key': &K
-    291..294 '{ }': ()
-    "###
-    );
-}
-
-#[test]
-fn issue_4800() {
-    assert_snapshot!(
-        infer(r#"
-trait Debug {}
-
-struct Foo<T>;
-
-type E1<T> = (T, T, T);
-type E2<T> = E1<E1<E1<(T, T, T)>>>;
-
-impl Debug for Foo<E2<()>> {}
-
-struct Request;
-
-pub trait Future {
-    type Output;
-}
-
-pub struct PeerSet<D>;
-
-impl<D> Service<Request> for PeerSet<D>
-where
-    D: Discover,
-    D::Key: Debug,
-{
-    type Error = ();
-    type Future = dyn Future<Output = Self::Error>;
-
-    fn call(&mut self) -> Self::Future {
-        loop {}
-    }
-}
-
-pub trait Discover {
-    type Key;
-}
-
-pub trait Service<Request> {
-    type Error;
-    type Future: Future<Output = Self::Error>;
-    fn call(&mut self) -> Self::Future;
-}
-"#),
-        @r###"
-    380..384 'self': &mut PeerSet<D>
-    402..425 '{     ...     }': dyn Future<Output = ()>
-    412..419 'loop {}': !
-    417..419 '{}': ()
-    576..580 'self': &mut Self
-    "###
-    );
-}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 961be4abdf..e81193a3c3 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2888,226 +2888,3 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
     );
     assert_eq!(t, "i32");
 }
-
-#[test]
-fn infer_closure_arg() {
-    assert_snapshot!(
-        infer(
-            r#"
-            //- /lib.rs
-
-            enum Option<T> {
-                None,
-                Some(T)
-            }
-
-            fn foo() {
-                let s = Option::None;
-                let f = |x: Option<i32>| {};
-                (&f)(s)
-            }
-        "#
-        ),
-        @r###"
-    137..259 '{     ...     }': ()
-    159..160 's': Option<i32>
-    163..175 'Option::None': Option<i32>
-    197..198 'f': |Option<i32>| -> ()
-    201..220 '|x: Op...2>| {}': |Option<i32>| -> ()
-    202..203 'x': Option<i32>
-    218..220 '{}': ()
-    238..245 '(&f)(s)': ()
-    239..241 '&f': &|Option<i32>| -> ()
-    240..241 'f': |Option<i32>| -> ()
-    243..244 's': Option<i32>
-    "###
-    );
-}
-
-#[test]
-fn infer_fn_trait_arg() {
-    assert_snapshot!(
-        infer(
-            r#"
-            //- /lib.rs deps:std
-
-            #[lang = "fn_once"]
-            pub trait FnOnce<Args> {
-                type Output;
-
-                extern "rust-call" fn call_once(&self, args: Args) -> Self::Output;
-            }
-
-            #[lang = "fn"]
-            pub trait Fn<Args>:FnOnce<Args> {
-                extern "rust-call" fn call(&self, args: Args) -> Self::Output;
-            }
-
-            enum Option<T> {
-                None,
-                Some(T)
-            }
-
-            fn foo<F, T>(f: F) -> T
-            where
-                F: Fn(Option<i32>) -> T,
-            {
-                let s = None;
-                f(s)
-            }
-        "#
-        ),
-        @r###"
-    183..187 'self': &Self
-    189..193 'args': Args
-    350..354 'self': &Self
-    356..360 'args': Args
-    515..516 'f': F
-    597..663 '{     ...     }': T
-    619..620 's': Option<i32>
-    623..627 'None': Option<i32>
-    645..646 'f': F
-    645..649 'f(s)': T
-    647..648 's': Option<i32>
-    "###
-    );
-}
-
-#[test]
-fn infer_box_fn_arg() {
-    assert_snapshot!(
-        infer(
-            r#"
-            //- /lib.rs deps:std
-
-            #[lang = "fn_once"]
-            pub trait FnOnce<Args> {
-                type Output;
-
-                extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-            }
-
-            #[lang = "deref"]
-            pub trait Deref {
-                type Target: ?Sized;
-
-                fn deref(&self) -> &Self::Target;
-            }
-
-            #[lang = "owned_box"]
-            pub struct Box<T: ?Sized> {
-                inner: *mut T,
-            }
-
-            impl<T: ?Sized> Deref for Box<T> {
-                type Target = T;
-
-                fn deref(&self) -> &T {
-                    &self.inner
-                }
-            }
-
-            enum Option<T> {
-                None,
-                Some(T)
-            }
-
-            fn foo() {
-                let s = Option::None;
-                let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
-                f(&s)
-            }
-        "#
-        ),
-        @r###"
-    182..186 'self': Self
-    188..192 'args': Args
-    356..360 'self': &Self
-    622..626 'self': &Box<T>
-    634..685 '{     ...     }': &T
-    656..667 '&self.inner': &*mut T
-    657..661 'self': &Box<T>
-    657..667 'self.inner': *mut T
-    812..957 '{     ...     }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
-    834..835 's': Option<i32>
-    838..850 'Option::None': Option<i32>
-    872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>>
-    907..920 'box (|ps| {})': Box<|{unknown}| -> ()>
-    912..919 '|ps| {}': |{unknown}| -> ()
-    913..915 'ps': {unknown}
-    917..919 '{}': ()
-    938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>>
-    938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
-    940..942 '&s': &Option<i32>
-    941..942 's': Option<i32>
-    "###
-    );
-}
-
-#[test]
-fn infer_dyn_fn_output() {
-    assert_snapshot!(
-        infer(
-            r#"
-            //- /lib.rs deps:std
-
-            #[lang = "fn_once"]
-            pub trait FnOnce<Args> {
-                type Output;
-
-                extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-            }
-
-            #[lang = "fn"]
-            pub trait Fn<Args>:FnOnce<Args> {
-                extern "rust-call" fn call(&self, args: Args) -> Self::Output;
-            }
-
-            #[lang = "deref"]
-            pub trait Deref {
-                type Target: ?Sized;
-
-                fn deref(&self) -> &Self::Target;
-            }
-
-            #[lang = "owned_box"]
-            pub struct Box<T: ?Sized> {
-                inner: *mut T,
-            }
-
-            impl<T: ?Sized> Deref for Box<T> {
-                type Target = T;
-
-                fn deref(&self) -> &T {
-                    &self.inner
-                }
-            }
-
-            fn foo() {
-                let f: Box<dyn Fn() -> i32> = box(|| 5);
-                let x = f();
-            }
-        "#
-        ),
-        @r###"
-    182..186 'self': Self
-    188..192 'args': Args
-    349..353 'self': &Self
-    355..359 'args': Args
-    523..527 'self': &Self
-    789..793 'self': &Box<T>
-    801..852 '{     ...     }': &T
-    823..834 '&self.inner': &*mut T
-    824..828 'self': &Box<T>
-    824..834 'self.inner': *mut T
-    889..990 '{     ...     }': ()
-    911..912 'f': Box<dyn Fn<(), Output = i32>>
-    937..946 'box(|| 5)': Box<|| -> i32>
-    941..945 '|| 5': || -> i32
-    944..945 '5': i32
-    968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
-    972..973 'f': Box<dyn Fn<(), Output = i32>>
-    972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
-    "###
-    );
-}
diff --git a/crates/ra_ide/src/snapshots/highlight_doctest.html b/crates/ra_ide/src/snapshots/highlight_doctest.html
index 63199cdbe2..f61c0daa50 100644
--- a/crates/ra_ide/src/snapshots/highlight_doctest.html
+++ b/crates/ra_ide/src/snapshots/highlight_doctest.html
@@ -84,13 +84,4 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration">foo</span>(&<span class="self_keyword">self</span>) -&gt; <span class="builtin_type">bool</span> {
         <span class="bool_literal">true</span>
     }
-}
-
-<span class="comment documentation">/// ```</span>
-<span class="comment documentation">/// </span><span class="macro">noop!</span>(<span class="numeric_literal">1</span>);
-<span class="comment documentation">/// ```</span>
-<span class="macro">macro_rules!</span> <span class="macro declaration">noop</span> {
-    ($expr:expr) =&gt; {
-        $expr
-    }
 }</code></pre>
\ No newline at end of file
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index 93a276ffe1..b4d56a7a06 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -344,15 +344,6 @@ impl Foo {
         true
     }
 }
-
-/// ```
-/// noop!(1);
-/// ```
-macro_rules! noop {
-    ($expr:expr) => {
-        $expr
-    }
-}
 "#
         .trim(),
         "crates/ra_ide/src/snapshots/highlight_doctest.html",
diff --git a/crates/ra_syntax/src/tests.rs b/crates/ra_syntax/src/tests.rs
index aee57db62a..959967b792 100644
--- a/crates/ra_syntax/src/tests.rs
+++ b/crates/ra_syntax/src/tests.rs
@@ -54,6 +54,51 @@ fn parser_tests() {
     });
 }
 
+#[test]
+fn expr_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/expr/ok"],
+        &["parser/fragments/expr/err"],
+        crate::ast::Expr::parse,
+    );
+}
+
+#[test]
+fn path_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/path/ok"],
+        &["parser/fragments/path/err"],
+        crate::ast::Path::parse,
+    );
+}
+
+#[test]
+fn pattern_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/pattern/ok"],
+        &["parser/fragments/pattern/err"],
+        crate::ast::Pat::parse,
+    );
+}
+
+#[test]
+fn item_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/item/ok"],
+        &["parser/fragments/item/err"],
+        crate::ast::ModuleItem::parse,
+    );
+}
+
+#[test]
+fn type_parser_tests() {
+    fragment_parser_dir_test(
+        &["parser/fragments/type/ok"],
+        &["parser/fragments/type/err"],
+        crate::ast::TypeRef::parse,
+    );
+}
+
 #[test]
 fn parser_fuzz_tests() {
     for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) {
@@ -134,3 +179,24 @@ fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str)
     }
     acc
 }
+
+fn fragment_parser_dir_test<T, F>(ok_paths: &[&str], err_paths: &[&str], f: F)
+where
+    T: crate::AstNode,
+    F: Fn(&str) -> Result<T, ()>,
+{
+    dir_tests(&test_data_dir(), ok_paths, "rast", |text, path| {
+        if let Ok(node) = f(text) {
+            format!("{:#?}", crate::ast::AstNode::syntax(&node))
+        } else {
+            panic!("Failed to parse '{:?}'", path);
+        }
+    });
+    dir_tests(&test_data_dir(), err_paths, "rast", |text, path| {
+        if let Ok(_) = f(text) {
+            panic!("'{:?}' successfully parsed when it should have errored", path);
+        } else {
+            "ERROR\n".to_owned()
+        }
+    });
+}
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs
new file mode 100644
index 0000000000..ca49acb079
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs
@@ -0,0 +1,1 @@
+1 +
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast
new file mode 100644
index 0000000000..fa78a02a6b
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast
@@ -0,0 +1,8 @@
+BIN_EXPR@0..5
+  LITERAL@0..1
+    INT_NUMBER@0..1 "1"
+  WHITESPACE@1..2 " "
+  PLUS@2..3 "+"
+  WHITESPACE@3..4 " "
+  LITERAL@4..5
+    INT_NUMBER@4..5 "2"
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs
new file mode 100644
index 0000000000..e0ef584020
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs
@@ -0,0 +1,1 @@
+1 + 2
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs
new file mode 100644
index 0000000000..dc32389bbb
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs
@@ -0,0 +1,1 @@
+fn fn foo() {}
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast
new file mode 100644
index 0000000000..f1e78f3882
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast
@@ -0,0 +1,12 @@
+FN_DEF@0..11
+  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_EXPR@9..11
+    L_CURLY@9..10 "{"
+    R_CURLY@10..11 "}"
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs
new file mode 100644
index 0000000000..8f3b7ef112
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs
@@ -0,0 +1,1 @@
+fn foo() {}
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs
new file mode 100644
index 0000000000..2046de0492
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs
@@ -0,0 +1,1 @@
+struct
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs
new file mode 100644
index 0000000000..745e8d376f
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs
@@ -0,0 +1,1 @@
+a + b
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast
new file mode 100644
index 0000000000..0c5d4360fa
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast
@@ -0,0 +1,4 @@
+PATH@0..3
+  PATH_SEGMENT@0..3
+    NAME_REF@0..3
+      IDENT@0..3 "foo"
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs
new file mode 100644
index 0000000000..257cc5642c
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs
@@ -0,0 +1,1 @@
+foo
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast
new file mode 100644
index 0000000000..4a2b45e6a9
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast
@@ -0,0 +1,14 @@
+PATH@0..13
+  PATH@0..8
+    PATH@0..3
+      PATH_SEGMENT@0..3
+        NAME_REF@0..3
+          IDENT@0..3 "foo"
+    COLON2@3..5 "::"
+    PATH_SEGMENT@5..8
+      NAME_REF@5..8
+        IDENT@5..8 "bar"
+  COLON2@8..10 "::"
+  PATH_SEGMENT@10..13
+    NAME_REF@10..13
+      IDENT@10..13 "baz"
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs
new file mode 100644
index 0000000000..81e0b21cd4
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs
@@ -0,0 +1,1 @@
+foo::bar::baz
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs
new file mode 100644
index 0000000000..ae26fc4556
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs
@@ -0,0 +1,1 @@
+fn
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs
new file mode 100644
index 0000000000..61a391d084
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs
@@ -0,0 +1,1 @@
+Some(x
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast
new file mode 100644
index 0000000000..15eb7f9c67
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast
@@ -0,0 +1,10 @@
+TUPLE_STRUCT_PAT@0..7
+  PATH@0..4
+    PATH_SEGMENT@0..4
+      NAME_REF@0..4
+        IDENT@0..4 "Some"
+  L_PAREN@4..5 "("
+  BIND_PAT@5..6
+    NAME@5..6
+      IDENT@5..6 "x"
+  R_PAREN@6..7 ")"
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs
new file mode 100644
index 0000000000..87114dd788
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs
@@ -0,0 +1,1 @@
+Some(x)
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast
new file mode 100644
index 0000000000..5df7507e2d
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast
@@ -0,0 +1,1 @@
+ERROR
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs
new file mode 100644
index 0000000000..caa4d7c092
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs
@@ -0,0 +1,1 @@
+Result<Foo, Bar
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast
new file mode 100644
index 0000000000..8831cfa6c8
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast
@@ -0,0 +1,22 @@
+PATH_TYPE@0..16
+  PATH@0..16
+    PATH_SEGMENT@0..16
+      NAME_REF@0..6
+        IDENT@0..6 "Result"
+      TYPE_ARG_LIST@6..16
+        L_ANGLE@6..7 "<"
+        TYPE_ARG@7..10
+          PATH_TYPE@7..10
+            PATH@7..10
+              PATH_SEGMENT@7..10
+                NAME_REF@7..10
+                  IDENT@7..10 "Foo"
+        COMMA@10..11 ","
+        WHITESPACE@11..12 " "
+        TYPE_ARG@12..15
+          PATH_TYPE@12..15
+            PATH@12..15
+              PATH_SEGMENT@12..15
+                NAME_REF@12..15
+                  IDENT@12..15 "Bar"
+        R_ANGLE@15..16 ">"
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs
new file mode 100644
index 0000000000..b50b3bb3bf
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs
@@ -0,0 +1,1 @@
+Result<Foo, Bar>