Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-ty/src/builtin_derive.rs | 14 | ||||
| -rw-r--r-- | crates/hir-ty/src/display.rs | 18 | ||||
| -rw-r--r-- | crates/hir-ty/src/generics.rs | 368 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/callee.rs | 11 | ||||
| -rw-r--r-- | crates/hir-ty/src/lib.rs | 14 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 99 | ||||
| -rw-r--r-- | crates/hir-ty/src/lower/path.rs | 29 | ||||
| -rw-r--r-- | crates/hir-ty/src/mir/lower.rs | 5 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/generic_arg.rs | 82 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/generics.rs | 119 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/interner.rs | 16 | ||||
| -rw-r--r-- | crates/hir/src/lib.rs | 21 |
12 files changed, 367 insertions, 429 deletions
diff --git a/crates/hir-ty/src/builtin_derive.rs b/crates/hir-ty/src/builtin_derive.rs index 6a9b1671e7..f14e6e4e4d 100644 --- a/crates/hir-ty/src/builtin_derive.rs +++ b/crates/hir-ty/src/builtin_derive.rs @@ -12,7 +12,7 @@ use hir_def::{ use itertools::Itertools; use la_arena::ArenaMap; use rustc_type_ir::{ - AliasTyKind, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, + AliasTyKind, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, inherent::{GenericArgs as _, IntoKind}, }; @@ -53,7 +53,10 @@ fn trait_args(trait_: BuiltinDeriveImplTrait, self_ty: Ty<'_>) -> GenericArgs<'_ } } -pub(crate) fn generics_of<'db>(interner: DbInterner<'db>, id: BuiltinDeriveImplId) -> Generics { +pub(crate) fn generics_of<'db>( + interner: DbInterner<'db>, + id: BuiltinDeriveImplId, +) -> Generics<'db> { let db = interner.db; let loc = id.loc(db); match loc.trait_ { @@ -65,15 +68,14 @@ pub(crate) fn generics_of<'db>(interner: DbInterner<'db>, id: BuiltinDeriveImplI | BuiltinDeriveImplTrait::Ord | BuiltinDeriveImplTrait::PartialOrd | BuiltinDeriveImplTrait::Eq - | BuiltinDeriveImplTrait::PartialEq => interner.generics_of(loc.adt.into()), + | BuiltinDeriveImplTrait::PartialEq => Generics::from_generic_def(db, loc.adt.into()), BuiltinDeriveImplTrait::CoerceUnsized | BuiltinDeriveImplTrait::DispatchFromDyn => { - let mut generics = interner.generics_of(loc.adt.into()); let trait_id = loc .trait_ .get_id(interner.lang_items()) .expect("we don't pass the impl to the solver if we can't resolve the trait"); - generics.push_param(coerce_pointee_new_type_param(trait_id).into()); - generics + let additional_param = coerce_pointee_new_type_param(trait_id).into(); + Generics::from_generic_def_plus_one(db, loc.adt.into(), additional_param) } } } 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..32482ca94b 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,166 +64,237 @@ 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) fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { +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, +} + +fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { let container = match def { GenericDefId::FunctionId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(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-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs index 05955d060b..75df2b541e 100644 --- a/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/crates/hir-ty/src/next_solver/generic_arg.rs @@ -8,6 +8,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData, ptr::NonNull}; +use arrayvec::ArrayVec; use hir_def::{GenericDefId, GenericParamId}; use intern::InternedRef; use rustc_type_ir::{ @@ -18,7 +19,6 @@ use rustc_type_ir::{ relate::{Relate, VarianceDiagInfo}, walk::TypeWalker, }; -use smallvec::SmallVec; use crate::next_solver::{ ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, interned_slice, @@ -495,7 +495,47 @@ impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArgs { } } +trait GenericArgsBuilder<'db>: AsRef<[GenericArg<'db>]> { + fn push(&mut self, arg: GenericArg<'db>); +} + +impl<'db, const N: usize> GenericArgsBuilder<'db> for ArrayVec<GenericArg<'db>, N> { + fn push(&mut self, arg: GenericArg<'db>) { + self.push(arg); + } +} + +impl<'db> GenericArgsBuilder<'db> for Vec<GenericArg<'db>> { + fn push(&mut self, arg: GenericArg<'db>) { + self.push(arg); + } +} + impl<'db> GenericArgs<'db> { + #[inline(always)] + fn fill_builder<F>( + args: &mut impl GenericArgsBuilder<'db>, + defs: &Generics<'db>, + mut mk_kind: F, + ) where + F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, + { + defs.iter_id().enumerate().for_each(|(idx, param_id)| { + let new_arg = mk_kind(idx as u32, param_id, args.as_ref()); + args.push(new_arg); + }); + } + + #[cold] + fn fill_vec_builder<F>(defs: &Generics<'db>, count: usize, mk_kind: F) -> GenericArgs<'db> + where + F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, + { + let mut args = Vec::with_capacity(count); + Self::fill_builder(&mut args, defs, mk_kind); + GenericArgs::new_from_slice(&args) + } + /// Creates an `GenericArgs` for generic parameter definitions, /// by calling closures to obtain each kind. /// The closures get to observe the `GenericArgs` as they're @@ -504,7 +544,7 @@ impl<'db> GenericArgs<'db> { pub fn for_item<F>( interner: DbInterner<'db>, def_id: SolverDefId, - mut mk_kind: F, + mk_kind: F, ) -> GenericArgs<'db> where F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, @@ -513,12 +553,14 @@ impl<'db> GenericArgs<'db> { let count = defs.count(); if count == 0 { - return Default::default(); + GenericArgs::default() + } else if count <= 10 { + let mut args = ArrayVec::<_, 10>::new(); + Self::fill_builder(&mut args, &defs, mk_kind); + GenericArgs::new_from_slice(&args) + } else { + Self::fill_vec_builder(&defs, count, mk_kind) } - - let mut args = SmallVec::with_capacity(count); - Self::fill_item(&mut args, interner, defs, &mut mk_kind); - interner.mk_args(&args) } /// Creates an all-error `GenericArgs`. @@ -577,32 +619,6 @@ impl<'db> GenericArgs<'db> { }) } - fn fill_item<F>( - args: &mut SmallVec<[GenericArg<'db>; 8]>, - interner: DbInterner<'_>, - defs: Generics, - mk_kind: &mut F, - ) where - F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, - { - if let Some(def_id) = defs.parent { - let parent_defs = interner.generics_of(def_id.into()); - Self::fill_item(args, interner, parent_defs, mk_kind); - } - Self::fill_single(args, &defs, mk_kind); - } - - fn fill_single<F>(args: &mut SmallVec<[GenericArg<'db>; 8]>, defs: &Generics, mk_kind: &mut F) - where - F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, - { - args.reserve(defs.own_params.len()); - for param in &defs.own_params { - let kind = mk_kind(args.len() as u32, param.id, args); - args.push(kind); - } - } - pub fn types(self) -> impl Iterator<Item = Ty<'db>> { self.iter().filter_map(|it| it.as_type()) } diff --git a/crates/hir-ty/src/next_solver/generics.rs b/crates/hir-ty/src/next_solver/generics.rs index f31de21796..570e245922 100644 --- a/crates/hir-ty/src/next_solver/generics.rs +++ b/crates/hir-ty/src/next_solver/generics.rs @@ -1,117 +1,60 @@ //! Things related to generics in the next-trait-solver. -use hir_def::{ - ConstParamId, GenericDefId, GenericParamId, LifetimeParamId, TypeOrConstParamId, TypeParamId, - hir::generics::{GenericParams, TypeOrConstParamData}, -}; -use rustc_type_ir::inherent::GenericsOf; +use hir_def::{GenericDefId, GenericParamId}; -use crate::generics::parent_generic_def; +use crate::db::HirDatabase; use super::SolverDefId; use super::DbInterner; -pub(crate) fn generics(interner: DbInterner<'_>, def: SolverDefId) -> Generics { - let mk_lt = |parent, index, local_id| { - let id = GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id }); - GenericParamDef { index, id } - }; - let mk_ty = |parent, index, local_id, p: &TypeOrConstParamData| { - let id = TypeOrConstParamId { parent, local_id }; - let id = match p { - TypeOrConstParamData::TypeParamData(_) => { - GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)) - } - TypeOrConstParamData::ConstParamData(_) => { - GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)) - } - }; - GenericParamDef { index, id } - }; - let own_params_for_generic_params = |parent, params: &GenericParams| { - let mut result = Vec::with_capacity(params.len()); - let mut type_and_consts = params.iter_type_or_consts(); - let mut index = 0; - if let Some(self_param) = params.trait_self_param() { - result.push(mk_ty(parent, 0, self_param, ¶ms[self_param])); - type_and_consts.next(); - index += 1; - } - result.extend(params.iter_lt().map(|(local_id, _data)| { - let lt = mk_lt(parent, index, local_id); - index += 1; - lt - })); - result.extend(type_and_consts.map(|(local_id, data)| { - let ty = mk_ty(parent, index, local_id, data); - index += 1; - ty - })); - result - }; - +pub(crate) fn generics(interner: DbInterner<'_>, def: SolverDefId) -> Generics<'_> { let db = interner.db; - let (parent, own_params) = match (def.try_into(), def) { - (Ok(def), _) => ( - parent_generic_def(db, def), - own_params_for_generic_params(def, GenericParams::of(db, def)), - ), - (_, SolverDefId::InternedOpaqueTyId(id)) => { - match db.lookup_intern_impl_trait_id(id) { - crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => { - // The opaque type itself does not have generics - only the parent function - (Some(GenericDefId::FunctionId(function_id)), vec![]) - } - crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => { - (Some(type_alias_id.into()), Vec::new()) - } - } - } + let def = match (def.try_into(), def) { + (Ok(def), _) => def, + (_, SolverDefId::InternedOpaqueTyId(id)) => match db.lookup_intern_impl_trait_id(id) { + crate::ImplTraitId::ReturnTypeImplTrait(function_id, _) => function_id.into(), + crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => type_alias_id.into(), + }, (_, SolverDefId::BuiltinDeriveImplId(id)) => { return crate::builtin_derive::generics_of(interner, id); } _ => panic!("No generics for {def:?}"), }; - let parent_generics = parent.map(|def| Box::new(generics(interner, def.into()))); - Generics { - parent, - parent_count: parent_generics.map_or(0, |g| g.parent_count + g.own_params.len()), - own_params, - } + Generics::from_generic_def(db, def) } #[derive(Debug)] -pub struct Generics { - pub parent: Option<GenericDefId>, - pub parent_count: usize, - pub own_params: Vec<GenericParamDef>, +pub struct Generics<'db> { + generics: crate::generics::Generics<'db>, + /// This is used for builtin derives, specifically `CoercePointee`. + additional_param: Option<GenericParamId>, } -impl Generics { - pub(crate) fn push_param(&mut self, id: GenericParamId) { - let index = self.count() as u32; - self.own_params.push(GenericParamDef { index, id }); +impl<'db> Generics<'db> { + pub(crate) fn from_generic_def(db: &'db dyn HirDatabase, def: GenericDefId) -> Generics<'db> { + Generics { generics: crate::generics::generics(db, def), additional_param: None } } -} -#[derive(Debug)] -pub struct GenericParamDef { - index: u32, - pub(crate) id: GenericParamId, -} + pub(crate) fn from_generic_def_plus_one( + db: &'db dyn HirDatabase, + def: GenericDefId, + additional_param: GenericParamId, + ) -> Generics<'db> { + Generics { + generics: crate::generics::generics(db, def), + additional_param: Some(additional_param), + } + } -impl GenericParamDef { - /// Returns the index of the param on the self generics only - /// (i.e. not including parent generics) - pub fn index(&self) -> u32 { - self.index + pub(super) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> { + self.generics.iter_id().chain(self.additional_param) } } -impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics { +impl<'db> rustc_type_ir::inherent::GenericsOf<DbInterner<'db>> for Generics<'db> { fn count(&self) -> usize { - self.parent_count + self.own_params.len() + self.generics.len() + usize::from(self.additional_param.is_some()) } } diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs index fc83ebc625..bdbcaee4f6 100644 --- a/crates/hir-ty/src/next_solver/interner.rs +++ b/crates/hir-ty/src/next_solver/interner.rs @@ -967,7 +967,7 @@ impl<'db> Interner for DbInterner<'db> { type Clause = Clause<'db>; type Clauses = Clauses<'db>; - type GenericsOf = Generics; + type GenericsOf = Generics<'db>; type VariancesOf = VariancesOf<'db>; @@ -1124,12 +1124,14 @@ impl<'db> Interner for DbInterner<'db> { def_id: Self::DefId, args: Self::GenericArgs, ) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) { - let trait_def_id = self.parent(def_id); - let trait_generics = self.generics_of(trait_def_id); - let trait_args = - GenericArgs::new_from_slice(&args.as_slice()[0..trait_generics.own_params.len()]); - let alias_args = &args.as_slice()[trait_generics.own_params.len()..]; - (TraitRef::new_from_args(self, trait_def_id.try_into().unwrap(), trait_args), alias_args) + let SolverDefId::TraitId(trait_def_id) = self.parent(def_id) else { + panic!("expected a trait"); + }; + let trait_generics = crate::generics::generics(self.db, trait_def_id.into()); + let trait_generics_len = trait_generics.len(); + let trait_args = GenericArgs::new_from_slice(&args.as_slice()[..trait_generics_len]); + let alias_args = &args.as_slice()[trait_generics_len..]; + (TraitRef::new_from_args(self, trait_def_id.into(), trait_args), alias_args) } fn check_args_compatible(self, _def_id: Self::DefId, _args: Self::GenericArgs) -> bool { 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() }) } |