/// Used for types that are `Copy` and which **do not care arena /// allocated data** (i.e., don't need to be folded). macro_rules! TrivialTypeTraversalImpls { ($($ty:ty,)+) => { $( impl $crate::fold::TypeFoldable for $ty { fn try_fold_with>( self, _: &mut F, ) -> ::std::result::Result { Ok(self) } #[inline] fn fold_with>( self, _: &mut F, ) -> Self { self } } impl $crate::visit::TypeVisitable for $ty { #[inline] fn visit_with>( &self, _: &mut F) -> ::std::ops::ControlFlow { ::std::ops::ControlFlow::Continue(()) } } )+ }; } macro_rules! EnumTypeTraversalImpl { (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { $($variants:tt)* } $(where $($wc:tt)*)*) => { impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s $(where $($wc)*)* { fn try_fold_with>( self, folder: &mut V, ) -> ::std::result::Result { EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } } }; (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path { $($variants:tt)* } $(where $($wc:tt)*)*) => { impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s $(where $($wc)*)* { fn visit_with>( &self, visitor: &mut V, ) -> ::std::ops::ControlFlow { EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) } } }; (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { Ok(match $this { $($output)* }) }; (@FoldVariants($this:expr, $folder:expr) input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( $variant ( $($variant_arg),* ) => { $variant ( $($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),* ) } $($output)* ) ) }; (@FoldVariants($this:expr, $folder:expr) input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( $variant { $($variant_arg),* } => { $variant { $($variant_arg: $crate::fold::TypeFoldable::fold_with( $variant_arg, $folder )?),* } } $($output)* ) ) }; (@FoldVariants($this:expr, $folder:expr) input( ($variant:path), $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @FoldVariants($this, $folder) input($($input)*) output( $variant => { $variant } $($output)* ) ) }; (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => { match $this { $($output)* } }; (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( $variant ( $($variant_arg),* ) => { $($crate::visit::TypeVisitable::visit_with( $variant_arg, $visitor )?;)* ::std::ops::ControlFlow::Continue(()) } $($output)* ) ) }; (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( $variant { $($variant_arg),* } => { $($crate::visit::TypeVisitable::visit_with( $variant_arg, $visitor )?;)* ::std::ops::ControlFlow::Continue(()) } $($output)* ) ) }; (@VisitVariants($this:expr, $visitor:expr) input( ($variant:path), $($input:tt)*) output( $($output:tt)*) ) => { EnumTypeTraversalImpl!( @VisitVariants($this, $visitor) input($($input)*) output( $variant => { ::std::ops::ControlFlow::Continue(()) } $($output)* ) ) }; }