From 811d25b7237cfb74a312369a7820bf6fbb81483e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 16 May 2020 18:32:15 +0200 Subject: Allow calling dyn trait super trait methods without the super trait in scope This also removes some vestiges of the old impl trait support which I think aren't currently in use. --- crates/ra_hir_ty/src/lib.rs | 14 +++++------ crates/ra_hir_ty/src/method_resolution.rs | 10 +++----- crates/ra_hir_ty/src/tests/method_resolution.rs | 31 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index ccc4348f4..daea02f88 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -808,15 +808,13 @@ impl Ty { } } - /// If this is an `impl Trait` or `dyn Trait`, returns that trait. - pub fn inherent_trait(&self) -> Option { + /// If this is a `dyn Trait`, returns that trait. + pub fn dyn_trait(&self) -> Option { match self { - Ty::Dyn(predicates) | Ty::Opaque(predicates) => { - predicates.iter().find_map(|pred| match pred { - GenericPredicate::Implemented(tr) => Some(tr.trait_), - _ => None, - }) - } + Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred { + GenericPredicate::Implemented(tr) => Some(tr.trait_), + _ => None, + }), _ => None, } } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 657284fd0..0851e16a8 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -408,8 +408,9 @@ fn iterate_trait_method_candidates( receiver_ty: Option<&Canonical>, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { - // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope - let inherent_trait = self_ty.value.inherent_trait().into_iter(); + // if ty is `dyn Trait`, the trait doesn't need to be in scope + let inherent_trait = + self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); let env_traits = if let Ty::Placeholder(_) = self_ty.value { // if we have `T: Trait` in the param env, the trait doesn't need to be in scope env.trait_predicates_for_self_ty(&self_ty.value) @@ -601,11 +602,6 @@ pub fn implements_trait( krate: CrateId, trait_: TraitId, ) -> 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 goal = generic_implements_goal(db, env, trait_, ty.clone()); let solution = db.trait_solve(krate, goal); diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 67f964ab5..9c2c9e1d2 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs @@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; } ); assert_eq!(t, "()"); } + +#[test] +fn dyn_trait_super_trait_not_in_scope() { + assert_snapshot!( + infer(r#" +mod m { + pub trait SuperTrait { + fn foo(&self) -> u32 { 0 } + } +} +trait Trait: m::SuperTrait {} + +struct S; +impl m::SuperTrait for S {} +impl Trait for S {} + +fn test(d: &dyn Trait) { + d.foo(); +} +"#), + @r###" + 52..56 'self': &Self + 65..70 '{ 0 }': u32 + 67..68 '0': u32 + 177..178 'd': &dyn Trait + 192..208 '{ ...o(); }': () + 198..199 'd': &dyn Trait + 198..205 'd.foo()': u32 + "### + ); +} -- cgit v1.2.3