From b1a40042e8f595af0486cf1cc70b63be1ff302b3 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 22 Aug 2019 13:23:50 +0200 Subject: 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::into()`. --- crates/ra_hir/src/ty/method_resolution.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir/src/ty/method_resolution.rs') 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( let krate = resolver.krate()?; // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) let env = lower::trait_env(db, resolver); - 'traits: for t in resolver.traits_in_scope(db) { + // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope + let traits = ty.value.inherent_trait().into_iter().chain(resolver.traits_in_scope(db)); + 'traits: for t in traits { let data = t.trait_data(db); + + // FIXME this is a bit of a hack, since Chalk should say the same thing + // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet + let inherently_implemented = ty.value.inherent_trait() == Some(t); + // we'll be lazy about checking whether the type implements the // trait, but if we find out it doesn't, we'll skip the rest of the // iteration - let mut known_implemented = false; + let mut known_implemented = inherently_implemented; for item in data.items() { if let TraitItem::Function(m) = *item { let data = m.data(db); @@ -271,6 +278,11 @@ pub(crate) fn implements_trait( krate: Crate, trait_: Trait, ) -> bool { + if ty.value.inherent_trait() == Some(trait_) { + // FIXME this is a bit of a hack, since Chalk should say the same thing + // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet + return true; + } let env = lower::trait_env(db, resolver); let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); let solution = db.trait_solve(krate, goal); -- cgit v1.2.3