aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/method_resolution.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-22 12:23:50 +0100
committerFlorian Diebold <[email protected]>2019-08-22 20:55:11 +0100
commitb1a40042e8f595af0486cf1cc70b63be1ff302b3 (patch)
treec3f58127c4a330275d2dd635bb5fb11ca7957ddc /crates/ra_hir/src/ty/method_resolution.rs
parent16a7d8cc850002b427fdc8d21ccde81caaed7902 (diff)
Handle impl/dyn Trait in method resolution
When we have one of these, the `Trait` doesn't need to be in scope to call its methods. So we need to consider this when looking for method candidates. (Actually I think the same is true when we have a bound `T: some::Trait`, but we don't handle that yet). At the same time, since Chalk doesn't handle these types yet, add a small hack to skip Chalk in method resolution and just consider `impl Trait: Trait` always true. This is enough to e.g. get completions for `impl Trait`, but since we don't do any unification we won't infer the return type of e.g. `impl Into<i64>::into()`.
Diffstat (limited to 'crates/ra_hir/src/ty/method_resolution.rs')
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 3f4c43aee..9873a0440 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -211,12 +211,19 @@ fn iterate_trait_method_candidates<T>(
211 let krate = resolver.krate()?; 211 let krate = resolver.krate()?;
212 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 212 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
213 let env = lower::trait_env(db, resolver); 213 let env = lower::trait_env(db, resolver);
214 'traits: for t in resolver.traits_in_scope(db) { 214 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
215 let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db));
216 'traits: for t in traits {
215 let data = t.trait_data(db); 217 let data = t.trait_data(db);
218
219 // FIXME this is a bit of a hack, since Chalk should say the same thing
220 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
221 let inherently_implemented = ty.value.inherent_trait() == Some(t);
222
216 // we'll be lazy about checking whether the type implements the 223 // we'll be lazy about checking whether the type implements the
217 // trait, but if we find out it doesn't, we'll skip the rest of the 224 // trait, but if we find out it doesn't, we'll skip the rest of the
218 // iteration 225 // iteration
219 let mut known_implemented = false; 226 let mut known_implemented = inherently_implemented;
220 for item in data.items() { 227 for item in data.items() {
221 if let TraitItem::Function(m) = *item { 228 if let TraitItem::Function(m) = *item {
222 let data = m.data(db); 229 let data = m.data(db);
@@ -271,6 +278,11 @@ pub(crate) fn implements_trait(
271 krate: Crate, 278 krate: Crate,
272 trait_: Trait, 279 trait_: Trait,
273) -> bool { 280) -> bool {
281 if ty.value.inherent_trait() == Some(trait_) {
282 // FIXME this is a bit of a hack, since Chalk should say the same thing
283 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
284 return true;
285 }
274 let env = lower::trait_env(db, resolver); 286 let env = lower::trait_env(db, resolver);
275 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); 287 let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone());
276 let solution = db.trait_solve(krate, goal); 288 let solution = db.trait_solve(krate, goal);