Repository: rust-analyzer/rust-analyzer
Pull request #2276 (2019-11-16 13:50:17)

Source-ify name_definition


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 16fbe75020..d7ec266c0b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -123,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "chalk-derive"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
  "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -133,9 +133,9 @@ dependencies = [
 [[package]]
 name = "chalk-engine"
 version = "0.9.0"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
- "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
+ "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -143,18 +143,18 @@ dependencies = [
 [[package]]
 name = "chalk-ir"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
- "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
+ "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
  "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "chalk-macros"
 version = "0.1.1"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -162,24 +162,23 @@ dependencies = [
 [[package]]
 name = "chalk-rust-ir"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
- "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
+ "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
 ]
 
 [[package]]
 name = "chalk-solve"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478#a88cad7f0a69e05ba8f40b74c58a1c229c1b2478"
+source = "git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05#50f9f636123bd88d0cc1b958749981d6702e4d05"
 dependencies = [
- "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
+ "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
  "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1017,9 +1016,9 @@ name = "ra_hir"
 version = "0.1.0"
 dependencies = [
  "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
- "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)",
+ "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
+ "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)",
  "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1874,12 +1873,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d"
 "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
-"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
-"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
-"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
-"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
-"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=a88cad7f0a69e05ba8f40b74c58a1c229c1b2478)" = "<none>"
+"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
+"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
+"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
+"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
+"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
+"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=50f9f636123bd88d0cc1b958749981d6702e4d05)" = "<none>"
 "checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
 "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 20f6e3649b..3249613284 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -23,9 +23,9 @@ hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
 test_utils = { path = "../test_utils" }
 ra_prof = { path = "../ra_prof" }
 
-chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
-chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
-chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
+chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
+chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
+chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "50f9f636123bd88d0cc1b958749981d6702e4d05" }
 lalrpop-intern = "0.15.1"
 
 [dev-dependencies]
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d75d71d665..276b0774fb 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -13,10 +13,8 @@ use crate::{
     lang_item::{LangItemTarget, LangItems},
     traits::TraitData,
     ty::{
-        method_resolution::CrateImplBlocks,
-        traits::{AssocTyValue, Impl},
-        CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
-        TypeCtor,
+        method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
+        InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor,
     },
     type_alias::TypeAliasData,
     Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField,
@@ -121,42 +119,26 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
     fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
     #[salsa::interned]
     fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId;
-    #[salsa::interned]
-    fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> ids::AssocTyValueId;
 
     #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
-    fn associated_ty_data(
-        &self,
-        id: chalk_ir::TypeId,
-    ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
+    fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
 
     #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)]
     fn trait_datum(
         &self,
         krate: Crate,
         trait_id: chalk_ir::TraitId,
-    ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
+    ) -> Arc<chalk_rust_ir::TraitDatum>;
 
     #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)]
     fn struct_datum(
         &self,
         krate: Crate,
         struct_id: chalk_ir::StructId,
-    ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
+    ) -> Arc<chalk_rust_ir::StructDatum>;
 
     #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)]
-    fn impl_datum(
-        &self,
-        krate: Crate,
-        impl_id: chalk_ir::ImplId,
-    ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
-
-    #[salsa::invoke(crate::ty::traits::chalk::associated_ty_value_query)]
-    fn associated_ty_value(
-        &self,
-        krate: Crate,
-        id: chalk_rust_ir::AssociatedTyValueId,
-    ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>;
+    fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>;
 
     #[salsa::invoke(crate::ty::traits::trait_solve_query)]
     fn trait_solve(
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 2b59365fb6..fe083c0c65 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -37,9 +37,3 @@ impl_intern_key!(TypeCtorId);
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct GlobalImplId(salsa::InternId);
 impl_intern_key!(GlobalImplId);
-
-/// This exists just for Chalk, because it needs a unique ID for each associated
-/// type value in an impl (even synthetic ones).
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct AssocTyValueId(salsa::InternId);
-impl_intern_key!(AssocTyValueId);
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index a541351880..ff6030ac42 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -224,8 +224,8 @@ impl TypeWalk for ProjectionTy {
         self.parameters.walk(f);
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
-        self.parameters.walk_mut_binders(f, binders);
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        self.parameters.walk_mut(f);
     }
 }
 
@@ -291,20 +291,6 @@ pub enum Ty {
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Substs(Arc<[Ty]>);
 
-impl TypeWalk for Substs {
-    fn walk(&self, f: &mut impl FnMut(&Ty)) {
-        for t in self.0.iter() {
-            t.walk(f);
-        }
-    }
-
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
-        for t in make_mut_slice(&mut self.0) {
-            t.walk_mut_binders(f, binders);
-        }
-    }
-}
-
 impl Substs {
     pub fn empty() -> Substs {
         Substs(Arc::new([]))
@@ -318,6 +304,18 @@ impl Substs {
         Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
     }
 
+    pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
+        for t in self.0.iter() {
+            t.walk(f);
+        }
+    }
+
+    pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        for t in make_mut_slice(&mut self.0) {
+            t.walk_mut(f);
+        }
+    }
+
     pub fn as_single(&self) -> &Ty {
         if self.0.len() != 1 {
             panic!("expected substs of len 1, got {:?}", self);
@@ -442,8 +440,8 @@ impl TypeWalk for TraitRef {
         self.substs.walk(f);
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
-        self.substs.walk_mut_binders(f, binders);
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        self.substs.walk_mut(f);
     }
 }
 
@@ -493,12 +491,10 @@ impl TypeWalk for GenericPredicate {
         }
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
         match self {
-            GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
-            GenericPredicate::Projection(projection_pred) => {
-                projection_pred.walk_mut_binders(f, binders)
-            }
+            GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f),
+            GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f),
             GenericPredicate::Error => {}
         }
     }
@@ -548,9 +544,9 @@ impl TypeWalk for FnSig {
         }
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
         for t in make_mut_slice(&mut self.params_and_return) {
-            t.walk_mut_binders(f, binders);
+            t.walk_mut(f);
         }
     }
 }
@@ -675,20 +671,7 @@ impl Ty {
 /// types, similar to Chalk's `Fold` trait.
 pub trait TypeWalk {
     fn walk(&self, f: &mut impl FnMut(&Ty));
-    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
-        self.walk_mut_binders(&mut |ty, _binders| f(ty), 0);
-    }
-    /// Walk the type, counting entered binders.
-    ///
-    /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers
-    /// to the innermost binder, 1 to the next, etc.. So when we want to
-    /// substitute a certain bound variable, we can't just walk the whole type
-    /// and blindly replace each instance of a certain index; when we 'enter'
-    /// things that introduce new bound variables, we have to keep track of
-    /// that. Currently, the only thing that introduces bound variables on our
-    /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
-    /// variable for the self type.
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty));
 
     fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
     where
@@ -717,22 +700,14 @@ pub trait TypeWalk {
     }
 
     /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
-    fn subst_bound_vars(mut self, substs: &Substs) -> Self
+    fn subst_bound_vars(self, substs: &Substs) -> Self
     where
         Self: Sized,
     {
-        self.walk_mut_binders(
-            &mut |ty, binders| match ty {
-                &mut Ty::Bound(idx) => {
-                    if idx as usize >= binders && (idx as usize - binders) < substs.len() {
-                        *ty = substs.0[idx as usize - binders].clone();
-                    }
-                }
-                _ => {}
-            },
-            0,
-        );
-        self
+        self.fold(&mut |ty| match ty {
+            Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)),
+            ty => ty,
+        })
     }
 
     /// Shifts up `Ty::Bound` vars by `n`.
@@ -773,22 +748,22 @@ impl TypeWalk for Ty {
         f(self);
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
         match self {
             Ty::Apply(a_ty) => {
-                a_ty.parameters.walk_mut_binders(f, binders);
+                a_ty.parameters.walk_mut(f);
             }
             Ty::Projection(p_ty) => {
-                p_ty.parameters.walk_mut_binders(f, binders);
+                p_ty.parameters.walk_mut(f);
             }
             Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
                 for p in make_mut_slice(predicates) {
-                    p.walk_mut_binders(f, binders + 1);
+                    p.walk_mut(f);
                 }
             }
             Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
         }
-        f(self, binders);
+        f(self);
     }
 }
 
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index 64d9394cf7..ca33cc7f87 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -134,19 +134,17 @@ where
 }
 
 impl<T> Canonicalized<T> {
-    pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
-        ty.walk_mut_binders(
-            &mut |ty, binders| match ty {
-                &mut Ty::Bound(idx) => {
-                    if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() {
-                        *ty = Ty::Infer(self.free_vars[idx as usize - binders]);
-                    }
+    pub fn decanonicalize_ty(&self, ty: Ty) -> Ty {
+        ty.fold(&mut |ty| match ty {
+            Ty::Bound(idx) => {
+                if (idx as usize) < self.free_vars.len() {
+                    Ty::Infer(self.free_vars[idx as usize])
+                } else {
+                    Ty::Bound(idx)
                 }
-                _ => {}
-            },
-            0,
-        );
-        ty
+            }
+            ty => ty,
+        })
     }
 
     pub fn apply_solution(
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index d20aeaacf2..9aad2d3fe7 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -228,10 +228,14 @@ fn iterate_trait_method_candidates<T>(
     'traits: for t in traits {
         let data = t.trait_data(db);
 
+        // FIXME this is a bit of a hack, since Chalk should say the same thing
+        // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
+        let inherently_implemented = ty.value.inherent_trait() == Some(t);
+
         // we'll be lazy about checking whether the type implements the
         // trait, but if we find out it doesn't, we'll skip the rest of the
         // iteration
-        let mut known_implemented = false;
+        let mut known_implemented = inherently_implemented;
         for &item in data.items() {
             if !is_valid_candidate(db, name, mode, item) {
                 continue;
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 45f7254380..4f1eab1508 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -8,7 +8,7 @@ use ra_prof::profile;
 use rustc_hash::FxHashSet;
 
 use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
-use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias};
+use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait};
 
 use self::chalk::{from_chalk, ToChalk};
 
@@ -17,7 +17,7 @@ pub(crate) mod chalk;
 #[derive(Debug, Clone)]
 pub struct TraitSolver {
     krate: Crate,
-    inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>,
+    inner: Arc<Mutex<chalk_solve::Solver>>,
 }
 
 /// We need eq for salsa
@@ -34,7 +34,7 @@ impl TraitSolver {
         &self,
         db: &impl HirDatabase,
         goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>,
-    ) -> Option<chalk_solve::Solution<ChalkIr>> {
+    ) -> Option<chalk_solve::Solution> {
         let context = ChalkContext { db, krate: self.krate };
         debug!("solve goal: {:?}", goal);
         let mut solver = match self.inner.lock() {
@@ -165,9 +165,9 @@ impl TypeWalk for ProjectionPredicate {
         self.ty.walk(f);
     }
 
-    fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
-        self.projection_ty.walk_mut_binders(f, binders);
-        self.ty.walk_mut_binders(f, binders);
+    fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+        self.projection_ty.walk_mut(f);
+        self.ty.walk_mut(f);
     }
 }
 
@@ -188,7 +188,6 @@ pub(crate) fn trait_solve_query(
     }
 
     let canonical = goal.to_chalk(db).cast();
-
     // We currently don't deal with universes (I think / hope they're not yet
     // relevant for our use cases?)
     let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
@@ -196,10 +195,7 @@ pub(crate) fn trait_solve_query(
     solution.map(|solution| solution_from_chalk(db, solution))
 }
 
-fn solution_from_chalk(
-    db: &impl HirDatabase,
-    solution: chalk_solve::Solution<ChalkIr>,
-) -> Solution {
+fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution {
     let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| {
         let value = subst
             .value
@@ -304,14 +300,3 @@ pub enum Impl {
     /// Closure types implement the Fn traits synthetically.
     ClosureFnTraitImpl(ClosureFnTraitImplData),
 }
-
-/// An associated type value. Usually this comes from a `type` declaration
-/// inside an impl block, but for built-in impls we have to synthesize it.
-/// (We only need this because Chalk wants a unique ID for each of these.)
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum AssocTyValue {
-    /// A normal assoc type value from an impl block.
-    TypeAlias(TypeAlias),
-    /// The output type of the Fn trait implementation.
-    ClosureFnTraitImplOutput(ClosureFnTraitImplData),
-}
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 9bf93981a0..68304b950c 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -7,19 +7,22 @@ use chalk_ir::{
     cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId,
     TypeKindId, TypeName, UniverseIndex,
 };
-use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
+use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
 
 use hir_expand::name;
 
 use ra_db::salsa::{InternId, InternKey};
 
-use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
+use super::{Canonical, ChalkContext, Impl, Obligation};
 use crate::{
     db::HirDatabase,
     generics::{GenericDef, HasGenericParams},
     ty::display::HirDisplay,
-    ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
-    Crate, HasBody, ImplBlock, Trait, TypeAlias,
+    ty::{
+        ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
+        TypeWalk,
+    },
+    AssocItem, Crate, HasBody, ImplBlock, Trait, TypeAlias,
 };
 
 /// This represents a trait whose name we could not resolve.
@@ -56,36 +59,29 @@ impl ToChalk for Ty {
                     }
                 };
                 let parameters = apply_ty.parameters.to_chalk(db);
-                chalk_ir::ApplicationTy { name, parameters }.cast().intern()
+                chalk_ir::ApplicationTy { name, parameters }.cast()
             }
             Ty::Projection(proj_ty) => {
                 let associated_ty_id = proj_ty.associated_ty.to_chalk(db);
                 let parameters = proj_ty.parameters.to_chalk(db);
-                chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern()
+                chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast()
             }
             Ty::Param { idx, .. } => {
                 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>()
             }
-            Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
+            Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize),
             Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
-            Ty::Dyn(predicates) => {
-                let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect();
-                chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern()
-            }
-            Ty::Opaque(predicates) => {
-                let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect();
-                chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern()
-            }
-            Ty::Unknown => {
+            // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed
+            Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => {
                 let parameters = Vec::new();
                 let name = TypeName::Error;
-                chalk_ir::ApplicationTy { name, parameters }.cast().intern()
+                chalk_ir::ApplicationTy { name, parameters }.cast()
             }
         }
     }
     fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self {
-        match chalk.data().clone() {
-            chalk_ir::TyData::Apply(apply_ty) => {
+        match chalk {
+            chalk_ir::Ty::Apply(apply_ty) => {
                 // FIXME this is kind of hacky due to the fact that
                 // TypeName::Placeholder is a Ty::Param on our side
                 match apply_ty.name {
@@ -108,21 +104,21 @@ impl ToChalk for Ty {
                     }
                 }
             }
-            chalk_ir::TyData::Projection(proj) => {
+            chalk_ir::Ty::Projection(proj) => {
                 let associated_ty = from_chalk(db, proj.associated_ty_id);
                 let parameters = from_chalk(db, proj.parameters);
                 Ty::Projection(ProjectionTy { associated_ty, parameters })
             }
-            chalk_ir::TyData::ForAll(_) => unimplemented!(),
-            chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32),
-            chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown,
-            chalk_ir::TyData::Dyn(where_clauses) => {
+            chalk_ir::Ty::ForAll(_) => unimplemented!(),
+            chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32),
+            chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown,
+            chalk_ir::Ty::Dyn(where_clauses) => {
                 assert_eq!(where_clauses.binders.len(), 1);
                 let predicates =
                     where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect();
                 Ty::Dyn(predicates)
             }
-            chalk_ir::TyData::Opaque(where_clauses) => {
+            chalk_ir::Ty::Opaque(where_clauses) => {
                 assert_eq!(where_clauses.binders.len(), 1);
                 let predicates =
                     where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect();
@@ -215,21 +211,6 @@ impl ToChalk for TypeAlias {
     }
 }
 
-impl ToChalk for AssocTyValue {
-    type Chalk = chalk_rust_ir::AssociatedTyValueId;
-
-    fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId {
-        db.intern_assoc_ty_value(self).into()
-    }
-
-    fn from_chalk(
-        db: &impl HirDatabase,
-        assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId,
-    ) -> AssocTyValue {
-        db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into())
-    }
-}
-
 impl ToChalk for GenericPredicate {
     type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>;
 
@@ -418,20 +399,20 @@ fn convert_where_clauses(
     result
 }
 
-impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB>
+impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB>
 where
     DB: HirDatabase,
 {
-    fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> {
+    fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> {
         self.db.associated_ty_data(id)
     }
-    fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> {
+    fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> {
         self.db.trait_datum(self.krate, trait_id)
     }
-    fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> {
+    fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> {
         self.db.struct_datum(self.krate, struct_id)
     }
-    fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> {
+    fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> {
         self.db.impl_datum(self.krate, impl_id)
     }
     fn impls_for_trait(
@@ -481,11 +462,13 @@ where
     fn type_name(&self, _id: TypeKindId) -> Identifier {
         unimplemented!()
     }
-    fn associated_ty_value(
+    fn split_projection<'p>(
         &self,
-        id: chalk_rust_ir::AssociatedTyValueId,
-    ) -> Arc<AssociatedTyValue<ChalkIr>> {
-        self.db.associated_ty_value(self.krate, id)
+        projection: &'p chalk_ir::ProjectionTy<ChalkIr>,
+    ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) {
+        debug!("split_projection {:?}", projection);
+        // we don't support GATs, so I think this should always be correct currently
+        (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[])
     }
     fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> {
         vec![]
@@ -502,7 +485,7 @@ where
 pub(crate) fn associated_ty_data_query(
     db: &impl HirDatabase,
     id: TypeId,
-) -> Arc<AssociatedTyDatum<ChalkIr>> {
+) -> Arc<AssociatedTyDatum> {
     debug!("associated_ty_data {:?}", id);
     let type_alias: TypeAlias = from_chalk(db, id);
     let trait_ = match type_alias.container(db) {
@@ -510,16 +493,19 @@ pub(crate) fn associated_ty_data_query(
         _ => panic!("associated type not in trait"),
     };
     let generic_params = type_alias.generic_params(db);
-    let bound_data = chalk_rust_ir::AssociatedTyDatumBound {
-        // FIXME add bounds and where clauses
-        bounds: vec![],
-        where_clauses: vec![],
-    };
+    let parameter_kinds = generic_params
+        .params_including_parent()
+        .into_iter()
+        .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string())))
+        .collect();
     let datum = AssociatedTyDatum {
         trait_id: trait_.to_chalk(db),
         id,
         name: lalrpop_intern::intern(&type_alias.name(db).to_string()),
-        binders: make_binders(bound_data, generic_params.count_params_including_parent()),
+        parameter_kinds,
+        // FIXME add bounds and where clauses
+        bounds: vec![],
+        where_clauses: vec![],
     };
     Arc::new(datum)
 }
@@ -528,10 +514,17 @@ pub(crate) fn trait_datum_query(
     db: &impl HirDatabase,
     krate: Crate,
     trait_id: chalk_ir::TraitId,
-) -> Arc<TraitDatum<ChalkIr>> {
+) -> Arc<TraitDatum> {
     debug!("trait_datum {:?}", trait_id);
     if trait_id == UNKNOWN_TRAIT {
-        let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() };
+        let trait_datum_bound = chalk_rust_ir::TraitDatumBound {
+            trait_ref: chalk_ir::TraitRef {
+                trait_id: UNKNOWN_TRAIT,
+                parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
+            },
+            associated_ty_ids: Vec::new(),
+            where_clauses: Vec::new(),
+        };
 
         let flags = chalk_rust_ir::TraitFlags {
             auto: false,
@@ -539,24 +532,18 @@ pub(crate) fn trait_datum_query(
             upstream: true,
             fundamental: false,
             non_enumerable: true,
-            coinductive: false,
         };
-        return Arc::new(TraitDatum {
-            id: trait_id,
-            binders: make_binders(trait_datum_bound, 1),
-            flags,
-            associated_ty_ids: vec![],
-        });
+        return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1), flags });
     }
     let trait_: Trait = from_chalk(db, trait_id);
     debug!("trait {:?} = {:?}", trait_id, trait_.name(db));
     let generic_params = trait_.generic_params(db);
     let bound_vars = Substs::bound_vars(&generic_params);
+    let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db);
     let flags = chalk_rust_ir::TraitFlags {
         auto: trait_.is_auto(db),
         upstream: trait_.module(db).krate() != krate,
         non_enumerable: true,
-        coinductive: false, // only relevant for Chalk testing
         // FIXME set these flags correctly
         marker: false,
         fundamental: false,
@@ -571,13 +558,10 @@ pub(crate) fn trait_datum_query(
         })
         .map(|type_alias| type_alias.to_chalk(db))
         .collect();
-    let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
-    let trait_datum = TraitDatum {
-        id: trait_id,
-        binders: make_binders(trait_datum_bound, bound_vars.len()),
-        flags,
-        associated_ty_ids,
-    };
+    let trait_datum_bound =
+        chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, associated_ty_ids };
+    let trait_datum =
+        TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()), flags };
     Arc::new(trait_datum)
 }
 
@@ -585,7 +569,7 @@ pub(crate) fn struct_datum_query(
     db: &impl HirDatabase,
     krate: Crate,
     struct_id: chalk_ir::StructId,
-) -> Arc<StructDatum<ChalkIr>> {
+) -> Arc<StructDatum> {
     debug!("struct_datum {:?}", struct_id);
     let type_ctor: TypeCtor = from_chalk(db, struct_id);
     debug!("struct {:?} = {:?}", struct_id, type_ctor);
@@ -604,12 +588,17 @@ pub(crate) fn struct_datum_query(
         // FIXME set fundamental flag correctly
         fundamental: false,
     };
+    let self_ty = chalk_ir::ApplicationTy {
+        name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()),
+        parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(),
+    };
     let struct_datum_bound = chalk_rust_ir::StructDatumBound {
+        self_ty,
         fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
         where_clauses,
+        flags,
     };
-    let struct_datum =
-        StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags };
+    let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) };
     Arc::new(struct_datum)
 }
 
@@ -617,15 +606,16 @@ pub(crate) fn impl_datum_query(
     db: &impl HirDatabase,
     krate: Crate,
     impl_id: ImplId,
-) -> Arc<ImplDatum<ChalkIr>> {
+) -> Arc<ImplDatum> {
     let _p = ra_prof::profile("impl_datum");
     debug!("impl_datum {:?}", impl_id);
     let impl_: Impl = from_chalk(db, impl_id);
     match impl_ {
         Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block),
-        Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
+        Impl::ClosureFnTraitImpl(data) => {
+            closure_fn_trait_impl_datum(db, krate, impl_id, data).unwrap_or_else(invalid_impl_datum)
+        }
     }
-    .unwrap_or_else(invalid_impl_datum)
 }
 
 fn impl_block_datum(
@@ -633,11 +623,13 @@ fn impl_block_datum(
     krate: Crate,
     impl_id: ImplId,
     impl_block: ImplBlock,
-) -> Option<Arc<ImplDatum<ChalkIr>>> {
+) -> Arc<ImplDatum> {
     let generic_params = impl_block.generic_params(db);
     let bound_vars = Substs::bound_vars(&generic_params);
-    let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars);
-    let trait_ = trait_ref.trait_;
+    let trait_ref = impl_block
+        .target_trait_ref(db)
+        .expect("FIXME handle unresolved impl block trait ref")
+        .subst(&bound_vars);
     let impl_type = if impl_block.krate(db) == krate {
         chalk_rust_ir::ImplType::Local
     } else {
@@ -652,49 +644,60 @@ fn impl_block_datum(
         trait_ref.display(db),
         where_clauses
     );
+    let trait_ = trait_ref.trait_;
     let trait_ref = trait_ref.to_chalk(db);
-
-    let polarity = if negative {
-        chalk_rust_ir::Polarity::Negative
-    } else {
-        chalk_rust_ir::Polarity::Positive
-    };
-
-    let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses };
-    let associated_ty_value_ids = impl_block
+    let associated_ty_values = impl_block
         .items(db)
         .into_iter()
         .filter_map(|item| match item {
-            crate::AssocItem::TypeAlias(type_alias) => Some(type_alias),
+            AssocItem::TypeAlias(t) => Some(t),
             _ => None,
         })
-        .filter(|type_alias| {
-            // don't include associated types that don't exist in the trait
-            trait_.associated_type_by_name(db, &type_alias.name(db)).is_some()
+        .filter_map(|t| {
+            let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?;
+            let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars);
+            Some(chalk_rust_ir::AssociatedTyValue {
+                impl_id,
+                associated_ty_id: assoc_ty.to_chalk(db),
+                value: chalk_ir::Binders {
+                    value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) },
+                    binders: vec![], // we don't support GATs yet
+                },
+            })
         })
-        .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db))
         .collect();
+
+    let polarity = if negative {
+        chalk_rust_ir::Polarity::Negative
+    } else {
+        chalk_rust_ir::Polarity::Positive
+    };
+
+    let impl_datum_bound =
+        chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses, associated_ty_values };
     debug!("impl_datum: {:?}", impl_datum_bound);
     let impl_datum = ImplDatum {
         binders: make_binders(impl_datum_bound, bound_vars.len()),
         impl_type,
         polarity,
-        associated_ty_value_ids,
     };
-    Some(Arc::new(impl_datum))
+    Arc::new(impl_datum)
 }
 
-fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> {
+fn invalid_impl_datum() -> Arc<ImplDatum> {
     let trait_ref = chalk_ir::TraitRef {
         trait_id: UNKNOWN_TRAIT,
-        parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()],
+        parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
+    };
+    let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
+        trait_ref,
+        where_clauses: Vec::new(),
+        associated_ty_values: Vec::new(),
     };
-    let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() };
     let impl_datum = ImplDatum {
         binders: make_binders(impl_datum_bound, 1),
         impl_type: chalk_rust_ir::ImplType::External,
         polarity: chalk_rust_ir::Polarity::Positive,
-        associated_ty_value_ids: Vec::new(),
     };
     Arc::new(impl_datum)
 }
@@ -702,18 +705,14 @@ fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> {
 fn closure_fn_trait_impl_datum(
     db: &impl HirDatabase,
     krate: Crate,
+    impl_id: ImplId,
     data: super::ClosureFnTraitImplData,
-) -> Option<Arc<ImplDatum<ChalkIr>>> {
+) -> Option<Arc<ImplDatum>> {
     // for some closure |X, Y| -> Z:
     // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
 
-    let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait
-
-    // validate FnOnce trait, since we need it in the assoc ty value definition
-    // and don't want to return a valid value only to find out later that FnOnce
-    // is broken
     let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
-    fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?;
+    let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait
 
     let num_args: u16 = match &data.def.body(db)[data.expr] {
         crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
@@ -727,6 +726,7 @@ fn closure_fn_trait_impl_datum(
         TypeCtor::Tuple { cardinality: num_args },
         Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
     );
+    let output_ty = Ty::Bound(num_args.into());
     let sig_ty = Ty::apply(
         TypeCtor::FnPtr { num_args },
         Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
@@ -739,99 +739,32 @@ fn closure_fn_trait_impl_datum(
         substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
     };
 
-    let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db);
+    let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?;
+
+    let output_ty_value = chalk_rust_ir::AssociatedTyValue {
+        associated_ty_id: output_ty_id.to_chalk(db),
+        impl_id,
+        value: make_binders(
+            chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) },
+            0,
+        ),
+    };
 
     let impl_type = chalk_rust_ir::ImplType::External;
 
     let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
         trait_ref: trait_ref.to_chalk(db),
         where_clauses: Vec::new(),
+        associated_ty_values: vec![output_ty_value],
     };
     let impl_datum = ImplDatum {
         binders: make_binders(impl_datum_bound, num_args as usize + 1),
         impl_type,
         polarity: chalk_rust_ir::Polarity::Positive,
-        associated_ty_value_ids: vec![output_ty_id],
     };
     Some(Arc::new(impl_datum))
 }
 
-pub(crate) fn associated_ty_value_query(
-    db: &impl HirDatabase,
-    krate: Crate,
-    id: chalk_rust_ir::AssociatedTyValueId,
-) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> {
-    let data: AssocTyValue = from_chalk(db, id);
-    match data {
-        AssocTyValue::TypeAlias(type_alias) => {
-            type_alias_associated_ty_value(db, krate, type_alias)
-        }
-        AssocTyValue::ClosureFnTraitImplOutput(data) => {
-            closure_fn_trait_output_assoc_ty_value(db, krate, data)
-        }
-    }
-}
-
-fn type_alias_associated_ty_value(
-    db: &impl HirDatabase,
-    _krate: Crate,
-    type_alias: TypeAlias,
-) -> Arc<AssociatedTyValue<ChalkIr>> {
-    let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl");
-    let impl_id = Impl::ImplBlock(impl_block).to_chalk(db);
-    let trait_ = impl_block
-        .target_trait_ref(db)
-        .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved
-        .trait_;
-    let assoc_ty = trait_
-        .associated_type_by_name(db, &type_alias.name(db))
-        .expect("assoc ty value should not exist"); // validated when building the impl data as well
-    let generic_params = impl_block.generic_params(db);
-    let bound_vars = Substs::bound_vars(&generic_params);
-    let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars);
-    let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
-    let value = chalk_rust_ir::AssociatedTyValue {
-        impl_id,
-        associated_ty_id: assoc_ty.to_chalk(db),
-        value: make_binders(value_bound, bound_vars.len()),
-    };
-    Arc::new(value)
-}
-
-fn closure_fn_trait_output_assoc_ty_value(
-    db: &impl HirDatabase,
-    krate: Crate,
-    data: super::ClosureFnTraitImplData,
-) -> Arc<AssociatedTyValue<ChalkIr>> {
-    let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db);
-
-    let num_args: u16 = match &data.def.body(db)[data.expr] {
-        crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
-        _ => {
-            log::warn!("closure for closure type {:?} not found", data);
-            0
-        }
-    };
-
-    let output_ty = Ty::Bound(num_args.into());
-
-    let fn_once_trait =
-        get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
-
-    let output_ty_id = fn_once_trait
-        .associated_type_by_name(db, &name::OUTPUT_TYPE)
-        .expect("assoc ty value should not exist");
-
-    let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) };
-
-    let value = chalk_rust_ir::AssociatedTyValue {
-        associated_ty_id: output_ty_id.to_chalk(db),
-        impl_id,
-        value: make_binders(value_bound, num_args as usize + 1),
-    };
-    Arc::new(value)
-}
-
 fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> {
     let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
     match target {
@@ -870,15 +803,3 @@ impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId {
         chalk_ir::ImplId(id_to_chalk(impl_id))
     }
 }
-
-impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId {
-    fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self {
-        id_from_chalk(id.0)
-    }
-}
-
-impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId {
-    fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self {
-        chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id))
-    }
-}
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 6c8387f6cd..821796e5f6 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,6 +1,7 @@
 //! FIXME: write short doc here
 
-use ra_db::{FileId, SourceDatabase};
+use hir::Source;
+use ra_db::SourceDatabase;
 use ra_syntax::{
     algo::find_node_at_offset,
     ast::{self, DocCommentsOwner},
@@ -21,11 +22,12 @@ pub(crate) fn goto_definition(
     let parse = db.parse(position.file_id);
     let syntax = parse.tree().syntax().clone();
     if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, position.offset) {
-        let navs = reference_definition(db, position.file_id, &name_ref).to_vec();
+        let navs =
+            reference_definition(db, Source::new(position.file_id.into(), &name_ref)).to_vec();
         return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()));
     }
     if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
-        let navs = name_definition(db, position.file_id, &name)?;
+        let navs = name_definition(db, Source::new(position.file_id.into(), &name))?;
         return Some(RangeInfo::new(name.syntax().text_range(), navs));
     }
     None
@@ -49,12 +51,11 @@ impl ReferenceResult {
 
 pub(crate) fn reference_definition(
     db: &RootDatabase,
-    file_id: FileId,
-    name_ref: &ast::NameRef,
+    name_ref: Source<&ast::NameRef>,
 ) -> ReferenceResult {
     use self::ReferenceResult::*;
 
-    let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind);
+    let name_kind = classify_name_ref(db, name_ref).map(|d| d.kind);
     match name_kind {
         Some(Macro(mac)) => return Exact(mac.to_nav(db)),
         Some(Field(field)) => return Exact(field.to_nav(db)),
@@ -76,7 +77,7 @@ pub(crate) fn reference_definition(
     };
 
     // Fallback index based approach:
-    let navs = crate::symbol_index::index_resolve(db, name_ref)
+    let navs = crate::symbol_index::index_resolve(db, name_ref.ast)
         .into_iter()
         .map(|s| s.to_nav(db))
         .collect();
@@ -85,14 +86,13 @@ pub(crate) fn reference_definition(
 
 pub(crate) fn name_definition(
     db: &RootDatabase,
-    file_id: FileId,
-    name: &ast::Name,
+    name: Source<&ast::Name>,
 ) -> Option<Vec<NavigationTarget>> {
-    let parent = name.syntax().parent()?;
+    let parent = name.ast.syntax().parent()?;
 
     if let Some(module) = ast::Module::cast(parent.clone()) {
         if module.has_semi() {
-            let src = hir::Source { file_id: file_id.into(), ast: module };
+            let src = name.with_ast(module);
             if let Some(child_module) = hir::Module::from_declaration(db, src) {
                 let nav = child_module.to_nav(db);
                 return Some(vec![nav]);
@@ -100,20 +100,20 @@ pub(crate) fn name_definition(
         }
     }
 
-    if let Some(nav) = named_target(db, file_id, &parent) {
+    if let Some(nav) = named_target(db, name.with_ast(&parent)) {
         return Some(vec![nav]);
     }
 
     None
 }
 
-fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> {
+fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<NavigationTarget> {
     match_ast! {
-        match node {
+        match (node.ast) {
             ast::StructDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -122,7 +122,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::EnumDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -131,7 +131,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::EnumVariant(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -140,7 +140,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::FnDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -149,7 +149,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::TypeAliasDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -158,7 +158,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::ConstDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -167,7 +167,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::StaticDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -176,7 +176,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::TraitDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -185,7 +185,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::RecordFieldDef(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -194,7 +194,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::Module(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     it.short_label(),
@@ -203,7 +203,7 @@ fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option
             ast::MacroCall(it) => {
                 Some(NavigationTarget::from_named(
                     db,
-                    file_id.into(),
+                    node.file_id,
                     &it,
                     it.doc_comment_text(),
                     None,
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 92b4b1f79b..cc25f4c375 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,6 +1,6 @@
 //! FIXME: write short doc here
 
-use hir::{Adt, HasSource, HirDisplay};
+use hir::{Adt, HasSource, HirDisplay, Source};
 use ra_db::SourceDatabase;
 use ra_syntax::{
     algo::{ancestors_at_offset, find_covering_element, find_node_at_offset},
@@ -171,7 +171,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
         find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset)
     {
         let mut no_fallback = false;
-        if let Some(name_kind) = classify_name_ref(db, position.file_id, &name_ref).map(|d| d.kind)
+        if let Some(name_kind) =
+            classify_name_ref(db, Source::new(position.file_id.into(), &name_ref)).map(|d| d.kind)
         {
             res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback))
         }
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index faa88d9882..1af7e8a9fa 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -14,6 +14,7 @@ mod name_definition;
 mod rename;
 mod search_scope;
 
+use hir::Source;
 use once_cell::unsync::Lazy;
 use ra_db::{SourceDatabase, SourceDatabaseExt};
 use ra_prof::profile;
@@ -114,7 +115,7 @@ fn find_name<'a>(
         return Some(RangeInfo::new(range, (name.text().to_string(), def)));
     }
     let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?;
-    let def = classify_name_ref(db, position.file_id, &name_ref)?;
+    let def = classify_name_ref(db, Source::new(position.file_id.into(), &name_ref))?;
     let range = name_ref.syntax().text_range();
     Some(RangeInfo::new(range, (name_ref.text().to_string(), def)))
 }
@@ -146,7 +147,7 @@ fn process_definition(
                         continue;
                     }
                 }
-                if let Some(d) = classify_name_ref(db, file_id, &name_ref) {
+                if let Some(d) = classify_name_ref(db, Source::new(file_id.into(), &name_ref)) {
                     if d == def {
                         refs.push(FileRange { file_id, range });
                     }
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index f12b58cb9f..5ca9da15e1 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -123,14 +123,12 @@ pub(crate) fn classify_name(
 
 pub(crate) fn classify_name_ref(
     db: &RootDatabase,
-    file_id: FileId,
-    name_ref: &ast::NameRef,
+    name_ref: Source<&ast::NameRef>,
 ) -> Option<NameDefinition> {
     let _p = profile("classify_name_ref");
 
-    let parent = name_ref.syntax().parent()?;
-    let analyzer =
-        SourceAnalyzer::new(db, hir::Source::new(file_id.into(), name_ref.syntax()), None);
+    let parent = name_ref.ast.syntax().parent()?;
+    let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None);
 
     if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
         tested_by!(goto_definition_works_for_methods);
@@ -150,17 +148,16 @@ pub(crate) fn classify_name_ref(
         tested_by!(goto_definition_works_for_record_fields);
         if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) {
             let variant_def = analyzer.resolve_record_literal(&record_lit)?;
-            let hir_path = Path::from_name_ref(name_ref);
+            let hir_path = Path::from_name_ref(name_ref.ast);
             let hir_name = hir_path.as_ident()?;
             let field = variant_def.field(db, hir_name)?;
             return Some(from_struct_field(db, field));
         }
     }
 
-    let file_id = file_id.into();
-    let ast = ModuleSource::from_child_node(db, Source::new(file_id, &parent));
+    let ast = ModuleSource::from_child_node(db, name_ref.with_ast(&parent));
     // FIXME: find correct container and visibility for each case
-    let container = Module::from_definition(db, Source { file_id, ast })?;
+    let container = Module::from_definition(db, name_ref.with_ast(ast))?;
     let visibility = None;
 
     if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
@@ -171,7 +168,7 @@ pub(crate) fn classify_name_ref(
         }
     }
 
-    let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
+    let path = name_ref.ast.syntax().ancestors().find_map(ast::Path::cast)?;
     let resolved = analyzer.resolve_path(db, &path)?;
     match resolved {
         PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))),
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index d53a759ee2..584657ca26 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -2,7 +2,7 @@
 
 use rustc_hash::{FxHashMap, FxHashSet};
 
-use hir::{Mutability, Name};
+use hir::{Mutability, Name, Source};
 use ra_db::SourceDatabase;
 use ra_prof::profile;
 use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T};
@@ -80,7 +80,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
                 }
 
                 let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap();
-                let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind);
+                let name_kind =
+                    classify_name_ref(db, Source::new(file_id.into(), &name_ref)).map(|d| d.kind);
 
                 if let Some(Local(local)) = &name_kind {
                     if let Some(name) = local.name(db) {
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts
index ac59bf60db..26372c1e8b 100644
--- a/editors/code/src/commands/runnables.ts
+++ b/editors/code/src/commands/runnables.ts
@@ -161,9 +161,7 @@ export async function startCargoWatch(
 ): Promise<CargoWatchProvider | undefined> {
     const execPromise = util.promisify(child_process.exec);
 
-    const { stderr, code = 0 } = await execPromise(
-        'cargo watch --version'
-    ).catch(e => e);
+    const { stderr } = await execPromise('cargo watch --version').catch(e => e);
 
     if (stderr.includes('no such subcommand: `watch`')) {
         const msg =
@@ -203,11 +201,6 @@ export async function startCargoWatch(
             );
             return;
         }
-    } else if (code !== 0) {
-        vscode.window.showErrorMessage(
-            `\`cargo watch\` failed with ${code}: ${stderr}`
-        );
-        return;
     }
 
     const provider = await registerCargoWatchProvider(context.subscriptions);


Test patch:
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index ca16936796..9a26e02fa2 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3983,11 +3983,11 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
     [180; 183) 'bar': fn bar() -> impl Trait<u64>
     [180; 185) 'bar()': impl Trait<u64>
     [191; 192) 'x': impl Trait<u64>
-    [191; 198) 'x.foo()': u64
+    [191; 198) 'x.foo()': {unknown}
     [204; 205) 'y': &impl Trait<u64>
-    [204; 211) 'y.foo()': u64
+    [204; 211) 'y.foo()': {unknown}
     [217; 218) 'z': impl Trait<u64>
-    [217; 224) 'z.foo()': u64
+    [217; 224) 'z.foo()': {unknown}
     [230; 231) 'x': impl Trait<u64>
     [230; 238) 'x.foo2()': i64
     [244; 245) 'y': &impl Trait<u64>
@@ -4033,11 +4033,11 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
     [177; 180) 'bar': fn bar() -> dyn Trait<u64>
     [177; 182) 'bar()': dyn Trait<u64>
     [188; 189) 'x': dyn Trait<u64>
-    [188; 195) 'x.foo()': u64
+    [188; 195) 'x.foo()': {unknown}
     [201; 202) 'y': &dyn Trait<u64>
-    [201; 208) 'y.foo()': u64
+    [201; 208) 'y.foo()': {unknown}
     [214; 215) 'z': dyn Trait<u64>
-    [214; 221) 'z.foo()': u64
+    [214; 221) 'z.foo()': {unknown}
     [227; 228) 'x': dyn Trait<u64>
     [227; 235) 'x.foo2()': i64
     [241; 242) 'y': &dyn Trait<u64>
@@ -4184,49 +4184,6 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
     );
 }
 
-#[test]
-fn impl_trait_assoc_binding_projection_bug() {
-    let (db, pos) = TestDB::with_position(
-        r#"
-//- /main.rs crate:main deps:std
-pub trait Language {
-    type Kind;
-}
-pub enum RustLanguage {}
-impl Language for RustLanguage {
-    type Kind = SyntaxKind;
-}
-struct SyntaxNode<L> {}
-fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {}
-
-trait Clone {
-    fn clone(&self) -> Self;
-}
-
-fn api_walkthrough() {
-    for node in foo() {
-        node.clone()<|>;
-    }
-}
-
-//- /std.rs crate:std
-#[prelude_import] use iter::*;
-mod iter {
-    trait IntoIterator {
-        type Item;
-    }
-    trait Iterator {
-        type Item;
-    }
-    impl<T: Iterator> IntoIterator for T {
-        type Item = <T as Iterator>::Item;
-    }
-}
-"#,
-    );
-    assert_eq!("{unknown}", type_at_pos(&db, pos));
-}
-
 #[test]
 fn projection_eq_within_chalk() {
     // std::env::set_var("CHALK_DEBUG", "1");