diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 2 |
2 files changed, 27 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 708a435b4..146e8a02e 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -8,12 +8,12 @@ use rustc_hash::FxHashMap; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | HirDatabase, Module, Crate, Name, Function, Trait, | 10 | HirDatabase, Module, Crate, Name, Function, Trait, |
11 | ids::TraitId, | ||
12 | impl_block::{ImplId, ImplBlock, ImplItem}, | 11 | impl_block::{ImplId, ImplBlock, ImplItem}, |
13 | ty::{Ty, TypeCtor}, | 12 | ty::{Ty, TypeCtor}, |
14 | nameres::CrateModuleId, resolve::Resolver, traits::TraitItem | 13 | nameres::CrateModuleId, resolve::Resolver, traits::TraitItem |
15 | 14 | ||
16 | }; | 15 | }; |
16 | use super::{ TraitRef, Substs}; | ||
17 | 17 | ||
18 | /// This is used as a key for indexing impls. | 18 | /// This is used as a key for indexing impls. |
19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -38,7 +38,7 @@ pub struct CrateImplBlocks { | |||
38 | /// To make sense of the CrateModuleIds, we need the source root. | 38 | /// To make sense of the CrateModuleIds, we need the source root. |
39 | krate: Crate, | 39 | krate: Crate, |
40 | impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>, | 40 | impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>, |
41 | impls_by_trait: FxHashMap<TraitId, Vec<(CrateModuleId, ImplId)>>, | 41 | impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>, |
42 | } | 42 | } |
43 | 43 | ||
44 | impl CrateImplBlocks { | 44 | impl CrateImplBlocks { |
@@ -56,8 +56,7 @@ impl CrateImplBlocks { | |||
56 | &'a self, | 56 | &'a self, |
57 | tr: &Trait, | 57 | tr: &Trait, |
58 | ) -> impl Iterator<Item = ImplBlock> + 'a { | 58 | ) -> impl Iterator<Item = ImplBlock> + 'a { |
59 | let id = tr.id; | 59 | self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map( |
60 | self.impls_by_trait.get(&id).into_iter().flat_map(|i| i.iter()).map( | ||
61 | move |(module_id, impl_id)| { | 60 | move |(module_id, impl_id)| { |
62 | let module = Module { krate: self.krate, module_id: *module_id }; | 61 | let module = Module { krate: self.krate, module_id: *module_id }; |
63 | ImplBlock::from_id(module, *impl_id) | 62 | ImplBlock::from_id(module, *impl_id) |
@@ -75,7 +74,7 @@ impl CrateImplBlocks { | |||
75 | 74 | ||
76 | if let Some(tr) = impl_block.target_trait(db) { | 75 | if let Some(tr) = impl_block.target_trait(db) { |
77 | self.impls_by_trait | 76 | self.impls_by_trait |
78 | .entry(tr.id) | 77 | .entry(tr) |
79 | .or_insert_with(Vec::new) | 78 | .or_insert_with(Vec::new) |
80 | .push((module.module_id, impl_id)); | 79 | .push((module.module_id, impl_id)); |
81 | } else { | 80 | } else { |
@@ -109,6 +108,24 @@ impl CrateImplBlocks { | |||
109 | } | 108 | } |
110 | } | 109 | } |
111 | 110 | ||
111 | /// Rudimentary check whether an impl exists for a given type and trait; this | ||
112 | /// will actually be done by chalk. | ||
113 | pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool { | ||
114 | // FIXME use all trait impls in the whole crate graph | ||
115 | let krate = trait_ref.trait_.module(db).krate(db); | ||
116 | let krate = match krate { | ||
117 | Some(krate) => krate, | ||
118 | None => return false, | ||
119 | }; | ||
120 | let crate_impl_blocks = db.impls_in_crate(krate); | ||
121 | for impl_block in crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_) { | ||
122 | if &impl_block.target_ty(db) == trait_ref.self_ty() { | ||
123 | return true; | ||
124 | } | ||
125 | } | ||
126 | false | ||
127 | } | ||
128 | |||
112 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { | 129 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { |
113 | match ty { | 130 | match ty { |
114 | Ty::Apply(a_ty) => match a_ty.ctor { | 131 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -162,7 +179,10 @@ impl Ty { | |||
162 | } | 179 | } |
163 | } | 180 | } |
164 | // FIXME the implements check may result in other obligations or unifying variables? | 181 | // FIXME the implements check may result in other obligations or unifying variables? |
165 | candidates.retain(|(_t, _m)| /* self implements t */ true); | 182 | candidates.retain(|(t, _m)| { |
183 | let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) }; | ||
184 | db.implements(trait_ref) | ||
185 | }); | ||
166 | // FIXME what happens if there are still multiple potential candidates? | 186 | // FIXME what happens if there are still multiple potential candidates? |
167 | let (_chosen_trait, chosen_method) = candidates.first()?; | 187 | let (_chosen_trait, chosen_method) = candidates.first()?; |
168 | Some((self.clone(), *chosen_method)) | 188 | Some((self.clone(), *chosen_method)) |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 971043266..655f3c522 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1920,7 +1920,7 @@ fn test() { | |||
1920 | [176; 178) 'S1': S1 | 1920 | [176; 178) 'S1': S1 |
1921 | [176; 187) 'S1.method()': u32 | 1921 | [176; 187) 'S1.method()': u32 |
1922 | [203; 205) 'S2': S2 | 1922 | [203; 205) 'S2': S2 |
1923 | [203; 214) 'S2.method()': u32"### | 1923 | [203; 214) 'S2.method()': i128"### |
1924 | ); | 1924 | ); |
1925 | } | 1925 | } |
1926 | 1926 | ||