Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 3bc2eee1e7..8186af296a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3574,6 +3574,61 @@ impl GenericDef { } } +// We cannot call this `Substitution` unfortunately... +#[derive(Debug)] +pub struct GenericSubstitution { + def: GenericDefId, + subst: Substitution, + env: Arc<TraitEnvironment>, +} + +impl GenericSubstitution { + fn new(def: GenericDefId, subst: Substitution, env: Arc<TraitEnvironment>) -> Self { + Self { def, subst, env } + } + + pub fn types(&self, db: &dyn HirDatabase) -> Vec<(Symbol, Type)> { + let container = match self.def { + GenericDefId::ConstId(id) => Some(id.lookup(db.upcast()).container), + GenericDefId::FunctionId(id) => Some(id.lookup(db.upcast()).container), + GenericDefId::TypeAliasId(id) => Some(id.lookup(db.upcast()).container), + _ => None, + }; + let container_type_params = container + .and_then(|container| match container { + ItemContainerId::ImplId(container) => Some(container.into()), + ItemContainerId::TraitId(container) => Some(container.into()), + _ => None, + }) + .map(|container| { + db.generic_params(container) + .iter_type_or_consts() + .filter_map(|param| match param.1 { + TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), + TypeOrConstParamData::ConstParamData(_) => None, + }) + .collect::<Vec<_>>() + }); + let generics = db.generic_params(self.def); + let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 { + TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), + TypeOrConstParamData::ConstParamData(_) => None, + }); + // The `Substitution` is first self then container, we want the reverse order. + let self_params = self.subst.type_parameters(Interner).zip(type_params); + let container_params = self.subst.as_slice(Interner)[generics.len()..] + .iter() + .filter_map(|param| param.ty(Interner).cloned()) + .zip(container_type_params.into_iter().flatten()); + container_params + .chain(self_params) + .filter_map(|(ty, name)| { + Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) + }) + .collect() + } +} + /// A single local definition. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Local { |