From 4b07c1e77515ae9198aae6275700aacd43181b50 Mon Sep 17 00:00:00 2001 From: vsrs Date: Thu, 11 Jun 2020 20:17:32 +0300 Subject: Add Type::walk method --- crates/ra_hir_ty/src/lib.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'crates/ra_hir_ty/src/lib.rs') diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 9d4d6aaa4..25ab9d872 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -877,6 +877,58 @@ impl Ty { _ => None, } } + + pub fn impl_trait_ref(&self, db: &dyn HirDatabase) -> Option { + match self { + Ty::Opaque(opaque_ty) => { + let predicates = match opaque_ty.opaque_ty_id { + OpaqueTyId::ReturnTypeImplTrait(func, idx) => { + db.return_type_impl_traits(func).map(|it| { + let data = (*it) + .as_ref() + .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); + data.clone().subst(&opaque_ty.parameters) + }) + } + }; + + predicates.and_then(|it| { + it.value.iter().find_map(|pred| match pred { + GenericPredicate::Implemented(tr) => Some(tr.clone()), + _ => None, + }) + }) + } + Ty::Placeholder(id) => { + let generic_params = db.generic_params(id.parent); + let param_data = &generic_params.types[id.local_id]; + match param_data.provenance { + hir_def::generics::TypeParamProvenance::ArgumentImplTrait => db + .generic_predicates_for_param(*id) + .into_iter() + .map(|pred| pred.value.clone()) + .find_map(|pred| match pred { + GenericPredicate::Implemented(tr) => Some(tr.clone()), + _ => None, + }), + _ => None, + } + } + _ => None, + } + } + + pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option { + match self { + Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => { + match type_alias_id.lookup(db.upcast()).container { + AssocContainerId::TraitId(trait_id) => Some(trait_id), + _ => None, + } + } + _ => None, + } + } } /// This allows walking structures that contain types to do something with those -- cgit v1.2.3