Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/display.rs18
-rw-r--r--crates/hir-ty/src/generics.rs366
-rw-r--r--crates/hir-ty/src/infer/callee.rs11
-rw-r--r--crates/hir-ty/src/lib.rs14
-rw-r--r--crates/hir-ty/src/lower.rs99
-rw-r--r--crates/hir-ty/src/lower/path.rs29
-rw-r--r--crates/hir-ty/src/mir/lower.rs5
-rw-r--r--crates/hir/src/lib.rs21
8 files changed, 269 insertions, 294 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 6bc55bc0e4..2df190bb7a 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -52,7 +52,7 @@ use stdx::never;
use crate::{
CallableDefId, FnAbi, ImplTraitId, MemoryMap, ParamEnvAndCrate, consteval,
db::HirDatabase,
- generics::generics,
+ generics::{ProvenanceSplit, generics},
layout::Layout,
lower::GenericPredicates,
mir::pad16,
@@ -743,7 +743,7 @@ impl<'db> HirDisplay<'db> for Const<'db> {
}
ConstKind::Infer(..) => write!(f, "#c#"),
ConstKind::Param(param) => {
- let generics = generics(f.db, param.id.parent());
+ let generics = GenericParams::of(f.db, param.id.parent());
let param_data = &generics[param.id.local_id()];
f.start_location_link_generic(param.id.into());
write!(f, "{}", param_data.name().unwrap().display(f.db, f.edition()))?;
@@ -1364,8 +1364,14 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
if !args.is_empty() {
let generic_def_id = GenericDefId::from_callable(db, def);
let generics = generics(db, generic_def_id);
- let (parent_len, self_param, type_, const_, impl_, lifetime) =
- generics.provenance_split();
+ let ProvenanceSplit {
+ parent_total: parent_len,
+ has_self_param: self_param,
+ non_impl_trait_type_params: type_,
+ const_params: const_,
+ impl_trait_type_params: impl_,
+ lifetimes: lifetime,
+ } = generics.provenance_split();
let parameters = args.as_slice();
debug_assert_eq!(
parameters.len(),
@@ -1631,7 +1637,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
TyKind::Param(param) => {
// FIXME: We should not access `param.id`, it should be removed, and we should know the
// parent from the formatted type.
- let generics = generics(db, param.id.parent());
+ let generics = GenericParams::of(db, param.id.parent());
let param_data = &generics[param.id.local_id()];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
@@ -2273,7 +2279,7 @@ impl<'db> HirDisplay<'db> for Region<'db> {
fn hir_fmt(&self, f: &mut HirFormatter<'_, 'db>) -> Result {
match self.kind() {
RegionKind::ReEarlyParam(param) => {
- let generics = generics(f.db, param.id.parent);
+ let generics = GenericParams::of(f.db, param.id.parent);
let param_data = &generics[param.id.local_id];
f.start_location_link_generic(param.id.into());
write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index b041281844..354acb1501 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -7,51 +7,56 @@
//! - Type or Const parameters
//!
//! where parent follows the same scheme.
-use std::ops;
+use arrayvec::ArrayVec;
use hir_def::{
ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup,
TypeOrConstParamId, TypeParamId,
db::DefDatabase,
expr_store::ExpressionStore,
hir::generics::{
- GenericParamDataRef, GenericParams, LifetimeParamData, LocalLifetimeParamId,
- LocalTypeOrConstParamId, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+ GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
+ TypeParamProvenance, WherePredicate,
},
};
-use itertools::chain;
-pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics<'_> {
- let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
+pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics<'_> {
+ let mut chain = ArrayVec::new();
+ let mut parent_params_len = 0;
+ if let Some(parent_def) = parent_generic_def(db, def) {
+ let (parent_params, parent_store) = GenericParams::with_store(db, parent_def);
+ chain.push(SingleGenerics {
+ def: parent_def,
+ params: parent_params,
+ store: parent_store,
+ preceding_params_len: 0,
+ });
+ parent_params_len = parent_params.len() as u32;
+ }
let (params, store) = GenericParams::with_store(db, def);
- let has_trait_self_param = params.trait_self_param().is_some();
- Generics { def, params, parent_generics, has_trait_self_param, store }
+ chain.push(SingleGenerics { def, params, store, preceding_params_len: parent_params_len });
+ Generics { chain }
+}
+
+#[derive(Debug)]
+pub(crate) struct Generics<'db> {
+ chain: ArrayVec<SingleGenerics<'db>, 2>,
}
-#[derive(Clone, Debug)]
-pub struct Generics<'db> {
+
+#[derive(Debug)]
+pub(crate) struct SingleGenerics<'db> {
def: GenericDefId,
+ preceding_params_len: u32,
params: &'db GenericParams,
store: &'db ExpressionStore,
- parent_generics: Option<Box<Generics<'db>>>,
- has_trait_self_param: bool,
}
-impl<T> ops::Index<T> for Generics<'_>
-where
- GenericParams: ops::Index<T>,
-{
- type Output = <GenericParams as ops::Index<T>>::Output;
- fn index(&self, index: T) -> &Self::Output {
- &self.params[index]
- }
-}
-
-impl<'db> Generics<'db> {
+impl<'db> SingleGenerics<'db> {
pub(crate) fn def(&self) -> GenericDefId {
self.def
}
- pub(crate) fn store(&self) -> &ExpressionStore {
+ pub(crate) fn store(&self) -> &'db ExpressionStore {
self.store
}
@@ -59,165 +64,236 @@ impl<'db> Generics<'db> {
self.params.where_predicates().iter()
}
- pub(crate) fn is_empty(&self) -> bool {
- self.params.is_empty() && self.parent_generics.as_ref().is_none_or(|g| g.params.is_empty())
+ pub(crate) fn has_no_params(&self) -> bool {
+ self.params.is_empty()
}
- pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
- self.iter_parent_id().chain(self.iter_self_id())
+ pub(crate) fn len_lifetimes(&self) -> usize {
+ self.params.len_lifetimes()
}
- pub(crate) fn iter_self_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
- self.iter_self().map(|(id, _)| id)
+ pub(crate) fn len(&self) -> usize {
+ self.params.len()
}
- pub(crate) fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
- self.iter_parent().map(|(id, _)| id)
+ fn iter_lifetimes(&self) -> impl Iterator<Item = (LifetimeParamId, &'db LifetimeParamData)> {
+ let parent = self.def;
+ self.params
+ .iter_lt()
+ .map(move |(local_id, data)| (LifetimeParamId { parent, local_id }, data))
}
- pub(crate) fn iter_self_type_or_consts(
+ pub(crate) fn iter_type_or_consts(
&self,
- ) -> impl DoubleEndedIterator<Item = (LocalTypeOrConstParamId, &TypeOrConstParamData)> + '_
- {
- let mut toc = self.params.iter_type_or_consts();
- let trait_self_param = self.has_trait_self_param.then(|| toc.next()).flatten();
- chain!(trait_self_param, toc)
+ ) -> impl Iterator<Item = (TypeOrConstParamId, &'db TypeOrConstParamData)> {
+ let parent = self.def;
+ self.params
+ .iter_type_or_consts()
+ .map(move |(local_id, data)| (TypeOrConstParamId { parent, local_id }, data))
}
- /// Iterate over the parent params followed by self params.
- pub(crate) fn iter(
+ fn iter_type_or_consts_as_generic(
+ &self,
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ self.iter_type_or_consts().map(|(id, data)| match data {
+ TypeOrConstParamData::TypeParamData(data) => (
+ GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+ GenericParamDataRef::TypeParamData(data),
+ ),
+ TypeOrConstParamData::ConstParamData(data) => (
+ GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+ GenericParamDataRef::ConstParamData(data),
+ ),
+ })
+ }
+
+ fn trait_self_and_others(
&self,
- ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
- self.iter_parent().chain(self.iter_self())
+ ) -> (
+ Option<(GenericParamId, GenericParamDataRef<'db>)>,
+ impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)>,
+ ) {
+ let mut iter = self.iter_type_or_consts_as_generic();
+ let trait_self = if let GenericDefId::TraitId(_) = self.def { iter.next() } else { None };
+ (trait_self, iter)
}
- pub(crate) fn iter_parents_with_store(
+ pub(crate) fn iter(&self) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ let lifetimes = self.iter_lifetimes().map(|(id, data)| {
+ (GenericParamId::LifetimeParamId(id), GenericParamDataRef::LifetimeParamData(data))
+ });
+ let (trait_self, type_and_consts) = self.trait_self_and_others();
+ trait_self.into_iter().chain(lifetimes).chain(type_and_consts)
+ }
+
+ pub(crate) fn iter_with_idx(
&self,
- ) -> impl Iterator<Item = ((GenericParamId, GenericParamDataRef<'_>), &ExpressionStore)> + '_
- {
- self.iter_parent()
- .zip(self.parent_generics().into_iter().flat_map(|it| std::iter::repeat(it.store)))
+ ) -> impl Iterator<Item = (u32, GenericParamId, GenericParamDataRef<'db>)> {
+ std::iter::zip(self.preceding_params_len.., self.iter())
+ .map(|(index, (id, data))| (index, id, data))
+ }
+
+ pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> {
+ self.iter().map(|(id, _)| id)
+ }
+}
+
+impl<'db> Generics<'db> {
+ pub(crate) fn iter_owners(&self) -> impl DoubleEndedIterator<Item = &SingleGenerics<'db>> {
+ self.chain.iter()
+ }
+
+ fn owner(&self) -> &SingleGenerics<'db> {
+ self.chain.last().expect("must have an owner params")
+ }
+
+ pub(crate) fn parent(&self) -> Option<&SingleGenerics<'db>> {
+ match &*self.chain {
+ [parent, _owner] => Some(parent),
+ _ => None,
+ }
+ }
+
+ pub(crate) fn has_no_params(&self) -> bool {
+ self.iter_owners().all(|owner| owner.has_no_params())
+ }
+
+ pub(crate) fn def(&self) -> GenericDefId {
+ self.owner().def
+ }
+
+ pub(crate) fn store(&self) -> &'db ExpressionStore {
+ self.owner().store
}
- /// Iterate over the params without parent params.
pub(crate) fn iter_self(
&self,
- ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
- let mut toc = self.params.iter_type_or_consts().map(from_toc_id(self));
- let trait_self_param = self.has_trait_self_param.then(|| toc.next()).flatten();
- chain!(trait_self_param, self.params.iter_lt().map(from_lt_id(self)), toc)
+ ) -> impl Iterator<Item = (GenericParamId, GenericParamDataRef<'db>)> {
+ self.owner().iter()
}
- /// Iterator over types and const params of parent.
- pub(crate) fn iter_parent(
+ pub(crate) fn iter_self_with_idx(
&self,
- ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'_>)> + '_ {
- self.parent_generics().into_iter().flat_map(|it| {
- let mut toc = it.params.iter_type_or_consts().map(from_toc_id(it));
- let trait_self_param = it.has_trait_self_param.then(|| toc.next()).flatten();
- chain!(trait_self_param, it.params.iter_lt().map(from_lt_id(it)), toc)
- })
+ ) -> impl Iterator<Item = (u32, GenericParamId, GenericParamDataRef<'db>)> {
+ self.owner().iter_with_idx()
+ }
+
+ pub(crate) fn iter_parent_id(&self) -> impl Iterator<Item = GenericParamId> {
+ self.parent().into_iter().flat_map(|parent| parent.iter_id())
+ }
+
+ pub(crate) fn iter_self_type_or_consts(
+ &self,
+ ) -> impl Iterator<Item = (TypeOrConstParamId, &'db TypeOrConstParamData)> {
+ self.owner().iter_type_or_consts()
+ }
+
+ /// 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_id(&self) -> impl Iterator<Item = GenericParamId> {
+ self.iter_owners().flat_map(|owner| owner.iter_id())
}
/// Returns total number of generic parameters in scope, including those from parent.
pub(crate) fn len(&self) -> usize {
- let parent = self.len_parent();
- let child = self.params.len();
- parent + child
+ match &*self.chain {
+ [parent, owner] => parent.len() + owner.len(),
+ [owner] => owner.len(),
+ _ => unreachable!(),
+ }
}
#[inline]
pub(crate) fn len_parent(&self) -> usize {
- self.parent_generics().map_or(0, Generics::len)
+ self.parent().map_or(0, SingleGenerics::len)
}
pub(crate) fn len_lifetimes_self(&self) -> usize {
- self.params.len_lifetimes()
+ self.owner().len_lifetimes()
}
- /// (parent total, self param, type params, const params, impl trait list, lifetimes)
- pub(crate) fn provenance_split(&self) -> (usize, bool, usize, usize, usize, usize) {
- let mut self_param = false;
- let mut type_params = 0;
- let mut impl_trait_params = 0;
+ pub(crate) fn provenance_split(&self) -> ProvenanceSplit {
+ let parent_total = self.len_parent();
+
+ let owner = self.owner();
+ let lifetimes = owner.params.len_lifetimes();
+
+ let mut has_self_param = false;
+ let mut non_impl_trait_type_params = 0;
+ let mut impl_trait_type_params = 0;
let mut const_params = 0;
- self.params.iter_type_or_consts().for_each(|(_, data)| match data {
+ owner.params.iter_type_or_consts().for_each(|(_, data)| match data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
- TypeParamProvenance::TypeParamList => type_params += 1,
- TypeParamProvenance::TraitSelf => self_param |= true,
- TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
+ TypeParamProvenance::TypeParamList => non_impl_trait_type_params += 1,
+ TypeParamProvenance::TraitSelf => has_self_param |= true,
+ TypeParamProvenance::ArgumentImplTrait => impl_trait_type_params += 1,
},
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
});
- let lifetime_params = self.params.len_lifetimes();
-
- 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(
- &self,
- param: TypeOrConstParamId,
- ) -> Option<(usize, TypeOrConstParamData)> {
- let idx = self.find_type_or_const_param(param)?;
- self.iter().nth(idx).and_then(|p| {
- let data = match p.1 {
- GenericParamDataRef::TypeParamData(p) => p.clone().into(),
- GenericParamDataRef::ConstParamData(p) => p.clone().into(),
- _ => return None,
- };
- Some((idx, data))
- })
- }
-
- pub fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
- self.find_type_or_const_param(param)
+ ProvenanceSplit {
+ parent_total,
+ has_self_param,
+ non_impl_trait_type_params,
+ const_params,
+ impl_trait_type_params,
+ lifetimes,
+ }
}
- fn find_type_or_const_param(&self, param: TypeOrConstParamId) -> Option<usize> {
- if param.parent == self.def {
- let idx = param.local_id.into_raw().into_u32() as usize;
- debug_assert!(
- idx < self.params.len_type_or_consts(),
- "idx: {} len: {}",
- idx,
- self.params.len_type_or_consts()
- );
- if self.params.trait_self_param() == Some(param.local_id) {
- return Some(idx);
+ fn find_owner(&self, def: GenericDefId) -> &SingleGenerics<'db> {
+ match &*self.chain {
+ [parent, owner] => {
+ if parent.def == def {
+ parent
+ } else {
+ debug_assert_eq!(def, owner.def);
+ owner
+ }
}
- Some(self.parent_generics().map_or(0, |g| g.len()) + self.params.len_lifetimes() + 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))
+ [owner] => {
+ debug_assert_eq!(def, owner.def);
+ owner
+ }
+ _ => unreachable!(),
}
}
- pub fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
- self.find_lifetime(lifetime)
- }
-
- fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<usize> {
- if lifetime.parent == self.def {
- let idx = lifetime.local_id.into_raw().into_u32() as usize;
- debug_assert!(idx <= self.params.len_lifetimes());
- Some(
- self.parent_generics().map_or(0, |g| g.len())
- + self.params.trait_self_param().is_some() as usize
- + idx,
- )
+ pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> u32 {
+ let owner = self.find_owner(param.parent);
+ let has_trait_self = matches!(owner.def, GenericDefId::TraitId(_));
+ if has_trait_self && param.local_id == GenericParams::SELF_PARAM_ID_IN_SELF {
+ owner.preceding_params_len
} else {
- debug_assert_eq!(self.parent_generics().map(|it| it.def), Some(lifetime.parent));
- self.parent_generics().and_then(|g| g.find_lifetime(lifetime))
+ owner.preceding_params_len
+ + owner.len_lifetimes() as u32
+ + param.local_id.into_raw().into_u32()
}
}
- pub(crate) fn parent_generics(&self) -> Option<&Generics<'db>> {
- self.parent_generics.as_deref()
+ pub(crate) fn lifetime_param_idx(&self, param: LifetimeParamId) -> u32 {
+ let owner = self.find_owner(param.parent);
+ 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()
}
}
+pub(crate) struct ProvenanceSplit {
+ pub(crate) parent_total: usize,
+ // The rest are about self.
+ pub(crate) has_self_param: bool,
+ pub(crate) non_impl_trait_type_params: usize,
+ pub(crate) const_params: usize,
+ pub(crate) impl_trait_type_params: usize,
+ pub(crate) lifetimes: usize,
+}
+
pub(crate) fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
let container = match def {
GenericDefId::FunctionId(it) => it.lookup(db).container,
@@ -235,35 +311,3 @@ pub(crate) fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Opt
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
}
}
-
-fn from_toc_id<'a>(
- it: &'a Generics<'a>,
-) -> impl Fn(
- (LocalTypeOrConstParamId, &'a TypeOrConstParamData),
-) -> (GenericParamId, GenericParamDataRef<'a>) {
- move |(local_id, p): (_, _)| {
- let id = TypeOrConstParamId { parent: it.def, local_id };
- match p {
- TypeOrConstParamData::TypeParamData(p) => (
- GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
- GenericParamDataRef::TypeParamData(p),
- ),
- TypeOrConstParamData::ConstParamData(p) => (
- GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
- GenericParamDataRef::ConstParamData(p),
- ),
- }
- }
-}
-
-fn from_lt_id<'a>(
- it: &'a Generics<'a>,
-) -> impl Fn((LocalLifetimeParamId, &'a LifetimeParamData)) -> (GenericParamId, GenericParamDataRef<'a>)
-{
- move |(local_id, p): (_, _)| {
- (
- GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
- GenericParamDataRef::LifetimeParamData(p),
- )
- }
-}
diff --git a/crates/hir-ty/src/infer/callee.rs b/crates/hir-ty/src/infer/callee.rs
index 237c9177f8..9fe566b8fe 100644
--- a/crates/hir-ty/src/infer/callee.rs
+++ b/crates/hir-ty/src/infer/callee.rs
@@ -5,9 +5,7 @@ use std::iter;
use intern::sym;
use tracing::debug;
-use hir_def::{
- CallableDefId, ConstParamId, TypeOrConstParamId, hir::ExprId, signatures::FunctionSignature,
-};
+use hir_def::{CallableDefId, ConstParamId, hir::ExprId, signatures::FunctionSignature};
use rustc_type_ir::{
InferTy, Interner,
inherent::{GenericArgs as _, IntoKind, Ty as _},
@@ -365,12 +363,7 @@ impl<'db> InferenceContext<'_, 'db> {
let const_params = generics
.iter_self_type_or_consts()
.filter(|(_, param_data)| param_data.const_param().is_some())
- .map(|(idx, _)| {
- ConstParamId::from_unchecked(TypeOrConstParamId {
- parent: func.into(),
- local_id: idx,
- })
- })
+ .map(|(id, _)| ConstParamId::from_unchecked(id))
.collect::<Vec<_>>();
let data = FunctionSignature::of(self.db, func);
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 4433dd6425..133447dff3 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -26,6 +26,7 @@ extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver;
extern crate self as hir_ty;
pub mod builtin_derive;
+mod generics;
mod infer;
mod inhabitedness;
mod lower;
@@ -44,7 +45,6 @@ pub mod diagnostics;
pub mod display;
pub mod drop;
pub mod dyn_compatibility;
-pub mod generics;
pub mod lang_items;
pub mod layout;
pub mod method_resolution;
@@ -61,8 +61,8 @@ mod tests;
use std::{hash::Hash, ops::ControlFlow};
use hir_def::{
- CallableDefId, ExpressionStoreOwnerId, GenericDefId, TypeAliasId, TypeOrConstParamId,
- TypeParamId,
+ CallableDefId, ExpressionStoreOwnerId, GenericDefId, LifetimeParamId, TypeAliasId,
+ TypeOrConstParamId, TypeParamId,
hir::{ExprId, ExprOrPatId, PatId},
resolver::TypeNs,
type_ref::{Rawness, TypeRefId},
@@ -210,10 +210,14 @@ impl<'db> MemoryMap<'db> {
}
/// Return an index of a parameter in the generic type parameter list by it's id.
-pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
+pub fn type_or_const_param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> u32 {
generics::generics(db, id.parent).type_or_const_param_idx(id)
}
+pub fn lifetime_param_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> u32 {
+ generics::generics(db, id.parent).lifetime_param_idx(id)
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum FnAbi {
Aapcs,
@@ -504,7 +508,7 @@ pub fn associated_type_shorthand_candidates(
};
let mut dedup_map = FxHashSet::default();
- let param_ty = Ty::new_param(interner, param, param_idx(db, param.into()).unwrap() as u32);
+ let param_ty = Ty::new_param(interner, param, type_or_const_param_idx(db, param.into()));
// We use the ParamEnv and not the predicates because the ParamEnv elaborates bounds.
let param_env = db.trait_environment(ExpressionStoreOwnerId::from(def));
for clause in param_env.clauses {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 7325cd0ef8..7066d40813 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -10,7 +10,6 @@ pub(crate) mod path;
use std::{cell::OnceCell, iter, mem};
-use arrayvec::ArrayVec;
use either::Either;
use hir_def::{
AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId,
@@ -55,7 +54,7 @@ use crate::{
FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
consteval::intern_const_ref,
db::{HirDatabase, InternedOpaqueTyId},
- generics::{Generics, generics},
+ generics::{Generics, SingleGenerics, generics},
next_solver::{
AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const,
DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FxIndexMap, GenericArg,
@@ -376,18 +375,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
Some(ValueNs::GenericParam(p)) => {
let args = self.generics();
- match args.type_or_const_param_idx(p.into()) {
- Some(idx) => Some(self.const_param(p, idx as u32)),
- None => {
- never!(
- "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
- args,
- path,
- p
- );
- None
- }
- }
+ let idx = args.type_or_const_param_idx(p.into());
+ Some(self.const_param(p, idx))
}
Some(ValueNs::ConstId(c)) => {
let args = GenericArgs::empty(self.interner);
@@ -465,9 +454,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
res = Some(TypeNs::GenericParam(type_param_id));
let generics = self.generics();
- let (idx, _data) =
- generics.type_or_const_param(type_param_id.into()).expect("matching generics");
- self.type_param(type_param_id, idx as u32)
+ let idx = generics.type_or_const_param_idx(type_param_id.into());
+ self.type_param(type_param_id, idx)
}
&TypeRef::RawPtr(inner, mutability) => {
let inner_ty = self.lower_ty(inner);
@@ -1094,11 +1082,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
Some(resolution) => match resolution {
LifetimeNs::Static => Region::new_static(self.interner),
LifetimeNs::LifetimeParam(id) => {
- let idx = match self.generics().lifetime_idx(id) {
- None => return Region::error(self.interner),
- Some(idx) => idx,
- };
- self.region_param(id, idx as u32)
+ let idx = self.generics().lifetime_param_idx(id);
+ self.region_param(id, idx)
}
},
None => Region::error(self.interner),
@@ -1785,11 +1770,7 @@ fn resolve_type_param_assoc_type_shorthand(
LifetimeElisionKind::AnonymousReportError,
);
let interner = ctx.interner;
- let param_ty = Ty::new_param(
- interner,
- param,
- generics.type_or_const_param_idx(param.into()).unwrap() as u32,
- );
+ let param_ty = Ty::new_param(interner, param, generics.type_or_const_param_idx(param.into()));
let mut this_trait_resolution = None;
if let GenericDefId::TraitId(containing_trait) = param.parent()
@@ -1805,9 +1786,7 @@ fn resolve_type_param_assoc_type_shorthand(
}
let mut supertraits_resolution = None;
- for maybe_parent_generics in
- std::iter::successors(Some(&generics), |generics| generics.parent_generics())
- {
+ for maybe_parent_generics in generics.iter_owners().rev() {
ctx.store = maybe_parent_generics.store();
for pred in maybe_parent_generics.where_predicates() {
let (WherePredicate::TypeBound { target, bound }
@@ -2211,16 +2190,13 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
let mut parent_predicates = Vec::new();
let mut own_assoc_ty_bounds = Vec::new();
let mut parent_assoc_ty_bounds = Vec::new();
- let all_generics =
- std::iter::successors(Some(&generics), |generics| generics.parent_generics())
- .collect::<ArrayVec<_, 2>>();
let own_implicit_trait_predicate = implicit_trait_predicate(interner, def);
- let parent_implicit_trait_predicate = if all_generics.len() > 1 {
- implicit_trait_predicate(interner, all_generics.last().unwrap().def())
+ let parent_implicit_trait_predicate = if let Some(parent) = generics.parent() {
+ implicit_trait_predicate(interner, parent.def())
} else {
None
};
- for &maybe_parent_generics in all_generics.iter().rev() {
+ for maybe_parent_generics in generics.iter_owners() {
// Collect only diagnostics from the child, not including parents.
ctx.diagnostics.clear();
@@ -2291,12 +2267,9 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
parent_predicates.push(clause);
}
};
- let parent_params_len = maybe_parent_generics.len_parent();
- maybe_parent_generics.iter_self().enumerate().for_each(
- |(param_idx, (param_id, param_data))| {
- add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data);
- },
- );
+ maybe_parent_generics.iter_with_idx().for_each(|(param_idx, param_id, param_data)| {
+ add_sized_clause(param_idx, param_id, param_data);
+ });
}
// We do not clear `ctx.unsized_types`, as the `?Sized` clause of a child (e.g. an associated type) can
@@ -2360,25 +2333,14 @@ fn generic_predicates(db: &dyn HirDatabase, def: GenericDefId) -> (GenericPredic
fn push_const_arg_has_type_predicates<'db>(
db: &'db dyn HirDatabase,
predicates: &mut Vec<Clause<'db>>,
- generics: &Generics<'db>,
+ single_generics: &SingleGenerics<'db>,
) {
let interner = DbInterner::new_no_crate(db);
- let const_params_offset = generics.len_parent() + generics.len_lifetimes_self();
- for (param_index, (param_idx, param_data)) in generics.iter_self_type_or_consts().enumerate() {
- if !matches!(param_data, TypeOrConstParamData::ConstParamData(_)) {
- continue;
- }
-
- let param_id = ConstParamId::from_unchecked(TypeOrConstParamId {
- parent: generics.def(),
- local_id: param_idx,
- });
+ for (param_index, param_id, _) in single_generics.iter_with_idx() {
+ let GenericParamId::ConstParamId(param_id) = param_id else { continue };
predicates.push(Clause(
ClauseKind::ConstArgHasType(
- Const::new_param(
- interner,
- ParamConst { id: param_id, index: (param_index + const_params_offset) as u32 },
- ),
+ Const::new_param(interner, ParamConst { id: param_id, index: param_index }),
db.const_param_ty(param_id),
)
.upcast(interner),
@@ -2408,7 +2370,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
def: GenericDefId,
) -> (GenericDefaults, Diagnostics) {
let generic_params = generics(db, def);
- if generic_params.is_empty() {
+ if generic_params.has_no_params() {
return (GenericDefaults(None), None);
}
let resolver = def.resolver(db);
@@ -2422,24 +2384,21 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
LifetimeElisionKind::AnonymousReportError,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
- let mut idx = 0;
let mut has_any_default = false;
- let mut defaults = generic_params
- .iter_parents_with_store()
- .map(|((_id, p), store)| {
- ctx.store = store;
+ let mut defaults = Vec::new();
+ if let Some(parent) = generic_params.parent() {
+ ctx.store = parent.store();
+ defaults.extend(parent.iter_with_idx().map(|(idx, _id, p)| {
let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
has_any_default |= has_default;
- idx += 1;
result
- })
- .collect::<Vec<_>>();
+ }));
+ }
ctx.diagnostics.clear(); // Don't include diagnostics from the parent.
ctx.store = store_for_self;
- defaults.extend(generic_params.iter_self().map(|(_id, p)| {
+ defaults.extend(generic_params.iter_self_with_idx().map(|(idx, _id, p)| {
let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
has_any_default |= has_default;
- idx += 1;
result
}));
let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
@@ -2452,10 +2411,10 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
fn handle_generic_param<'db>(
ctx: &mut TyLoweringContext<'db, '_>,
- idx: usize,
+ idx: u32,
p: GenericParamDataRef<'_>,
) -> (Option<StoredEarlyBinder<StoredGenericArg>>, bool) {
- ctx.lowering_param_default(idx as u32);
+ ctx.lowering_param_default(idx);
match p {
GenericParamDataRef::TypeParamData(p) => {
let ty = p.default.map(|ty| ctx.lower_ty(ty));
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index d6b9c375fc..c81e4647d8 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -22,7 +22,6 @@ use rustc_type_ir::{
inherent::{GenericArgs as _, Region as _, Ty as _},
};
use smallvec::SmallVec;
-use stdx::never;
use crate::{
GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
@@ -243,17 +242,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
TypeNs::GenericParam(param_id) => {
let generics = self.ctx.generics();
let idx = generics.type_or_const_param_idx(param_id.into());
- match idx {
- None => {
- never!("no matching generics");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- Some(idx) => {
- let (pidx, _param) = generics.iter().nth(idx).unwrap();
- assert_eq!(pidx, param_id.into());
- self.ctx.type_param(param_id, idx as u32)
- }
- }
+ self.ctx.type_param(param_id, idx)
}
TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
TypeNs::AdtSelfType(adt) => {
@@ -640,7 +629,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
);
- return unknown_subst(self.ctx.interner, def);
+ return GenericArgs::error_for_item(self.ctx.interner, def.into());
}
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
@@ -1332,17 +1321,3 @@ fn type_looks_like_const(
_ => None,
}
}
-
-fn unknown_subst<'db>(interner: DbInterner<'db>, def: impl Into<GenericDefId>) -> GenericArgs<'db> {
- let params = generics(interner.db(), def.into());
- GenericArgs::new_from_iter(
- interner,
- params.iter_id().map(|id| match id {
- GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
- GenericParamId::ConstParamId(id) => {
- unknown_const_as_generic(const_param_ty_query(interner.db(), id))
- }
- GenericParamId::LifetimeParamId(_) => Region::error(interner).into(),
- }),
- )
-}
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index d16e1b0d59..9c9cf0ac0b 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -567,10 +567,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
not_supported!("owner without generic def id");
};
let generics = generics(self.db, def);
- let index = generics
- .type_or_const_param_idx(p.into())
- .ok_or(MirLowerError::TypeError("fail to lower const generic param"))?
- as u32;
+ let index = generics.type_or_const_param_idx(p.into());
self.push_assignment(
current,
place,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9b36f8ab81..8488d6931e 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -4633,13 +4633,12 @@ impl GenericParam {
GenericParam::ConstParam(_) => return None,
GenericParam::LifetimeParam(it) => it.id.parent,
};
- let generics = hir_ty::generics::generics(db, parent);
let index = match self {
- GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?,
+ GenericParam::TypeParam(it) => hir_ty::type_or_const_param_idx(db, it.id.into()),
GenericParam::ConstParam(_) => return None,
- GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?,
+ GenericParam::LifetimeParam(it) => hir_ty::lifetime_param_idx(db, it.id),
};
- db.variances_of(parent).get(index).map(Into::into)
+ db.variances_of(parent).get(index as usize).map(Into::into)
}
}
@@ -4711,8 +4710,8 @@ impl TypeParam {
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
let resolver = self.id.parent().resolver(db);
let interner = DbInterner::new_no_crate(db);
- let index = hir_ty::param_idx(db, self.id.into()).unwrap();
- let ty = Ty::new_param(interner, self.id, index as u32);
+ let index = hir_ty::type_or_const_param_idx(db, self.id.into());
+ let ty = Ty::new_param(interner, self.id, index);
Type::new_with_resolver_inner(db, &resolver, ty)
}
@@ -4812,9 +4811,9 @@ impl ConstParam {
}
fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
- let local_idx = hir_ty::param_idx(db, id)?;
+ let local_idx = hir_ty::type_or_const_param_idx(db, id);
let defaults = db.generic_defaults(id.parent);
- let ty = defaults.get(local_idx)?;
+ let ty = defaults.get(local_idx as usize)?;
// FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
Some(ty.instantiate_identity())
}
@@ -7344,10 +7343,8 @@ fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId)
.filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
.map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id })
.any(|param| {
- let Some(param) = hir_ty::param_idx(db, param) else {
- return false;
- };
- defaults.get(param).is_none()
+ let param = hir_ty::type_or_const_param_idx(db, param);
+ defaults.get(param as usize).is_none()
})
}