diff options
author | Florian Diebold <[email protected]> | 2019-08-22 12:23:50 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-08-22 20:55:11 +0100 |
commit | b1a40042e8f595af0486cf1cc70b63be1ff302b3 (patch) | |
tree | c3f58127c4a330275d2dd635bb5fb11ca7957ddc /crates/ra_hir/src/ty/method_resolution.rs | |
parent | 16a7d8cc850002b427fdc8d21ccde81caaed7902 (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.rs | 16 |
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); |