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 | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs index 097bb85cbd..89a4d9202a 100644 --- a/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/crates/hir-ty/src/next_solver/generic_arg.rs @@ -1,7 +1,8 @@ //! Things related to generic args in the next-trait-solver. -use hir_def::GenericParamId; +use hir_def::{GenericDefId, GenericParamId}; use intern::{Interned, Symbol}; +use rustc_type_ir::inherent::Const as _; use rustc_type_ir::{ ClosureArgs, CollectAndApply, ConstVid, CoroutineArgs, CoroutineClosureArgs, FnSig, FnSigTys, GenericArgKind, IntTy, Interner, TermKind, TyKind, TyVid, TypeFoldable, TypeVisitable, @@ -216,6 +217,59 @@ impl<'db> GenericArgs<'db> { interner.mk_args(&args) } + /// Like `for_item`, but prefers the default of a parameter if it has any. + pub fn for_item_with_defaults<F>( + interner: DbInterner<'db>, + def_id: GenericDefId, + mut fallback: F, + ) -> GenericArgs<'db> + where + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, + { + let defaults = interner.db.generic_defaults_ns(def_id); + Self::for_item(interner, def_id.into(), |name, idx, id, prev| { + match defaults.get(idx as usize) { + Some(default) => default.instantiate(interner, prev), + None => fallback(name, idx, id, prev), + } + }) + } + + /// Like `for_item()`, but calls first uses the args from `first`. + pub fn fill_rest<F>( + interner: DbInterner<'db>, + def_id: SolverDefId, + first: impl IntoIterator<Item = GenericArg<'db>>, + mut fallback: F, + ) -> GenericArgs<'db> + where + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, + { + let mut iter = first.into_iter(); + Self::for_item(interner, def_id, |name, idx, id, prev| { + iter.next().unwrap_or_else(|| fallback(name, idx, id, prev)) + }) + } + + /// Appends default param values to `first` if needed. Params without default will call `fallback()`. + pub fn fill_with_defaults<F>( + interner: DbInterner<'db>, + def_id: GenericDefId, + first: impl IntoIterator<Item = GenericArg<'db>>, + mut fallback: F, + ) -> GenericArgs<'db> + where + F: FnMut(&Symbol, u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, + { + let defaults = interner.db.generic_defaults_ns(def_id); + Self::fill_rest(interner, def_id.into(), first, |name, idx, id, prev| { + defaults + .get(idx as usize) + .map(|default| default.instantiate(interner, prev)) + .unwrap_or_else(|| fallback(name, idx, id, prev)) + }) + } + fn fill_item<F>( args: &mut SmallVec<[GenericArg<'db>; 8]>, interner: DbInterner<'_>, @@ -271,6 +325,18 @@ impl<'db> GenericArgs<'db> { } } } + + pub fn types(self) -> impl Iterator<Item = Ty<'db>> { + self.iter().filter_map(|it| it.as_type()) + } + + pub fn consts(self) -> impl Iterator<Item = Const<'db>> { + self.iter().filter_map(|it| it.as_const()) + } + + pub fn regions(self) -> impl Iterator<Item = Region<'db>> { + self.iter().filter_map(|it| it.as_region()) + } } impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for GenericArgs<'db> { |