Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/generic_arg.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/generic_arg.rs | 124 |
1 files changed, 89 insertions, 35 deletions
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs index 72cf2f9f07..51f070cd64 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, @@ -194,6 +194,25 @@ impl std::fmt::Debug for StoredGenericArg { } } +impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArg { + fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result { + self.as_ref().visit_with(visitor) + } +} + +impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArg { + fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self.as_ref().try_fold_with(folder)?.store()) + } + + fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { + self.as_ref().fold_with(folder).store() + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'db> { ptr: GenericArgImpl<'db>, @@ -457,7 +476,66 @@ impl_foldable_for_interned_slice!(GenericArgs); impl<'db> rustc_type_ir::inherent::GenericArg<DbInterner<'db>> for GenericArg<'db> {} +impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArgs { + fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result { + self.as_ref().visit_with(visitor) + } +} + +impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArgs { + fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self.as_ref().try_fold_with(folder)?.store()) + } + + fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { + self.as_ref().fold_with(folder).store() + } +} + +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 @@ -466,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>, @@ -475,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`. @@ -499,7 +579,7 @@ impl<'db> GenericArgs<'db> { { let defaults = interner.db.generic_defaults(def_id); Self::for_item(interner, def_id.into(), |idx, id, prev| match defaults.get(idx as usize) { - Some(default) => default.instantiate(interner, prev), + Some(default) => default.instantiate(interner, prev).skip_norm_wip(), None => fallback(idx, id, prev), }) } @@ -534,37 +614,11 @@ impl<'db> GenericArgs<'db> { Self::fill_rest(interner, def_id.into(), first, |idx, id, prev| { defaults .get(idx as usize) - .map(|default| default.instantiate(interner, prev)) + .map(|default| default.instantiate(interner, prev).skip_norm_wip()) .unwrap_or_else(|| fallback(idx, id, prev)) }) } - 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()) } |