From c46be83a346eb2559420c2c880a52e7ce1787dde Mon Sep 17 00:00:00 2001
From: kjeremy <kjeremy@gmail.com>
Date: Thu, 31 Oct 2019 13:29:56 -0400
Subject: Fixes #2143

---
 crates/ra_hir/src/source_binder.rs       |  4 +++-
 crates/ra_ide_api/src/goto_definition.rs | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 152bc71bd..0008cb232 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -255,7 +255,9 @@ impl SourceAnalyzer {
 
         let items =
             self.resolver.resolve_module_path(db, &path).take_types().map(PathResolution::Def);
-        types.or(values).or(items)
+        types.or(values).or(items).or_else(|| {
+            self.resolver.resolve_path_as_macro(db, &path).map(|def| PathResolution::Macro(def))
+        })
     }
 
     pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 1f3fa6c57..323faab33 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -315,6 +315,25 @@ mod tests {
         );
     }
 
+    #[test]
+    fn goto_definition_works_for_macros_in_use_tree() {
+        check_goto(
+            "
+            //- /lib.rs
+            use foo::foo<|>;
+
+            //- /foo/lib.rs
+            #[macro_export]
+            macro_rules! foo {
+                () => {
+                    {}
+                };
+            }
+            ",
+            "foo MACRO_CALL FileId(2) [0; 66) [29; 32)",
+        );
+    }
+
     #[test]
     fn goto_definition_works_for_methods() {
         covers!(goto_definition_works_for_methods);
-- 
cgit v1.2.3


From dcc0a9cd7ed5521aa521920c4b67e149523beb7f Mon Sep 17 00:00:00 2001
From: kjeremy <kjeremy@gmail.com>
Date: Thu, 31 Oct 2019 16:21:46 -0400
Subject: Attach docs to statics

---
 crates/ra_syntax/src/ast.rs                    | 14 ++++++++++++++
 crates/ra_syntax/src/parsing/text_tree_sink.rs |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index a12da5be2..1ec9881b9 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -112,6 +112,20 @@ fn test_doc_comment_of_items() {
     assert_eq!("doc", module.doc_comment_text().unwrap());
 }
 
+#[test]
+fn test_doc_comment_of_statics() {
+    let file = SourceFile::parse(
+        r#"
+        /// Number of levels
+        static LEVELS: i32 = 0;
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let st = file.syntax().descendants().find_map(StaticDef::cast).unwrap();
+    assert_eq!("Number of levels", st.doc_comment_text().unwrap());
+}
+
 #[test]
 fn test_doc_comment_preserves_indents() {
     let file = SourceFile::parse(
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index 142164316..c36756d6c 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -147,7 +147,7 @@ fn n_attached_trivias<'a>(
 ) -> usize {
     match kind {
         MACRO_CALL | CONST_DEF | TYPE_ALIAS_DEF | STRUCT_DEF | ENUM_DEF | ENUM_VARIANT | FN_DEF
-        | TRAIT_DEF | MODULE | RECORD_FIELD_DEF => {
+        | TRAIT_DEF | MODULE | RECORD_FIELD_DEF | STATIC_DEF => {
             let mut res = 0;
             for (i, (kind, text)) in trivias.enumerate() {
                 match kind {
-- 
cgit v1.2.3


From b634ba41e0439cbbb89b12a3d340c8463b35b93e Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Tue, 29 Oct 2019 11:04:42 +0100
Subject: Get trait assoc item resolution mostly working

---
 crates/ra_hir/src/ty.rs            |  18 +++--
 crates/ra_hir/src/ty/infer/path.rs | 106 +++++++++++++++++++++++--
 crates/ra_hir/src/ty/tests.rs      | 153 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 261 insertions(+), 16 deletions(-)

diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d2bfcdc7d..e39f06e68 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -385,13 +385,21 @@ impl SubstsBuilder {
         self.param_count - self.vec.len()
     }
 
-    pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self {
-        self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound));
-        self
+    pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
+        self.fill((starting_from..).map(Ty::Bound))
+    }
+
+    pub fn fill_with_params(self) -> Self {
+        let start = self.vec.len() as u32;
+        self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
+    }
+
+    pub fn fill_with_unknown(self) -> Self {
+        self.fill(iter::repeat(Ty::Unknown))
     }
 
-    pub fn fill_with_unknown(mut self) -> Self {
-        self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining()));
+    pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
+        self.vec.extend(filler.take(self.remaining()));
         self
     }
 
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 77aa35ce1..885588174 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,9 +6,11 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
 use crate::{
     db::HirDatabase,
     resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
+    ty::{lower, traits::TraitEnvironment, Canonical},
     ty::{Substs, Ty, TypableDef, TypeWalk},
-    AssocItem, HasGenericParams, Namespace, Path,
+    AssocItem, HasGenericParams, Name, Namespace, Path, Trait,
 };
+use std::sync::Arc;
 
 impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     pub(super) fn infer_path(
@@ -39,7 +41,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
             let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
             self.resolve_ty_assoc_item(
                 ty,
-                path.segments.last().expect("path had at least one segment"),
+                &path.segments.last().expect("path had at least one segment").name,
                 id,
             )?
         } else {
@@ -125,7 +127,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 let segment =
                     remaining_segments.last().expect("there should be at least one segment here");
 
-                self.resolve_ty_assoc_item(ty, segment, id)
+                self.resolve_ty_assoc_item(ty, &segment.name, id)
             }
         }
     }
@@ -162,7 +164,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         };
         let substs = Substs::build_for_def(self.db, item)
             .use_parent_substs(&trait_ref.substs)
-            .fill_with_unknown()
+            .fill_with_params()
             .build();
 
         self.write_assoc_resolution(id, item);
@@ -172,20 +174,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     fn resolve_ty_assoc_item(
         &mut self,
         ty: Ty,
-        segment: &PathSegment,
+        name: &Name,
         id: ExprOrPatId,
     ) -> Option<(ValueNs, Option<Substs>)> {
         if let Ty::Unknown = ty {
             return None;
         }
 
+        self.find_inherent_assoc_candidate(ty.clone(), name, id)
+            .or_else(|| self.find_trait_assoc_candidate(ty.clone(), name, id))
+    }
+
+    fn find_inherent_assoc_candidate(
+        &mut self,
+        ty: Ty,
+        name: &Name,
+        id: ExprOrPatId,
+    ) -> Option<(ValueNs, Option<Substs>)> {
         let krate = self.resolver.krate()?;
 
         // Find impl
-        // FIXME: consider trait candidates
         let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item {
             AssocItem::Function(func) => {
-                if segment.name == func.name(self.db) {
+                if *name == func.name(self.db) {
                     Some(AssocItem::Function(func))
                 } else {
                     None
@@ -193,7 +204,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
             }
 
             AssocItem::Const(konst) => {
-                if konst.name(self.db).map_or(false, |n| n == segment.name) {
+                if konst.name(self.db).map_or(false, |n| n == *name) {
                     Some(AssocItem::Const(konst))
                 } else {
                     None
@@ -212,6 +223,65 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         Some((def, substs))
     }
 
+    fn find_trait_assoc_candidate(
+        &mut self,
+        ty: Ty,
+        name: &Name,
+        _id: ExprOrPatId,
+    ) -> Option<(ValueNs, Option<Substs>)> {
+        let krate = self.resolver.krate()?;
+
+        let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
+
+        let env = lower::trait_env(self.db, &self.resolver);
+        // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
+        let traits_from_env = env
+            .trait_predicates_for_self_ty(&ty)
+            .map(|tr| tr.trait_)
+            .flat_map(|t| t.all_super_traits(self.db));
+        let traits = traits_from_env.chain(self.resolver.traits_in_scope(self.db));
+
+        'traits: for t in traits {
+            let data = t.trait_data(self.db);
+            let mut known_implemented = false;
+            for item in data.items() {
+                if let AssocItem::Function(f) = *item {
+                    if f.name(self.db) == *name {
+                        if !known_implemented {
+                            let goal = generic_implements_goal(
+                                self.db,
+                                env.clone(),
+                                t,
+                                canonical_ty.value.clone(),
+                            );
+                            if self.db.trait_solve(krate, goal).is_none() {
+                                continue 'traits;
+                            }
+                        }
+                        known_implemented = true;
+
+                        // we're picking this method
+                        let trait_substs = Substs::build_for_def(self.db, t)
+                            .push(ty.clone())
+                            .fill(std::iter::repeat_with(|| self.new_type_var()))
+                            .build();
+                        let substs = Substs::build_for_def(self.db, f)
+                            .use_parent_substs(&trait_substs)
+                            .fill_with_params()
+                            .build();
+                        self.obligations.push(super::Obligation::Trait(TraitRef {
+                            trait_: t,
+                            substs: trait_substs,
+                        }));
+                        return Some((ValueNs::Function(f), Some(substs)));
+                    }
+                }
+            }
+        }
+
+        None
+    }
+
     fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
         if let ValueNs::Function(func) = def {
             // We only do the infer if parent has generic params
@@ -242,3 +312,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         }
     }
 }
+
+// TODO remove duplication
+/// This creates Substs for a trait with the given Self type and type variables
+/// for all other parameters, to query Chalk with it.
+fn generic_implements_goal(
+    db: &impl HirDatabase,
+    env: Arc<TraitEnvironment>,
+    trait_: Trait,
+    self_ty: Canonical<Ty>,
+) -> Canonical<super::InEnvironment<super::Obligation>> {
+    let num_vars = self_ty.num_vars;
+    let substs = super::Substs::build_for_def(db, trait_)
+        .push(self_ty.value)
+        .fill_with_bound_vars(num_vars as u32)
+        .build();
+    let num_vars = substs.len() - 1 + self_ty.num_vars;
+    let trait_ref = TraitRef { trait_, substs };
+    let obligation = super::Obligation::Trait(trait_ref);
+    Canonical { num_vars, value: super::InEnvironment::new(env, obligation) }
+}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c12326643..7183b205c 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2782,9 +2782,9 @@ fn test() {
     [97; 99) 's1': S
     [105; 121) 'Defaul...efault': fn default<S>() -> Self
     [105; 123) 'Defaul...ault()': S
-    [133; 135) 's2': {unknown}
-    [138; 148) 'S::default': {unknown}
-    [138; 150) 'S::default()': {unknown}
+    [133; 135) 's2': S
+    [138; 148) 'S::default': fn default<S>() -> Self
+    [138; 150) 'S::default()': S
     [160; 162) 's3': S
     [165; 188) '<S as ...efault': fn default<S>() -> Self
     [165; 190) '<S as ...ault()': S
@@ -2792,6 +2792,153 @@ fn test() {
     );
 }
 
+#[test]
+fn infer_trait_assoc_method_generics_1() {
+    assert_snapshot!(
+        infer(r#"
+trait Trait<T> {
+    fn make() -> T;
+}
+struct S;
+impl Trait<u32> for S {}
+struct G<T>;
+impl<T> Trait<T> for G<T> {}
+fn test() {
+    let a = S::make();
+    let b = G::<u64>::make();
+    let c: f64 = G::make();
+}
+"#),
+        @r###"
+    [127; 211) '{     ...e(); }': ()
+    [137; 138) 'a': u32
+    [141; 148) 'S::make': fn make<S, u32>() -> T
+    [141; 150) 'S::make()': u32
+    [160; 161) 'b': u64
+    [164; 178) 'G::<u64>::make': fn make<G<u64>, u64>() -> T
+    [164; 180) 'G::<u6...make()': u64
+    [190; 191) 'c': f64
+    [199; 206) 'G::make': fn make<G<f64>, f64>() -> T
+    [199; 208) 'G::make()': f64
+    "###
+    );
+}
+
+#[test]
+fn infer_trait_assoc_method_generics_2() {
+    assert_snapshot!(
+        infer(r#"
+trait Trait<T> {
+    fn make<U>() -> (T, U);
+}
+struct S;
+impl Trait<u32> for S {}
+struct G<T>;
+impl<T> Trait<T> for G<T> {}
+fn test() {
+    let a = S::make::<i64>();
+    let b: (_, i64) = S::make();
+    let c = G::<u32>::make::<i64>();
+    let d: (u32, _) = G::make::<i64>();
+    let e: (u32, i64) = G::make();
+}
+"#),
+        @r###"
+    [135; 313) '{     ...e(); }': ()
+    [145; 146) 'a': (u32, i64)
+    [149; 163) 'S::make::<i64>': fn make<S, u32, i64>() -> (T, U)
+    [149; 165) 'S::mak...i64>()': (u32, i64)
+    [175; 176) 'b': (u32, i64)
+    [189; 196) 'S::make': fn make<S, u32, i64>() -> (T, U)
+    [189; 198) 'S::make()': (u32, i64)
+    [208; 209) 'c': (u32, i64)
+    [212; 233) 'G::<u3...:<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
+    [212; 235) 'G::<u3...i64>()': (u32, i64)
+    [245; 246) 'd': (u32, i64)
+    [259; 273) 'G::make::<i64>': fn make<G<u32>, u32, i64>() -> (T, U)
+    [259; 275) 'G::mak...i64>()': (u32, i64)
+    [285; 286) 'e': (u32, i64)
+    [301; 308) 'G::make': fn make<G<u32>, u32, i64>() -> (T, U)
+    [301; 310) 'G::make()': (u32, i64)
+    "###
+    );
+}
+
+#[test]
+fn infer_trait_assoc_method_generics_3() {
+    assert_snapshot!(
+        infer(r#"
+trait Trait<T> {
+    fn make() -> (Self, T);
+}
+struct S<T>;
+impl Trait<i64> for S<i32> {}
+fn test() {
+    let a = S::make();
+}
+"#),
+        @r###"
+    [101; 127) '{     ...e(); }': ()
+    [111; 112) 'a': {unknown}
+    [115; 122) 'S::make': {unknown}
+    [115; 124) 'S::make()': {unknown}
+    "###
+    );
+}
+
+#[test]
+fn infer_trait_assoc_method_generics_4() {
+    assert_snapshot!(
+        infer(r#"
+trait Trait<T> {
+    fn make() -> (Self, T);
+}
+struct S<T>;
+impl Trait<i64> for S<u64> {}
+impl Trait<i32> for S<u32> {}
+fn test() {
+    let a: (Self<i64>, _) = S::make();
+    let b: (_, u32) = S::make();
+}
+"#),
+        @r###"
+    [131; 206) '{     ...e(); }': ()
+    [141; 142) 'a': ({unknown}, {unknown})
+    [161; 168) 'S::make': {unknown}
+    [161; 170) 'S::make()': ({unknown}, {unknown})
+    [180; 181) 'b': ({unknown}, u32)
+    [194; 201) 'S::make': {unknown}
+    [194; 203) 'S::make()': ({unknown}, u32)
+    "###
+    );
+}
+
+#[test]
+fn infer_trait_assoc_method_generics_5() {
+    assert_snapshot!(
+        infer(r#"
+trait Trait<T> {
+    fn make<U>() -> (Self, T, U);
+}
+struct S<T>;
+impl Trait<i64> for S<u64> {}
+fn test() {
+    let a = <S as Trait<i64>>::make::<u8>();
+    let b: (S<u64>, _, _) = Trait::<i64>::make::<u8>();
+}
+"#),
+        @r###"
+    [107; 211) '{     ...>(); }': ()
+    [117; 118) 'a': (S<u64>, i64, u8)
+    [121; 150) '<S as ...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
+    [121; 152) '<S as ...<u8>()': (S<u64>, i64, u8)
+    [162; 163) 'b': (S<u64>, i64, u8)
+    [182; 206) 'Trait:...::<u8>': fn make<S<u64>, i64, u8>() -> (Self, T, U)
+    [182; 208) 'Trait:...<u8>()': (S<u64>, i64, u8)
+    "###
+    );
+}
+
 #[test]
 fn infer_from_bound_1() {
     assert_snapshot!(
-- 
cgit v1.2.3


From 44279ef1df49585d0b151dcfb5cefade012dbc7a Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Wed, 30 Oct 2019 20:35:01 +0100
Subject: Add another unrelated, currently not working test

---
 crates/ra_hir/src/ty/tests.rs | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 7183b205c..3af926279 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3450,6 +3450,22 @@ fn test() { S.foo()<|>; }
     assert_eq!(t, "u128");
 }
 
+#[ignore]
+#[test]
+fn method_resolution_by_value_before_autoref() {
+    let t = type_at(
+        r#"
+//- /main.rs
+trait Clone { fn clone(&self) -> Self; }
+struct S;
+impl Clone for S {}
+impl Clone for &S {}
+fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; }
+"#,
+    );
+    assert_eq!(t, "(S, S, &S)");
+}
+
 #[test]
 fn method_resolution_trait_before_autoderef() {
     let t = type_at(
-- 
cgit v1.2.3


From 7b7133ec58818894d3d56df021ae70159e2c3252 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Wed, 30 Oct 2019 21:22:46 +0100
Subject: Insert type vars before doing assoc item resolution

---
 crates/ra_hir/src/ty/infer/path.rs |  3 +++
 crates/ra_hir/src/ty/tests.rs      | 24 ++++++++++++------------
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 885588174..0cde77265 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -124,6 +124,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                     return None;
                 }
 
+                let ty = self.insert_type_vars(ty);
+                let ty = self.normalize_associated_types_in(ty);
+
                 let segment =
                     remaining_segments.last().expect("there should be at least one segment here");
 
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 3af926279..e071e4d4e 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2879,9 +2879,9 @@ fn test() {
 "#),
         @r###"
     [101; 127) '{     ...e(); }': ()
-    [111; 112) 'a': {unknown}
-    [115; 122) 'S::make': {unknown}
-    [115; 124) 'S::make()': {unknown}
+    [111; 112) 'a': (S<i32>, i64)
+    [115; 122) 'S::make': fn make<S<i32>, i64>() -> (Self, T)
+    [115; 124) 'S::make()': (S<i32>, i64)
     "###
     );
 }
@@ -2897,18 +2897,18 @@ struct S<T>;
 impl Trait<i64> for S<u64> {}
 impl Trait<i32> for S<u32> {}
 fn test() {
-    let a: (Self<i64>, _) = S::make();
-    let b: (_, u32) = S::make();
+    let a: (S<u64>, _) = S::make();
+    let b: (_, i32) = S::make();
 }
 "#),
         @r###"
-    [131; 206) '{     ...e(); }': ()
-    [141; 142) 'a': ({unknown}, {unknown})
-    [161; 168) 'S::make': {unknown}
-    [161; 170) 'S::make()': ({unknown}, {unknown})
-    [180; 181) 'b': ({unknown}, u32)
-    [194; 201) 'S::make': {unknown}
-    [194; 203) 'S::make()': ({unknown}, u32)
+    [131; 203) '{     ...e(); }': ()
+    [141; 142) 'a': (S<u64>, i64)
+    [158; 165) 'S::make': fn make<S<u64>, i64>() -> (Self, T)
+    [158; 167) 'S::make()': (S<u64>, i64)
+    [177; 178) 'b': (S<u32>, i32)
+    [191; 198) 'S::make': fn make<S<u32>, i32>() -> (Self, T)
+    [191; 200) 'S::make()': (S<u32>, i32)
     "###
     );
 }
-- 
cgit v1.2.3


From c7cedea270c492e9a2c8b81c1312fda44fd8217e Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 15:13:52 +0100
Subject: Record assoc item resolution

---
 crates/ra_hir/src/ty/infer/path.rs       |  4 ++-
 crates/ra_ide_api/src/goto_definition.rs | 55 ++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 0cde77265..c58564b22 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -230,7 +230,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         &mut self,
         ty: Ty,
         name: &Name,
-        _id: ExprOrPatId,
+        id: ExprOrPatId,
     ) -> Option<(ValueNs, Option<Substs>)> {
         let krate = self.resolver.krate()?;
 
@@ -276,6 +276,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                             trait_: t,
                             substs: trait_substs,
                         }));
+
+                        self.write_assoc_resolution(id, *item);
                         return Some((ValueNs::Function(f), Some(substs)));
                     }
                 }
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 323faab33..c1ce54bea 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -390,6 +390,61 @@ mod tests {
             "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
         );
     }
+
+    #[test]
+    fn goto_definition_works_for_ufcs_inherent_methods() {
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            impl Foo {
+                fn frobnicate() {  }
+            }
+
+            fn bar(foo: &Foo) {
+                Foo::frobnicate<|>();
+            }
+            ",
+            "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)",
+        );
+    }
+
+    #[test]
+    fn goto_definition_works_for_ufcs_trait_methods_through_traits() {
+        check_goto(
+            "
+            //- /lib.rs
+            trait Foo {
+                fn frobnicate();
+            }
+
+            fn bar() {
+                Foo::frobnicate<|>();
+            }
+            ",
+            "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)",
+        );
+    }
+
+    #[test]
+    fn goto_definition_works_for_ufcs_trait_methods_through_self() {
+        check_goto(
+            "
+            //- /lib.rs
+            struct Foo;
+            trait Trait {
+                fn frobnicate();
+            }
+            impl Trait for Foo {}
+
+            fn bar() {
+                Foo::frobnicate<|>();
+            }
+            ",
+            "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)",
+        );
+    }
+
     #[test]
     fn goto_definition_on_self() {
         check_goto(
-- 
cgit v1.2.3


From 1173c3dab5f77a1afd367d547790dd82c558fe0d Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 19:28:33 +0100
Subject: Refactor to unify with method resolution

---
 crates/ra_hir/src/code_model.rs                  |   9 ++
 crates/ra_hir/src/generics.rs                    |   3 +-
 crates/ra_hir/src/source_binder.rs               |   7 +-
 crates/ra_hir/src/ty/infer/path.rs               | 135 +++++------------------
 crates/ra_hir/src/ty/method_resolution.rs        |  90 +++++++++++----
 crates/ra_hir/src/ty/tests.rs                    |   4 +-
 crates/ra_ide_api/src/completion/complete_dot.rs |  10 +-
 7 files changed, 117 insertions(+), 141 deletions(-)

diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index ae6ef7606..c97ea18a2 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1053,4 +1053,13 @@ impl AssocItem {
             AssocItem::TypeAlias(t) => t.module(db),
         }
     }
+
+    pub fn container(self, db: &impl DefDatabase) -> Container {
+        match self {
+            AssocItem::Function(f) => f.container(db),
+            AssocItem::Const(c) => c.container(db),
+            AssocItem::TypeAlias(t) => t.container(db),
+        }
+        .expect("AssocItem without container")
+    }
 }
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 52e1fbf29..9c261eda9 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -77,9 +77,10 @@ impl GenericParams {
         let parent = match def {
             GenericDef::Function(it) => it.container(db).map(GenericDef::from),
             GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
+            GenericDef::Const(it) => it.container(db).map(GenericDef::from),
             GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()),
             GenericDef::Adt(_) | GenericDef::Trait(_) => None,
-            GenericDef::ImplBlock(_) | GenericDef::Const(_) => None,
+            GenericDef::ImplBlock(_) => None,
         };
         let mut generics = GenericParams {
             def,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 0008cb232..0398806fd 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -28,8 +28,8 @@ use crate::{
     ids::LocationCtx,
     resolve::{ScopeDef, TypeNs, ValueNs},
     ty::method_resolution::implements_trait,
-    Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module,
-    Name, Path, Resolver, Static, Struct, Ty,
+    AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId,
+    MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty,
 };
 
 fn try_get_resolver_for_node(
@@ -327,7 +327,7 @@ impl SourceAnalyzer {
         db: &impl HirDatabase,
         ty: Ty,
         name: Option<&Name>,
-        callback: impl FnMut(&Ty, Function) -> Option<T>,
+        callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
     ) -> Option<T> {
         // There should be no inference vars in types passed here
         // FIXME check that?
@@ -337,6 +337,7 @@ impl SourceAnalyzer {
             db,
             &self.resolver,
             name,
+            crate::ty::method_resolution::LookupMode::MethodCall,
             callback,
         )
     }
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index c58564b22..1946bf608 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -6,11 +6,9 @@ use super::{ExprOrPatId, InferenceContext, TraitRef};
 use crate::{
     db::HirDatabase,
     resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs},
-    ty::{lower, traits::TraitEnvironment, Canonical},
-    ty::{Substs, Ty, TypableDef, TypeWalk},
-    AssocItem, HasGenericParams, Name, Namespace, Path, Trait,
+    ty::{method_resolution, Substs, Ty, TypableDef, TypeWalk},
+    AssocItem, Container, HasGenericParams, Name, Namespace, Path,
 };
-use std::sync::Arc;
 
 impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     pub(super) fn infer_path(
@@ -184,91 +182,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
             return None;
         }
 
-        self.find_inherent_assoc_candidate(ty.clone(), name, id)
-            .or_else(|| self.find_trait_assoc_candidate(ty.clone(), name, id))
-    }
-
-    fn find_inherent_assoc_candidate(
-        &mut self,
-        ty: Ty,
-        name: &Name,
-        id: ExprOrPatId,
-    ) -> Option<(ValueNs, Option<Substs>)> {
-        let krate = self.resolver.krate()?;
-
-        // Find impl
-        let item = ty.clone().iterate_impl_items(self.db, krate, |item| match item {
-            AssocItem::Function(func) => {
-                if *name == func.name(self.db) {
-                    Some(AssocItem::Function(func))
-                } else {
-                    None
-                }
-            }
-
-            AssocItem::Const(konst) => {
-                if konst.name(self.db).map_or(false, |n| n == *name) {
-                    Some(AssocItem::Const(konst))
-                } else {
-                    None
-                }
-            }
-            AssocItem::TypeAlias(_) => None,
-        })?;
-        let def = match item {
-            AssocItem::Function(f) => ValueNs::Function(f),
-            AssocItem::Const(c) => ValueNs::Const(c),
-            AssocItem::TypeAlias(_) => unreachable!(),
-        };
-        let substs = self.find_self_types(&def, ty);
-
-        self.write_assoc_resolution(id, item);
-        Some((def, substs))
-    }
-
-    fn find_trait_assoc_candidate(
-        &mut self,
-        ty: Ty,
-        name: &Name,
-        id: ExprOrPatId,
-    ) -> Option<(ValueNs, Option<Substs>)> {
-        let krate = self.resolver.krate()?;
-
         let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
 
-        let env = lower::trait_env(self.db, &self.resolver);
-        // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
-        let traits_from_env = env
-            .trait_predicates_for_self_ty(&ty)
-            .map(|tr| tr.trait_)
-            .flat_map(|t| t.all_super_traits(self.db));
-        let traits = traits_from_env.chain(self.resolver.traits_in_scope(self.db));
-
-        'traits: for t in traits {
-            let data = t.trait_data(self.db);
-            let mut known_implemented = false;
-            for item in data.items() {
-                if let AssocItem::Function(f) = *item {
-                    if f.name(self.db) == *name {
-                        if !known_implemented {
-                            let goal = generic_implements_goal(
-                                self.db,
-                                env.clone(),
-                                t,
-                                canonical_ty.value.clone(),
-                            );
-                            if self.db.trait_solve(krate, goal).is_none() {
-                                continue 'traits;
-                            }
-                        }
-                        known_implemented = true;
-
+        method_resolution::iterate_method_candidates(
+            &canonical_ty.value,
+            self.db,
+            &self.resolver.clone(),
+            Some(name),
+            method_resolution::LookupMode::Path,
+            move |_ty, item| {
+                let def = match item {
+                    AssocItem::Function(f) => ValueNs::Function(f),
+                    AssocItem::Const(c) => ValueNs::Const(c),
+                    AssocItem::TypeAlias(_) => unreachable!(),
+                };
+                match item.container(self.db) {
+                    Container::ImplBlock(_) => {
+                        let substs = self.find_self_types(&def, ty.clone());
+
+                        self.write_assoc_resolution(id, item);
+                        Some((def, substs))
+                    }
+                    Container::Trait(t) => {
                         // we're picking this method
                         let trait_substs = Substs::build_for_def(self.db, t)
                             .push(ty.clone())
                             .fill(std::iter::repeat_with(|| self.new_type_var()))
                             .build();
-                        let substs = Substs::build_for_def(self.db, f)
+                        let substs = Substs::build_for_def(self.db, item)
                             .use_parent_substs(&trait_substs)
                             .fill_with_params()
                             .build();
@@ -277,14 +218,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                             substs: trait_substs,
                         }));
 
-                        self.write_assoc_resolution(id, *item);
-                        return Some((ValueNs::Function(f), Some(substs)));
+                        self.write_assoc_resolution(id, item);
+                        Some((def, Some(substs)))
                     }
                 }
-            }
-        }
-
-        None
+            },
+        )
     }
 
     fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
@@ -317,23 +256,3 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         }
     }
 }
-
-// TODO remove duplication
-/// This creates Substs for a trait with the given Self type and type variables
-/// for all other parameters, to query Chalk with it.
-fn generic_implements_goal(
-    db: &impl HirDatabase,
-    env: Arc<TraitEnvironment>,
-    trait_: Trait,
-    self_ty: Canonical<Ty>,
-) -> Canonical<super::InEnvironment<super::Obligation>> {
-    let num_vars = self_ty.num_vars;
-    let substs = super::Substs::build_for_def(db, trait_)
-        .push(self_ty.value)
-        .fill_with_bound_vars(num_vars as u32)
-        .build();
-    let num_vars = substs.len() - 1 + self_ty.num_vars;
-    let trait_ref = TraitRef { trait_, substs };
-    let obligation = super::Obligation::Trait(trait_ref);
-    Canonical { num_vars, value: super::InEnvironment::new(env, obligation) }
-}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index eb69344f6..ee0c7b00f 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -166,7 +166,19 @@ pub(crate) fn lookup_method(
     name: &Name,
     resolver: &Resolver,
 ) -> Option<(Ty, Function)> {
-    iterate_method_candidates(ty, db, resolver, Some(name), |ty, f| Some((ty.clone(), f)))
+    iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| {
+        if let AssocItem::Function(f) = f {
+            Some((ty.clone(), f))
+        } else {
+            None
+        }
+    })
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(crate) enum LookupMode {
+    MethodCall,
+    Path,
 }
 
 // This would be nicer if it just returned an iterator, but that runs into
@@ -176,7 +188,8 @@ pub(crate) fn iterate_method_candidates<T>(
     db: &impl HirDatabase,
     resolver: &Resolver,
     name: Option<&Name>,
-    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
+    mode: LookupMode,
+    mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
 ) -> Option<T> {
     // For method calls, rust first does any number of autoderef, and then one
     // autoref (i.e. when the method takes &self or &mut self). We just ignore
@@ -188,13 +201,15 @@ pub(crate) fn iterate_method_candidates<T>(
     // rustc does an autoderef and then autoref again).
 
     let krate = resolver.krate()?;
+    // TODO no autoderef in LookupMode::Path
     for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
-        if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback)
+        if let Some(result) =
+            iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
         {
             return Some(result);
         }
         if let Some(result) =
-            iterate_trait_method_candidates(&derefed_ty, db, resolver, name, &mut callback)
+            iterate_trait_method_candidates(&derefed_ty, db, resolver, name, mode, &mut callback)
         {
             return Some(result);
         }
@@ -207,7 +222,8 @@ fn iterate_trait_method_candidates<T>(
     db: &impl HirDatabase,
     resolver: &Resolver,
     name: Option<&Name>,
-    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
+    mode: LookupMode,
+    mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
 ) -> Option<T> {
     let krate = resolver.krate()?;
     // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
@@ -231,21 +247,35 @@ fn iterate_trait_method_candidates<T>(
         // trait, but if we find out it doesn't, we'll skip the rest of the
         // iteration
         let mut known_implemented = inherently_implemented;
-        for item in data.items() {
-            if let AssocItem::Function(m) = *item {
-                let data = m.data(db);
-                if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
-                    if !known_implemented {
-                        let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
-                        if db.trait_solve(krate, goal).is_none() {
-                            continue 'traits;
-                        }
+        for &item in data.items() {
+            // TODO unify with the impl case
+            match item {
+                AssocItem::Function(m) => {
+                    let data = m.data(db);
+                    if !name.map_or(true, |name| data.name() == name)
+                        || (!data.has_self_param() && mode != LookupMode::Path)
+                    {
+                        continue;
                     }
-                    known_implemented = true;
-                    if let Some(result) = callback(&ty.value, m) {
-                        return Some(result);
+                }
+                AssocItem::Const(c) => {
+                    if !name.map_or(true, |name| Some(name) == c.name(db).as_ref())
+                        || (mode != LookupMode::Path)
+                    {
+                        continue;
                     }
                 }
+                _ => {}
+            };
+            if !known_implemented {
+                let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
+                if db.trait_solve(krate, goal).is_none() {
+                    continue 'traits;
+                }
+            }
+            known_implemented = true;
+            if let Some(result) = callback(&ty.value, item) {
+                return Some(result);
             }
         }
     }
@@ -256,21 +286,35 @@ fn iterate_inherent_methods<T>(
     ty: &Canonical<Ty>,
     db: &impl HirDatabase,
     name: Option<&Name>,
+    mode: LookupMode,
     krate: Crate,
-    mut callback: impl FnMut(&Ty, Function) -> Option<T>,
+    mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
 ) -> Option<T> {
     for krate in def_crates(db, krate, &ty.value)? {
         let impls = db.impls_in_crate(krate);
 
         for impl_block in impls.lookup_impl_blocks(&ty.value) {
             for item in impl_block.items(db) {
-                if let AssocItem::Function(f) = item {
-                    let data = f.data(db);
-                    if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
-                        if let Some(result) = callback(&ty.value, f) {
-                            return Some(result);
+                match item {
+                    AssocItem::Function(f) => {
+                        let data = f.data(db);
+                        if !name.map_or(true, |name| data.name() == name)
+                            || (!data.has_self_param() && mode != LookupMode::Path)
+                        {
+                            continue;
                         }
                     }
+                    AssocItem::Const(c) => {
+                        if !name.map_or(true, |name| Some(name) == c.name(db).as_ref())
+                            || (mode != LookupMode::Path)
+                        {
+                            continue;
+                        }
+                    }
+                    _ => {}
+                }
+                if let Some(result) = callback(&ty.value, item) {
+                    return Some(result);
                 }
             }
         }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index e071e4d4e..bfef48b16 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1841,8 +1841,8 @@ fn test() {
     [243; 254) 'Struct::FOO': u32
     [264; 265) 'y': u32
     [268; 277) 'Enum::BAR': u32
-    [287; 288) 'z': {unknown}
-    [291; 304) 'TraitTest::ID': {unknown}
+    [287; 288) 'z': u32
+    [291; 304) 'TraitTest::ID': u32
     "###
     );
 }
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index b4df6ee2a..7135f481d 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -58,10 +58,12 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
 
 fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
     let mut seen_methods = FxHashSet::default();
-    ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
-        let data = func.data(ctx.db);
-        if data.has_self_param() && seen_methods.insert(data.name().clone()) {
-            acc.add_function(ctx, func);
+    ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, item| {
+        if let hir::AssocItem::Function(func) = item {
+            let data = func.data(ctx.db);
+            if data.has_self_param() && seen_methods.insert(data.name().clone()) {
+                acc.add_function(ctx, func);
+            }
         }
         None::<()>
     });
-- 
cgit v1.2.3


From f4181deb0dd2cce2184df0057cf349628a70f2e9 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 20:01:46 +0100
Subject: Don't do autoderef for path resolution

---
 crates/ra_hir/src/ty/method_resolution.rs | 57 +++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 18 deletions(-)

diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index ee0c7b00f..332bb14b2 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -191,27 +191,48 @@ pub(crate) fn iterate_method_candidates<T>(
     mode: LookupMode,
     mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
 ) -> Option<T> {
-    // For method calls, rust first does any number of autoderef, and then one
-    // autoref (i.e. when the method takes &self or &mut self). We just ignore
-    // the autoref currently -- when we find a method matching the given name,
-    // we assume it fits.
+    let krate = resolver.krate()?;
+    match mode {
+        LookupMode::MethodCall => {
+            // For method calls, rust first does any number of autoderef, and then one
+            // autoref (i.e. when the method takes &self or &mut self). We just ignore
+            // the autoref currently -- when we find a method matching the given name,
+            // we assume it fits.
 
-    // Also note that when we've got a receiver like &S, even if the method we
-    // find in the end takes &self, we still do the autoderef step (just as
-    // rustc does an autoderef and then autoref again).
+            // Also note that when we've got a receiver like &S, even if the method we
+            // find in the end takes &self, we still do the autoderef step (just as
+            // rustc does an autoderef and then autoref again).
 
-    let krate = resolver.krate()?;
-    // TODO no autoderef in LookupMode::Path
-    for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
-        if let Some(result) =
-            iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
-        {
-            return Some(result);
+            for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
+                if let Some(result) =
+                    iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
+                {
+                    return Some(result);
+                }
+                if let Some(result) = iterate_trait_method_candidates(
+                    &derefed_ty,
+                    db,
+                    resolver,
+                    name,
+                    mode,
+                    &mut callback,
+                ) {
+                    return Some(result);
+                }
+            }
         }
-        if let Some(result) =
-            iterate_trait_method_candidates(&derefed_ty, db, resolver, name, mode, &mut callback)
-        {
-            return Some(result);
+        LookupMode::Path => {
+            // No autoderef for path lookups
+            if let Some(result) =
+                iterate_inherent_methods(&ty, db, name, mode, krate, &mut callback)
+            {
+                return Some(result);
+            }
+            if let Some(result) =
+                iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback)
+            {
+                return Some(result);
+            }
         }
     }
     None
-- 
cgit v1.2.3


From b0bf1deb7c99d1c5b597b9b43b79a8fd3d24ddd7 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 20:37:46 +0100
Subject: Refactor a bit

---
 crates/ra_hir/src/ty/method_resolution.rs | 61 +++++++++++++------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 332bb14b2..43b485ec0 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -269,25 +269,9 @@ fn iterate_trait_method_candidates<T>(
         // iteration
         let mut known_implemented = inherently_implemented;
         for &item in data.items() {
-            // TODO unify with the impl case
-            match item {
-                AssocItem::Function(m) => {
-                    let data = m.data(db);
-                    if !name.map_or(true, |name| data.name() == name)
-                        || (!data.has_self_param() && mode != LookupMode::Path)
-                    {
-                        continue;
-                    }
-                }
-                AssocItem::Const(c) => {
-                    if !name.map_or(true, |name| Some(name) == c.name(db).as_ref())
-                        || (mode != LookupMode::Path)
-                    {
-                        continue;
-                    }
-                }
-                _ => {}
-            };
+            if !is_valid_candidate(db, name, mode, item) {
+                continue;
+            }
             if !known_implemented {
                 let goal = generic_implements_goal(db, env.clone(), t, ty.clone());
                 if db.trait_solve(krate, goal).is_none() {
@@ -316,23 +300,8 @@ fn iterate_inherent_methods<T>(
 
         for impl_block in impls.lookup_impl_blocks(&ty.value) {
             for item in impl_block.items(db) {
-                match item {
-                    AssocItem::Function(f) => {
-                        let data = f.data(db);
-                        if !name.map_or(true, |name| data.name() == name)
-                            || (!data.has_self_param() && mode != LookupMode::Path)
-                        {
-                            continue;
-                        }
-                    }
-                    AssocItem::Const(c) => {
-                        if !name.map_or(true, |name| Some(name) == c.name(db).as_ref())
-                            || (mode != LookupMode::Path)
-                        {
-                            continue;
-                        }
-                    }
-                    _ => {}
+                if !is_valid_candidate(db, name, mode, item) {
+                    continue;
                 }
                 if let Some(result) = callback(&ty.value, item) {
                     return Some(result);
@@ -343,6 +312,26 @@ fn iterate_inherent_methods<T>(
     None
 }
 
+fn is_valid_candidate(
+    db: &impl HirDatabase,
+    name: Option<&Name>,
+    mode: LookupMode,
+    item: AssocItem,
+) -> bool {
+    match item {
+        AssocItem::Function(m) => {
+            let data = m.data(db);
+            name.map_or(true, |name| data.name() == name)
+                && (data.has_self_param() || mode == LookupMode::Path)
+        }
+        AssocItem::Const(c) => {
+            name.map_or(true, |name| Some(name) == c.name(db).as_ref())
+                && (mode == LookupMode::Path)
+        }
+        _ => false,
+    }
+}
+
 pub(crate) fn implements_trait(
     ty: &Canonical<Ty>,
     db: &impl HirDatabase,
-- 
cgit v1.2.3


From 5da941897d4ed092a219729d7980bd103907850a Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 20:42:57 +0100
Subject: Add failing tests for trait assoc method completion

---
 crates/ra_ide_api/src/completion/complete_path.rs | 60 +++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index a58fdc036..b471787eb 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -558,6 +558,66 @@ mod tests {
         );
     }
 
+    #[test]
+    fn completes_trait_associated_method_1() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /lib.rs
+                trait Trait {
+                  /// A trait method
+                  fn m();
+                }
+
+                fn foo() { let _ = Trait::<|> }
+                "
+            ),
+            @"[]"
+        );
+    }
+
+    #[test]
+    fn completes_trait_associated_method_2() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /lib.rs
+                trait Trait {
+                  /// A trait method
+                  fn m();
+                }
+
+                struct S;
+                impl Trait for S {}
+
+                fn foo() { let _ = S::<|> }
+                "
+            ),
+            @"[]"
+        );
+    }
+
+    #[test]
+    fn completes_trait_associated_method_3() {
+        assert_debug_snapshot!(
+            do_reference_completion(
+                "
+                //- /lib.rs
+                trait Trait {
+                  /// A trait method
+                  fn m();
+                }
+
+                struct S;
+                impl Trait for S {}
+
+                fn foo() { let _ = <S as Trait>::<|> }
+                "
+            ),
+            @"[]"
+        );
+    }
+
     #[test]
     fn completes_type_alias() {
         assert_debug_snapshot!(
-- 
cgit v1.2.3


From 79cb0a0dab5fd8e3e84cf4a3b927ec29d2b6e65c Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Thu, 31 Oct 2019 21:21:48 +0100
Subject: Complete trait assoc items

---
 crates/ra_hir/src/lib.rs                          |  3 +-
 crates/ra_hir/src/source_binder.rs                |  8 +++--
 crates/ra_hir/src/ty/method_resolution.rs         |  2 +-
 crates/ra_ide_api/src/completion/complete_dot.rs  | 22 ++++++++-----
 crates/ra_ide_api/src/completion/complete_path.rs | 38 ++++++++++++++++++++---
 5 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 40f5562b4..4cace432e 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -76,7 +76,8 @@ pub use crate::{
     resolve::ScopeDef,
     source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
     ty::{
-        display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
+        display::HirDisplay, method_resolution::LookupMode, ApplicationTy, CallableDef, Substs,
+        TraitRef, Ty, TypeCtor, TypeWalk,
     },
 };
 
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 0398806fd..82e6eb852 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -27,7 +27,7 @@ use crate::{
     },
     ids::LocationCtx,
     resolve::{ScopeDef, TypeNs, ValueNs},
-    ty::method_resolution::implements_trait,
+    ty::method_resolution::{self, implements_trait},
     AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId,
     MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty,
 };
@@ -327,17 +327,19 @@ impl SourceAnalyzer {
         db: &impl HirDatabase,
         ty: Ty,
         name: Option<&Name>,
+        mode: method_resolution::LookupMode,
         callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
     ) -> Option<T> {
         // There should be no inference vars in types passed here
         // FIXME check that?
+        // FIXME replace Unknown by bound vars here
         let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
-        crate::ty::method_resolution::iterate_method_candidates(
+        method_resolution::iterate_method_candidates(
             &canonical,
             db,
             &self.resolver,
             name,
-            crate::ty::method_resolution::LookupMode::MethodCall,
+            mode,
             callback,
         )
     }
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 43b485ec0..9caff422f 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -176,7 +176,7 @@ pub(crate) fn lookup_method(
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum LookupMode {
+pub enum LookupMode {
     MethodCall,
     Path,
 }
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 7135f481d..fe32e7366 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -58,15 +58,21 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
 
 fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
     let mut seen_methods = FxHashSet::default();
-    ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, item| {
-        if let hir::AssocItem::Function(func) = item {
-            let data = func.data(ctx.db);
-            if data.has_self_param() && seen_methods.insert(data.name().clone()) {
-                acc.add_function(ctx, func);
+    ctx.analyzer.iterate_method_candidates(
+        ctx.db,
+        receiver,
+        None,
+        hir::LookupMode::MethodCall,
+        |_ty, item| {
+            if let hir::AssocItem::Function(func) = item {
+                let data = func.data(ctx.db);
+                if data.has_self_param() && seen_methods.insert(data.name().clone()) {
+                    acc.add_function(ctx, func);
+                }
             }
-        }
-        None::<()>
-    });
+            None::<()>
+        },
+    );
 }
 
 #[cfg(test)]
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index b471787eb..940858342 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -50,9 +50,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
                 _ => unreachable!(),
             };
-            let krate = ctx.module.map(|m| m.krate());
-            if let Some(krate) = krate {
-                ty.iterate_impl_items(ctx.db, krate, |item| {
+            ctx.analyzer.iterate_method_candidates(
+                ctx.db,
+                ty.clone(),
+                None,
+                hir::LookupMode::Path,
+                |_ty, item| {
                     match item {
                         hir::AssocItem::Function(func) => {
                             let data = func.data(ctx.db);
@@ -64,6 +67,18 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
                     }
                     None::<()>
+                },
+            );
+            // Iterate assoc types separately
+            // FIXME: complete T::AssocType
+            let krate = ctx.module.map(|m| m.krate());
+            if let Some(krate) = krate {
+                ty.iterate_impl_items(ctx.db, krate, |item| {
+                    match item {
+                        hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
+                        hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
+                    }
+                    None::<()>
                 });
             }
         }
@@ -593,7 +608,22 @@ mod tests {
                 fn foo() { let _ = S::<|> }
                 "
             ),
-            @"[]"
+            @r###"
+        [
+            CompletionItem {
+                label: "m()",
+                source_range: [99; 99),
+                delete: [99; 99),
+                insert: "m()$0",
+                kind: Function,
+                lookup: "m",
+                detail: "fn m()",
+                documentation: Documentation(
+                    "A trait method",
+                ),
+            },
+        ]
+        "###
         );
     }
 
-- 
cgit v1.2.3


From 77c26c2bf111314cc3be7ef100b6318a698c8089 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Fri, 1 Nov 2019 00:15:15 +0100
Subject: Complete items on traits as well

---
 crates/ra_ide_api/src/completion/complete_path.rs | 48 ++++++++++++++++++++++-
 1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 940858342..2aec8eb26 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -82,6 +82,20 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                 });
             }
         }
+        hir::ModuleDef::Trait(t) => {
+            for item in t.items(ctx.db) {
+                match item {
+                    hir::AssocItem::Function(func) => {
+                        let data = func.data(ctx.db);
+                        if !data.has_self_param() {
+                            acc.add_function(ctx, func);
+                        }
+                    }
+                    hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
+                    hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
+                }
+            }
+        }
         _ => {}
     };
 }
@@ -587,7 +601,22 @@ mod tests {
                 fn foo() { let _ = Trait::<|> }
                 "
             ),
-            @"[]"
+            @r###"
+        [
+            CompletionItem {
+                label: "m()",
+                source_range: [73; 73),
+                delete: [73; 73),
+                insert: "m()$0",
+                kind: Function,
+                lookup: "m",
+                detail: "fn m()",
+                documentation: Documentation(
+                    "A trait method",
+                ),
+            },
+        ]
+        "###
         );
     }
 
@@ -644,7 +673,22 @@ mod tests {
                 fn foo() { let _ = <S as Trait>::<|> }
                 "
             ),
-            @"[]"
+            @r###"
+        [
+            CompletionItem {
+                label: "m()",
+                source_range: [110; 110),
+                delete: [110; 110),
+                insert: "m()$0",
+                kind: Function,
+                lookup: "m",
+                detail: "fn m()",
+                documentation: Documentation(
+                    "A trait method",
+                ),
+            },
+        ]
+        "###
         );
     }
 
-- 
cgit v1.2.3


From dc4066ebed57d43068035f574244e3abd18ee67f Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Fri, 1 Nov 2019 11:53:29 +0100
Subject: Add some doc comments

---
 crates/ra_hir/src/ty/method_resolution.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 9caff422f..8d682bb18 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -175,9 +175,15 @@ pub(crate) fn lookup_method(
     })
 }
 
+/// Whether we're looking up a dotted method call (like `v.len()`) or a path
+/// (like `Vec::new`).
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum LookupMode {
+    /// Looking up a method call like `v.len()`: We only consider candidates
+    /// that have a `self` parameter, and do autoderef.
     MethodCall,
+    /// Looking up a path like `Vec::new` or `Vec::default`: We consider all
+    /// candidates including associated constants, but don't do autoderef.
     Path,
 }
 
-- 
cgit v1.2.3


From b29092ade31d7ff37532649dfbe1dc811edf3651 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Fri, 1 Nov 2019 19:56:56 +0100
Subject: Various review fixes

---
 crates/ra_hir/src/ty.rs                   |  1 +
 crates/ra_hir/src/ty/infer/path.rs        | 18 +++++++-----------
 crates/ra_hir/src/ty/method_resolution.rs | 11 +++++------
 3 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index e39f06e68..d1a9d7411 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -400,6 +400,7 @@ impl SubstsBuilder {
 
     pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
         self.vec.extend(filler.take(self.remaining()));
+        assert_eq!(self.remaining(), 0);
         self
     }
 
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 1946bf608..59b7f7eb6 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -196,13 +196,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                     AssocItem::Const(c) => ValueNs::Const(c),
                     AssocItem::TypeAlias(_) => unreachable!(),
                 };
-                match item.container(self.db) {
-                    Container::ImplBlock(_) => {
-                        let substs = self.find_self_types(&def, ty.clone());
-
-                        self.write_assoc_resolution(id, item);
-                        Some((def, substs))
-                    }
+                let substs = match item.container(self.db) {
+                    Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()),
                     Container::Trait(t) => {
                         // we're picking this method
                         let trait_substs = Substs::build_for_def(self.db, t)
@@ -217,11 +212,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                             trait_: t,
                             substs: trait_substs,
                         }));
-
-                        self.write_assoc_resolution(id, item);
-                        Some((def, Some(substs)))
+                        Some(substs)
                     }
-                }
+                };
+
+                self.write_assoc_resolution(id, item);
+                Some((def, substs))
             },
         )
     }
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 8d682bb18..8c3d32d09 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -166,12 +166,10 @@ pub(crate) fn lookup_method(
     name: &Name,
     resolver: &Resolver,
 ) -> Option<(Ty, Function)> {
-    iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| {
-        if let AssocItem::Function(f) = f {
-            Some((ty.clone(), f))
-        } else {
-            None
-        }
+    iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
+    {
+        AssocItem::Function(f) => Some((ty.clone(), f)),
+        _ => None,
     })
 }
 
@@ -189,6 +187,7 @@ pub enum LookupMode {
 
 // This would be nicer if it just returned an iterator, but that runs into
 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
+// FIXME add a context type here?
 pub(crate) fn iterate_method_candidates<T>(
     ty: &Canonical<Ty>,
     db: &impl HirDatabase,
-- 
cgit v1.2.3


From 895238088417b292e35705e72182ff8cc3ab6f63 Mon Sep 17 00:00:00 2001
From: Florian Diebold <flodiebold@gmail.com>
Date: Fri, 1 Nov 2019 20:01:21 +0100
Subject: Change SourceAnalyzer method resoltion API

---
 crates/ra_hir/src/lib.rs                          |  3 +--
 crates/ra_hir/src/source_binder.rs                | 27 ++++++++++++++++++++--
 crates/ra_ide_api/src/completion/complete_dot.rs  | 22 ++++++------------
 crates/ra_ide_api/src/completion/complete_path.rs | 28 +++++++++--------------
 4 files changed, 44 insertions(+), 36 deletions(-)

diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 4cace432e..40f5562b4 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -76,8 +76,7 @@ pub use crate::{
     resolve::ScopeDef,
     source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
     ty::{
-        display::HirDisplay, method_resolution::LookupMode, ApplicationTy, CallableDef, Substs,
-        TraitRef, Ty, TypeCtor, TypeWalk,
+        display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
     },
 };
 
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 82e6eb852..a4ca59bba 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -327,7 +327,30 @@ impl SourceAnalyzer {
         db: &impl HirDatabase,
         ty: Ty,
         name: Option<&Name>,
-        mode: method_resolution::LookupMode,
+        mut callback: impl FnMut(&Ty, Function) -> Option<T>,
+    ) -> Option<T> {
+        // There should be no inference vars in types passed here
+        // FIXME check that?
+        // FIXME replace Unknown by bound vars here
+        let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
+        method_resolution::iterate_method_candidates(
+            &canonical,
+            db,
+            &self.resolver,
+            name,
+            method_resolution::LookupMode::MethodCall,
+            |ty, it| match it {
+                AssocItem::Function(f) => callback(ty, f),
+                _ => None,
+            },
+        )
+    }
+
+    pub fn iterate_path_candidates<T>(
+        &self,
+        db: &impl HirDatabase,
+        ty: Ty,
+        name: Option<&Name>,
         callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
     ) -> Option<T> {
         // There should be no inference vars in types passed here
@@ -339,7 +362,7 @@ impl SourceAnalyzer {
             db,
             &self.resolver,
             name,
-            mode,
+            method_resolution::LookupMode::Path,
             callback,
         )
     }
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index fe32e7366..b4df6ee2a 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -58,21 +58,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
 
 fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
     let mut seen_methods = FxHashSet::default();
-    ctx.analyzer.iterate_method_candidates(
-        ctx.db,
-        receiver,
-        None,
-        hir::LookupMode::MethodCall,
-        |_ty, item| {
-            if let hir::AssocItem::Function(func) = item {
-                let data = func.data(ctx.db);
-                if data.has_self_param() && seen_methods.insert(data.name().clone()) {
-                    acc.add_function(ctx, func);
-                }
-            }
-            None::<()>
-        },
-    );
+    ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
+        let data = func.data(ctx.db);
+        if data.has_self_param() && seen_methods.insert(data.name().clone()) {
+            acc.add_function(ctx, func);
+        }
+        None::<()>
+    });
 }
 
 #[cfg(test)]
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 2aec8eb26..9ac9768af 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -50,25 +50,19 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
                 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
                 _ => unreachable!(),
             };
-            ctx.analyzer.iterate_method_candidates(
-                ctx.db,
-                ty.clone(),
-                None,
-                hir::LookupMode::Path,
-                |_ty, item| {
-                    match item {
-                        hir::AssocItem::Function(func) => {
-                            let data = func.data(ctx.db);
-                            if !data.has_self_param() {
-                                acc.add_function(ctx, func);
-                            }
+            ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| {
+                match item {
+                    hir::AssocItem::Function(func) => {
+                        let data = func.data(ctx.db);
+                        if !data.has_self_param() {
+                            acc.add_function(ctx, func);
                         }
-                        hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
-                        hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
                     }
-                    None::<()>
-                },
-            );
+                    hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
+                    hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
+                }
+                None::<()>
+            });
             // Iterate assoc types separately
             // FIXME: complete T::AssocType
             let krate = ctx.module.map(|m| m.krate());
-- 
cgit v1.2.3


From e3354c1496a6fd6b80ad563712edb88b12bb7372 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= <lnicola@dend.ro>
Date: Fri, 1 Nov 2019 22:20:44 +0200
Subject: Use run-time project path in xtask

---
 xtask/src/lib.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index cc69463a9..bae4c4650 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -3,6 +3,7 @@
 pub mod codegen;
 
 use std::{
+    env,
     error::Error,
     fs,
     io::{Error as IoError, ErrorKind},
@@ -17,7 +18,13 @@ pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
 const TOOLCHAIN: &str = "stable";
 
 pub fn project_root() -> PathBuf {
-    Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(1).unwrap().to_path_buf()
+    Path::new(
+        &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
+    )
+    .ancestors()
+    .nth(1)
+    .unwrap()
+    .to_path_buf()
 }
 
 pub struct Cmd<'a> {
-- 
cgit v1.2.3