diff options
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index aac7d6384..f69b8304b 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -108,20 +108,6 @@ impl CrateImplBlocks { | |||
108 | } | 108 | } |
109 | } | 109 | } |
110 | 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 | let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_); | ||
122 | impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty()) | ||
123 | } | ||
124 | |||
125 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { | 111 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { |
126 | match ty { | 112 | match ty { |
127 | Ty::Apply(a_ty) => match a_ty.ctor { | 113 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -142,6 +128,7 @@ impl Ty { | |||
142 | resolver: &Resolver, | 128 | resolver: &Resolver, |
143 | ) -> Option<(Ty, Function)> { | 129 | ) -> Option<(Ty, Function)> { |
144 | // FIXME: trait methods should be used before autoderefs | 130 | // FIXME: trait methods should be used before autoderefs |
131 | // (and we need to do autoderefs for trait method calls as well) | ||
145 | let inherent_method = self.clone().iterate_methods(db, |ty, f| { | 132 | let inherent_method = self.clone().iterate_methods(db, |ty, f| { |
146 | let sig = f.signature(db); | 133 | let sig = f.signature(db); |
147 | if sig.name() == name && sig.has_self_param() { | 134 | if sig.name() == name && sig.has_self_param() { |
@@ -174,24 +161,15 @@ impl Ty { | |||
174 | } | 161 | } |
175 | } | 162 | } |
176 | } | 163 | } |
177 | // FIXME: | ||
178 | // - we might not actually be able to determine fully that the type | ||
179 | // implements the trait here; it's enough if we (well, Chalk) determine | ||
180 | // that it's possible. | ||
181 | // - when the trait method is picked, we need to register an | ||
182 | // 'obligation' somewhere so that we later check that it's really | ||
183 | // implemented | ||
184 | // - both points go for additional requirements from where clauses as | ||
185 | // well (in fact, the 'implements' condition could just be considered a | ||
186 | // 'where Self: Trait' clause) | ||
187 | candidates.retain(|(t, _m)| { | 164 | candidates.retain(|(t, _m)| { |
188 | // FIXME construct substs of the correct length for the trait | 165 | let trait_ref = |
189 | // - check in rustc whether it does anything smarter than putting variables for everything | 166 | TraitRef { trait_: *t, substs: fresh_substs_for_trait(db, *t, self.clone()) }; |
190 | let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) }; | 167 | let (trait_ref, _) = super::traits::canonicalize(trait_ref); |
191 | db.implements(trait_ref) | 168 | db.implements(trait_ref).is_some() |
192 | }); | 169 | }); |
193 | // FIXME if there's multiple candidates here, that's an ambiguity error | 170 | // FIXME if there's multiple candidates here, that's an ambiguity error |
194 | let (_chosen_trait, chosen_method) = candidates.first()?; | 171 | let (_chosen_trait, chosen_method) = candidates.first()?; |
172 | // FIXME return correct receiver type | ||
195 | Some((self.clone(), *chosen_method)) | 173 | Some((self.clone(), *chosen_method)) |
196 | } | 174 | } |
197 | 175 | ||
@@ -254,3 +232,16 @@ impl Ty { | |||
254 | None | 232 | None |
255 | } | 233 | } |
256 | } | 234 | } |
235 | |||
236 | fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs { | ||
237 | let mut substs = Vec::new(); | ||
238 | let mut counter = 0; | ||
239 | let generics = tr.generic_params(db); | ||
240 | substs.push(self_ty); | ||
241 | substs.extend(generics.params_including_parent().into_iter().skip(1).map(|_p| { | ||
242 | let fresh_var = Ty::Infer(super::infer::InferTy::TypeVar(super::infer::TypeVarId(counter))); | ||
243 | counter += 1; | ||
244 | fresh_var | ||
245 | })); | ||
246 | substs.into() | ||
247 | } | ||