aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/method_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs47
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.
113pub(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
125fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { 111fn 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
236fn 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}