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.rs55
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 {