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.rs | 129 |
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(¶m.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 { |