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/generics.rs | 2 | ||||
| -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 |
5 files changed, 98 insertions, 135 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/generics.rs b/crates/hir-ty/src/generics.rs index 354acb1501..32482ca94b 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -294,7 +294,7 @@ pub(crate) struct ProvenanceSplit { pub(crate) lifetimes: usize, } -pub(crate) fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { +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, 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 { |