//! This module contains implementations of the `TypeFoldable` and `TypeVisitable` //! traits for various types in the Rust compiler. Most are written by hand, though //! we've recently added some macros and proc-macros to help with the tedium. use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; use rustc_data_structures::functor::IdFunctor; use rustc_index::vec::{Idx, IndexVec}; use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; /////////////////////////////////////////////////////////////////////////// // Atomic structs // // For things that don't carry any arena-allocated data (and are // copy...), just add them to this list. TrivialTypeTraversalImpls! { (), bool, usize, u16, u32, u64, String, crate::DebruijnIndex, } /////////////////////////////////////////////////////////////////////////// // Traversal implementations. impl, U: TypeFoldable> TypeFoldable for (T, U) { fn try_fold_with>(self, folder: &mut F) -> Result<(T, U), F::Error> { Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) } } impl, U: TypeVisitable> TypeVisitable for (T, U) { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.0.visit_with(visitor)?; self.1.visit_with(visitor) } } impl, B: TypeFoldable, C: TypeFoldable> TypeFoldable for (A, B, C) { fn try_fold_with>( self, folder: &mut F, ) -> Result<(A, B, C), F::Error> { Ok(( self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?, self.2.try_fold_with(folder)?, )) } } impl, B: TypeVisitable, C: TypeVisitable> TypeVisitable for (A, B, C) { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.0.visit_with(visitor)?; self.1.visit_with(visitor)?; self.2.visit_with(visitor) } } EnumTypeTraversalImpl! { impl TypeFoldable for Option { (Some)(a), (None), } where I: Interner, T: TypeFoldable } EnumTypeTraversalImpl! { impl TypeVisitable for Option { (Some)(a), (None), } where I: Interner, T: TypeVisitable } EnumTypeTraversalImpl! { impl TypeFoldable for Result { (Ok)(a), (Err)(a), } where I: Interner, T: TypeFoldable, E: TypeFoldable, } EnumTypeTraversalImpl! { impl TypeVisitable for Result { (Ok)(a), (Err)(a), } where I: Interner, T: TypeVisitable, E: TypeVisitable, } impl> TypeFoldable for Rc { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } impl> TypeVisitable for Rc { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } impl> TypeFoldable for Arc { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } impl> TypeVisitable for Arc { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } impl> TypeFoldable for Box { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) } } impl> TypeVisitable for Box { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } impl> TypeFoldable for Vec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|t| t.try_fold_with(folder)) } } impl> TypeVisitable for Vec { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } impl> TypeVisitable for &[T] { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } impl> TypeFoldable for Box<[T]> { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|t| t.try_fold_with(folder)) } } impl> TypeVisitable for Box<[T]> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|x| x.try_fold_with(folder)) } } impl, Ix: Idx> TypeVisitable for IndexVec { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } }