Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/generics.rs')
-rw-r--r--crates/hir-ty/src/generics.rs129
1 files changed, 104 insertions, 25 deletions
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 1f98fcb466..f2ca060bb5 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -72,17 +72,31 @@ impl<'db> SingleGenerics<'db> {
self.params.len_lifetimes()
}
- pub(crate) fn len(&self) -> usize {
- self.params.len()
+ pub(crate) fn len(&self, consider_late_bound: bool) -> usize {
+ if consider_late_bound {
+ self.params.len()
+ } else {
+ self.params.len() - self.params.len_late_bound_lifetimes()
+ }
}
fn iter_lifetimes(&self) -> impl Iterator<Item = (LifetimeParamId, &'db LifetimeParamData)> {
let parent = self.def;
self.params
- .iter_lt()
+ .iter_early_bound_lt()
.map(move |(local_id, data)| (LifetimeParamId { parent, local_id }, data))
}
+ fn iter_late_bound_lifetimes(
+ &self,
+ consider_late_bound: bool,
+ ) -> impl Iterator<Item = (LifetimeParamId, &'db LifetimeParamData)> {
+ let parent = self.def;
+ self.params.iter_late_bound_lt().filter_map(move |(local_id, data)| {
+ consider_late_bound.then_some((LifetimeParamId { parent, local_id }, data))
+ })
+ }
+
pub(crate) fn iter_type_or_consts(
&self,
) -> impl Iterator<Item = (TypeOrConstParamId, &'db TypeOrConstParamData)> {
@@ -118,23 +132,46 @@ impl<'db> SingleGenerics<'db> {
(trait_self, iter)
}
- pub(crate) fn iter(&self) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
- let lifetimes = self.iter_lifetimes().map(|(id, data)| {
+ pub(crate) fn iter(
+ &self,
+ consider_late_bound: bool,
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ let lifetime_map = |(id, data)| {
(GenericParamId::LifetimeParamId(id), GenericParamDataRef::LifetimeParamData(data))
- });
+ };
+ let lifetimes = self.iter_lifetimes().map(lifetime_map);
+ let late_bound_lifetimes =
+ self.iter_late_bound_lifetimes(consider_late_bound).map(lifetime_map);
+
let (trait_self, type_and_consts) = self.trait_self_and_others();
- trait_self.into_iter().chain(lifetimes).chain(type_and_consts)
+ trait_self.into_iter().chain(lifetimes).chain(type_and_consts).chain(late_bound_lifetimes)
}
pub(crate) fn iter_with_idx(
&self,
) -> impl Iterator<Item = (u32, GenericParamId, GenericParamDataRef<'db>)> {
- std::iter::zip(self.preceding_params_len.., self.iter())
+ std::iter::zip(self.preceding_params_len.., self.iter(false))
.map(|(index, (id, data))| (index, id, data))
}
- pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
- self.iter().map(|(id, _)| id)
+ pub(crate) fn iter_id(
+ &self,
+ consider_late_bound: bool,
+ ) -> impl Iterator<Item = GenericParamId> {
+ self.iter(consider_late_bound).map(|(id, _)| id)
+ }
+
+ pub(crate) fn iter_late_bound(
+ &self,
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ // we don't handle late bound types or const now, so it is ignored for now
+ let parent = self.def;
+ self.params.iter_late_bound_lt().map(move |(local_id, data)| {
+ (
+ GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }),
+ GenericParamDataRef::LifetimeParamData(data),
+ )
+ })
}
}
@@ -169,7 +206,7 @@ impl<'db> Generics<'db> {
pub(crate) fn iter_self(
&self,
) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
- self.owner().iter()
+ self.owner().iter(false)
}
pub(crate) fn iter_self_with_idx(
@@ -178,8 +215,14 @@ impl<'db> Generics<'db> {
self.owner().iter_with_idx()
}
+ pub(crate) fn iter_self_late_bound(
+ &self,
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ self.owner().iter_late_bound()
+ }
+
pub(crate) fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> {
- self.parent().into_iter().flat_map(|parent| parent.iter_id())
+ self.parent().into_iter().flat_map(move |parent| parent.iter_id(false))
}
pub(crate) fn iter_self_type_or_consts(
@@ -189,27 +232,33 @@ impl<'db> Generics<'db> {
}
/// Iterate over the parent params followed by self params.
- #[cfg(test)]
- pub(crate) fn iter(&self) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'_>)> {
- self.iter_owners().flat_map(|owner| owner.iter())
+ pub(crate) fn iter(
+ &self,
+ consider_late_bound: bool,
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ self.iter_owners().flat_map(move |owner| owner.iter(consider_late_bound))
}
- pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
- self.iter_owners().flat_map(|owner| owner.iter_id())
+ pub(crate) fn iter_id(
+ &self,
+ consider_late_bound: bool,
+ ) -> impl Iterator<Item = GenericParamId> {
+ self.iter_owners().flat_map(move |owner| owner.iter_id(consider_late_bound))
}
/// Returns total number of generic parameters in scope, including those from parent.
- pub(crate) fn len(&self) -> usize {
+ pub(crate) fn len(&self, consider_late_bound: bool) -> usize {
match &*self.chain {
- [parent, owner] => parent.len() + owner.len(),
- [owner] => owner.len(),
+ [parent, owner] => parent.len(consider_late_bound) + owner.len(consider_late_bound),
+ [owner] => owner.len(consider_late_bound),
_ => unreachable!(),
}
}
#[inline]
pub(crate) fn len_parent(&self) -> usize {
- self.parent().map_or(0, SingleGenerics::len)
+ // add `consider_late_bound` arg if needed in future, currently it's not needed.
+ self.parent().map_or(0, |p| p.len(true))
}
pub(crate) fn len_lifetimes_self(&self) -> usize {
@@ -275,12 +324,30 @@ impl<'db> Generics<'db> {
}
}
- pub(crate) fn lifetime_param_idx(&self, param: LifetimeParamId) -> u32 {
+ // Rename this?
+ pub(crate) fn lifetime_param_idx(
+ &self,
+ param: LifetimeParamId,
+ is_lowering_impl_trait_bounds: bool,
+ ) -> (u32, bool) {
let owner = self.find_owner(param.parent);
+ if is_lowering_impl_trait_bounds {
+ let idx = self.opaque_lifetime_idx(param);
+ return (owner.preceding_params_len + (idx as u32), false);
+ }
+
let has_trait_self = matches!(owner.def, GenericDefId::TraitId(_));
- owner.preceding_params_len
- + u32::from(has_trait_self)
- + param.local_id.into_raw().into_u32()
+ match owner.params.lifetime_param_idx(&param.local_id) {
+ Some((idx, is_late_bound)) => {
+ let idx = if is_late_bound {
+ idx as u32
+ } else {
+ owner.preceding_params_len + u32::from(has_trait_self) + (idx as u32)
+ };
+ (idx, is_late_bound)
+ }
+ _ => unreachable!(),
+ }
}
#[deprecated = "don't use this; it's easy to expose an erroneous `Generics` with this"]
@@ -294,6 +361,18 @@ impl<'db> Generics<'db> {
});
Generics { chain }
}
+
+ fn opaque_lifetime_idx(&self, param: LifetimeParamId) -> usize {
+ self.find_owner(param.parent)
+ .iter_id(true)
+ .position(|id| {
+ let GenericParamId::LifetimeParamId(id) = id else {
+ return false;
+ };
+ param == id
+ })
+ .unwrap()
+ }
}
pub(crate) struct ProvenanceSplit {