diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs index a7ce69113f..b9f8082391 100644 --- a/crates/hir-def/src/generics.rs +++ b/crates/hir-def/src/generics.rs @@ -444,15 +444,18 @@ impl GenericParamsCollector { impl GenericParams { /// Number of Generic parameters (type_or_consts + lifetimes) + #[inline] pub fn len(&self) -> usize { self.type_or_consts.len() + self.lifetimes.len() } + #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Iterator of type_or_consts field + #[inline] pub fn iter_type_or_consts( &self, ) -> impl DoubleEndedIterator { @@ -460,6 +463,7 @@ impl GenericParams { } /// Iterator of lifetimes field + #[inline] pub fn iter_lt( &self, ) -> impl DoubleEndedIterator { @@ -608,7 +612,7 @@ impl GenericParams { }) } - pub fn find_trait_self_param(&self) -> Option { + pub fn trait_self_param(&self) -> Option { if self.type_or_consts.is_empty() { return None; } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 0dcd9129d6..f6fe0c618a 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -923,6 +923,7 @@ pub enum GenericDefId { ImplId(ImplId), // enum variants cannot have generics themselves, but their parent enums // can, and this makes some code easier to write + // FIXME: Try to remove this as that will reduce the amount of query slots generated per enum? EnumVariantId(EnumVariantId), // consts can have type parameters from their parents (i.e. associated consts of traits) ConstId(ConstId), diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index 21bed9d3da..ea10e6881e 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -50,13 +50,17 @@ impl Generics { } pub(crate) fn iter_id(&self) -> impl Iterator + '_ { - self.iter().map(|(id, _)| id) + self.iter_self_id().chain(self.iter_parent_id()) } pub(crate) fn iter_self_id(&self) -> impl Iterator + '_ { self.iter_self().map(|(id, _)| id) } + fn iter_parent_id(&self) -> impl Iterator + '_ { + self.iter_parent().map(|(id, _)| id) + } + pub(crate) fn iter_self_type_or_consts( &self, ) -> impl DoubleEndedIterator { @@ -81,7 +85,7 @@ impl Generics { } /// Iterator over types and const params of parent. - pub(crate) fn iter_parent( + fn iter_parent( &self, ) -> impl DoubleEndedIterator)> + '_ { self.parent_generics().into_iter().flat_map(|it| { @@ -108,7 +112,6 @@ impl Generics { let mut type_params = 0; let mut impl_trait_params = 0; let mut const_params = 0; - let mut lifetime_params = 0; self.params.iter_type_or_consts().for_each(|(_, data)| match data { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::TypeParamList => type_params += 1, @@ -118,52 +121,44 @@ impl Generics { TypeOrConstParamData::ConstParamData(_) => const_params += 1, }); - self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1); + let lifetime_params = self.params.iter_lt().count(); let parent_len = self.parent_generics().map_or(0, Generics::len); (parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params) } pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option { - Some(self.find_type_or_const_param(param)?.0) + self.find_type_or_const_param(param) } - fn find_type_or_const_param( - &self, - param: TypeOrConstParamId, - ) -> Option<(usize, &TypeOrConstParamData)> { + fn find_type_or_const_param(&self, param: TypeOrConstParamId) -> Option { if param.parent == self.def { let idx = param.local_id.into_raw().into_u32() as usize; - if idx >= self.params.type_or_consts.len() { - return None; - } - Some((idx, &self.params.type_or_consts[param.local_id])) + debug_assert!(idx <= self.params.type_or_consts.len()); + Some(idx) } else { + debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(param.parent)); self.parent_generics() .and_then(|g| g.find_type_or_const_param(param)) // Remember that parent parameters come after parameters for self. - .map(|(idx, data)| (self.len_self() + idx, data)) + .map(|idx| self.len_self() + idx) } } pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option { - Some(self.find_lifetime(lifetime)?.0) + self.find_lifetime(lifetime) } - fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> { + fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option { if lifetime.parent == self.def { let idx = lifetime.local_id.into_raw().into_u32() as usize; - if idx >= self.params.lifetimes.len() { - return None; - } - Some(( - self.params.type_or_consts.len() + idx, - &self.params.lifetimes[lifetime.local_id], - )) + debug_assert!(idx <= self.params.lifetimes.len()); + Some(self.params.type_or_consts.len() + idx) } else { + debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent)); self.parent_generics() .and_then(|g| g.find_lifetime(lifetime)) - .map(|(idx, data)| (self.len_self() + idx, data)) + .map(|idx| self.len_self() + idx) } } diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 658d407001..969999cdb8 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -155,7 +155,7 @@ impl Iterator for ClauseElaborator<'_> { fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) { let resolver = trait_.resolver(db); let generic_params = db.generic_params(trait_.into()); - let trait_self = generic_params.find_trait_self_param(); + let trait_self = generic_params.trait_self_param(); generic_params .where_predicates .iter() @@ -188,7 +188,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(Tra fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) { let generic_params = db.generic_params(trait_ref.hir_trait_id().into()); - let trait_self = match generic_params.find_trait_self_param() { + let trait_self = match generic_params.trait_self_param() { Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p }, None => return, };