blob: f484cbe268450340bd2ac510bca39a85d61bdb41 [file] [log] [blame]
//! This module contains "rote and uninteresting" impls of `TypeFoldable` for
//! various types. In general, we prefer to derive `TypeFoldable`, but
//! sometimes that doesn't work for whatever reason.
//!
//! The more interesting impls of `TypeFoldable` remain in the `fold` module.
use super::in_place;
use crate::*;
use std::marker::PhantomData;
impl<T: TypeFoldable<I>, I: Interner> TypeFoldable<I> for Vec<T> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
in_place::fallible_map_vec(self, |e| e.try_fold_with(folder, outer_binder))
}
}
impl<T: TypeFoldable<I>, I: Interner> TypeFoldable<I> for Box<T> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
in_place::fallible_map_box(self, |e| e.try_fold_with(folder, outer_binder))
}
}
macro_rules! tuple_fold {
($($n:ident),*) => {
impl<$($n: TypeFoldable<I>,)* I: Interner> TypeFoldable<I> for ($($n,)*) {
fn try_fold_with<Error>(self, folder: &mut dyn FallibleTypeFolder<I, Error = Error>, outer_binder: DebruijnIndex) -> Result<Self, Error>
{
#[allow(non_snake_case)]
let ($($n),*) = self;
Ok(($($n.try_fold_with(folder, outer_binder)?,)*))
}
}
}
}
tuple_fold!(A, B);
tuple_fold!(A, B, C);
tuple_fold!(A, B, C, D);
tuple_fold!(A, B, C, D, E);
impl<T: TypeFoldable<I>, I: Interner> TypeFoldable<I> for Option<T> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
match self {
None => Ok(None),
Some(e) => Ok(Some(e.try_fold_with(folder, outer_binder)?)),
}
}
}
impl<I: Interner> TypeFoldable<I> for GenericArg<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let data = self
.data(interner)
.clone()
.try_fold_with(folder, outer_binder)?;
Ok(GenericArg::new(interner, data))
}
}
impl<I: Interner> TypeFoldable<I> for Substitution<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let folded = self
.iter(interner)
.cloned()
.map(|p| p.try_fold_with(folder, outer_binder));
Substitution::from_fallible(interner, folded)
}
}
impl<I: Interner> TypeFoldable<I> for Goals<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let folded = self
.iter(interner)
.cloned()
.map(|p| p.try_fold_with(folder, outer_binder));
Goals::from_fallible(interner, folded)
}
}
impl<I: Interner> TypeFoldable<I> for ProgramClauses<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let folded = self
.iter(interner)
.cloned()
.map(|p| p.try_fold_with(folder, outer_binder));
ProgramClauses::from_fallible(interner, folded)
}
}
impl<I: Interner> TypeFoldable<I> for QuantifiedWhereClauses<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let folded = self
.iter(interner)
.cloned()
.map(|p| p.try_fold_with(folder, outer_binder));
QuantifiedWhereClauses::from_fallible(interner, folded)
}
}
impl<I: Interner> TypeFoldable<I> for Constraints<I> {
fn try_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let interner = folder.interner();
let folded = self
.iter(interner)
.cloned()
.map(|p| p.try_fold_with(folder, outer_binder));
Constraints::from_fallible(interner, folded)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! copy_fold {
($t:ty) => {
impl<I: Interner> $crate::fold::TypeFoldable<I> for $t {
fn try_fold_with<E>(
self,
_folder: &mut dyn ($crate::fold::FallibleTypeFolder<I, Error = E>),
_outer_binder: DebruijnIndex,
) -> ::std::result::Result<Self, E> {
Ok(self)
}
}
};
}
copy_fold!(bool);
copy_fold!(usize);
copy_fold!(UniverseIndex);
copy_fold!(PlaceholderIndex);
copy_fold!(QuantifierKind);
copy_fold!(DebruijnIndex);
copy_fold!(());
copy_fold!(UintTy);
copy_fold!(IntTy);
copy_fold!(FloatTy);
copy_fold!(Scalar);
copy_fold!(ClausePriority);
copy_fold!(Mutability);
copy_fold!(Safety);
#[doc(hidden)]
#[macro_export]
macro_rules! id_fold {
($t:ident) => {
impl<I: Interner> $crate::fold::TypeFoldable<I> for $t<I> {
fn try_fold_with<E>(
self,
_folder: &mut dyn ($crate::fold::FallibleTypeFolder<I, Error = E>),
_outer_binder: DebruijnIndex,
) -> ::std::result::Result<Self, E> {
Ok(self)
}
}
};
}
id_fold!(ImplId);
id_fold!(AdtId);
id_fold!(TraitId);
id_fold!(AssocTypeId);
id_fold!(OpaqueTyId);
id_fold!(FnDefId);
id_fold!(ClosureId);
id_fold!(CoroutineId);
id_fold!(ForeignDefId);
impl<I: Interner> TypeSuperFoldable<I> for ProgramClauseData<I> {
fn try_super_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> ::std::result::Result<Self, E> {
Ok(ProgramClauseData(
self.0.try_fold_with(folder, outer_binder)?,
))
}
}
impl<I: Interner> TypeSuperFoldable<I> for ProgramClause<I> {
fn try_super_fold_with<E>(
self,
folder: &mut dyn FallibleTypeFolder<I, Error = E>,
outer_binder: DebruijnIndex,
) -> ::std::result::Result<Self, E> {
let clause = self.data(folder.interner()).clone();
Ok(clause
.try_super_fold_with(folder, outer_binder)?
.intern(folder.interner()))
}
}
impl<I: Interner> TypeFoldable<I> for PhantomData<I> {
fn try_fold_with<E>(
self,
_folder: &mut dyn FallibleTypeFolder<I, Error = E>,
_outer_binder: DebruijnIndex,
) -> ::std::result::Result<Self, E> {
Ok(PhantomData)
}
}