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.rs124
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())
}