Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/utils.rs')
-rw-r--r--crates/hir-ty/src/utils.rs149
1 files changed, 86 insertions, 63 deletions
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 39e7bdd962..cadb099c2b 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -9,12 +9,11 @@ use chalk_ir::{
fold::{FallibleTypeFolder, Shift},
BoundVar, DebruijnIndex,
};
-use either::Either;
use hir_def::{
db::DefDatabase,
generics::{
- GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
- WherePredicate, WherePredicateTypeTarget,
+ GenericParamData, GenericParams, LifetimeParamData, TypeOrConstParamData,
+ TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
lang_item::LangItem,
resolver::{HasResolver, TypeNs},
@@ -271,81 +270,102 @@ pub(crate) struct Generics {
}
impl Generics {
- pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
- self.iter().map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
- TypeOrConstParamData::ConstParamData(_) => {
- Either::Right(ConstParamId::from_unchecked(id))
- }
- })
+ pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+ self.iter().map(|(id, _)| id)
}
/// Iterator over types and const params of self, then parent.
pub(crate) fn iter<'a>(
&'a self,
- ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
- let to_toc_id = |it: &'a Generics| {
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+ let from_toc_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ }
};
- self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
+
+ let from_lt_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
+ }
+ };
+
+ let lt_iter = self.params.iter_lt().map(from_lt_id(self));
+ self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent())
}
/// Iterate over types and const params without parent params.
pub(crate) fn iter_self<'a>(
&'a self,
- ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
- let to_toc_id = |it: &'a Generics| {
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + 'a {
+ let from_toc_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ }
};
- self.params.iter().map(to_toc_id(self))
- }
- /// Iterator over types and const params of parent.
- pub(crate) fn iter_parent(
- &self,
- ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
- self.parent_generics().into_iter().flat_map(|it| {
- let to_toc_id =
- move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
- it.params.iter().map(to_toc_id)
- })
- }
-
- pub(crate) fn iter_id_with_lt(&self) -> impl Iterator<Item = GenericParamId> + '_ {
- let toc_iter = self.iter().map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => {
- GenericParamId::TypeParamId(TypeParamId::from_unchecked(id))
- }
- TypeOrConstParamData::ConstParamData(_) => {
- GenericParamId::ConstParamId(ConstParamId::from_unchecked(id))
+ let from_lt_id = |it: &'a Generics| {
+ move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
}
- });
- let lt_iter = self.iter_lt().map(|(id, _)| GenericParamId::LifetimeParamId(id));
-
- toc_iter.chain(lt_iter)
- }
-
- pub(crate) fn iter_lt<'a>(
- &'a self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
- self.iter_lt_self().chain(self.iter_lt_parent())
- }
-
- fn iter_lt_self<'a>(
- &'a self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &'a LifetimeParamData)> + 'a {
- let to_id = |it: &'a Generics| {
- move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p)
};
- self.params.iter_lt().map(to_id(self))
+
+ self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
}
- fn iter_lt_parent(
+ /// Iterator over types and const params of parent.
+ pub(crate) fn iter_parent(
&self,
- ) -> impl DoubleEndedIterator<Item = (LifetimeParamId, &LifetimeParamData)> {
+ ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamData)> + '_ {
self.parent_generics().into_iter().flat_map(|it| {
- let to_id = move |(local_id, p)| (LifetimeParamId { parent: it.def, local_id }, p);
- it.params.iter_lt().map(to_id)
+ let from_toc_id = move |(local_id, p): (_, &TypeOrConstParamData)| {
+ let id = TypeOrConstParamId { parent: it.def, local_id };
+ match p {
+ TypeOrConstParamData::TypeParamData(p) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamData::TypeParamData(p.clone()),
+ ),
+ TypeOrConstParamData::ConstParamData(p) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamData::ConstParamData(p.clone()),
+ ),
+ }
+ };
+
+ let from_lt_id = move |(local_id, p): (_, &LifetimeParamData)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+ GenericParamData::LifetimeParamData(p.clone()),
+ )
+ };
+ let lt_iter = it.params.iter_lt().map(from_lt_id);
+ it.params.iter().map(from_toc_id).chain(lt_iter)
})
}
@@ -437,7 +457,7 @@ impl Generics {
) -> Substitution {
Substitution::from_iter(
Interner,
- self.iter_id_with_lt().enumerate().map(|(idx, id)| match id {
+ self.iter_id().enumerate().map(|(idx, id)| match id {
GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
.to_const(Interner, db.const_param_ty(id))
.cast(Interner),
@@ -456,12 +476,15 @@ impl Generics {
Substitution::from_iter(
Interner,
self.iter_id().map(|id| match id {
- Either::Left(id) => {
+ GenericParamId::TypeParamId(id) => {
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
}
- Either::Right(id) => crate::to_placeholder_idx(db, id.into())
- .to_const(Interner, db.const_param_ty(id))
+ GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
+ .to_const(Interner, db.const_param_ty(id.into()))
.cast(Interner),
+ GenericParamId::LifetimeParamId(id) => {
+ crate::lt_to_placeholder_idx(db, id.into()).to_lifetime(Interner).cast(Interner)
+ }
}),
)
}