From 23837c1901ab234ee6bc806744cd47d5a652cdfc Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 9 Feb 2018 10:34:23 -0500 Subject: [PATCH] improve TypeFoldable/Lift macros and make a bunch of stuff use them Improvements: - Use Clone not Copy for the "simple cases" - Separate TypeFoldable and Lift for the "simple cases" - Support generics type parameters - Support named fields in enum variants - etc --- src/librustc/infer/mod.rs | 13 - src/librustc/lib.rs | 1 + src/librustc/macros.rs | 300 +++++++++++++ src/librustc/mir/cache.rs | 4 + src/librustc/mir/mod.rs | 186 +++----- src/librustc/mir/tcx.rs | 24 +- src/librustc/traits/structural_impls.rs | 281 ++---------- src/librustc/ty/fold.rs | 3 + src/librustc/ty/relate.rs | 11 +- src/librustc/ty/structural_impls.rs | 541 ++++++------------------ 10 files changed, 551 insertions(+), 813 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5d44b2043e2..b94f1819c7d 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1647,19 +1647,6 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - TypeTrace { - cause: self.cause.fold_with(folder), - values: self.values.fold_with(folder) - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.cause.visit_with(visitor) || self.values.visit_with(visitor) - } -} - impl<'tcx> fmt::Debug for RegionObligation<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "RegionObligation(sub_region={:?}, sup_type={:?})", diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 56de2939ffa..2cf17603629 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -57,6 +57,7 @@ #![feature(inclusive_range)] #![feature(inclusive_range_syntax)] #![cfg_attr(windows, feature(libc))] +#![feature(macro_lifetime_matcher)] #![feature(macro_vis_matcher)] #![feature(match_default_bindings)] #![feature(never_type)] diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 9a394e52481..6013e3aef81 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -138,3 +138,303 @@ fn hash_stable(&self, ); } +/////////////////////////////////////////////////////////////////////////// +// Lift and TypeFoldable macros +// +// When possible, use one of these (relatively) convenient macros to write +// the impls for you. + +#[macro_export] +macro_rules! CloneLiftImpls { + (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + $( + impl<$tcx> $crate::ty::Lift<$tcx> for $ty { + type Lifted = Self; + fn lift_to_tcx<'a, 'gcx>(&self, _: $crate::ty::TyCtxt<'a, 'gcx, $tcx>) -> Option { + Some(Clone::clone(self)) + } + } + )+ + }; + + ($($ty:ty,)+) => { + CloneLiftImpls! { + for <'tcx> { + $($ty,)+ + } + } + }; +} + +/// Used for types that are `Copy` and which **do not care arena +/// allocated data** (i.e., don't need to be folded). +#[macro_export] +macro_rules! CloneTypeFoldableImpls { + (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + $( + impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty { + fn super_fold_with<'gcx: $tcx, F: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( + &self, + _: &mut F + ) -> $ty { + Clone::clone(self) + } + + fn super_visit_with>( + &self, + _: &mut F) + -> bool + { + false + } + } + )+ + }; + + ($($ty:ty,)+) => { + CloneTypeFoldableImpls! { + for <'tcx> { + $($ty,)+ + } + } + }; +} + +#[macro_export] +macro_rules! CloneTypeFoldableAndLiftImpls { + ($($t:tt)*) => { + CloneTypeFoldableImpls! { $($t)* } + CloneLiftImpls! { $($t)* } + } +} + +#[macro_export] +macro_rules! BraceStructLiftImpl { + (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path { + type Lifted = $lifted:ty; + $($field:ident),* $(,)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::Lift<$tcx> for $s + $(where $($wc)*)* + { + type Lifted = $lifted; + + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> { + $(let $field = tcx.lift(&self.$field)?;)* + Some(Self::Lifted { $($field),* }) + } + } + }; +} + +#[macro_export] +macro_rules! EnumLiftImpl { + (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path { + type Lifted = $lifted:ty; + $( + ($variant:path) ( $( $variant_arg:ident),* ) + ),* + $(,)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::Lift<$tcx> for $s + $(where $($wc)*)* + { + type Lifted = $lifted; + + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> { + match self { + $($variant ( $($variant_arg),* ) => { + Some($variant ( $(tcx.lift($variant_arg)?),* )) + })* + } + } + } + }; +} + +#[macro_export] +macro_rules! BraceStructTypeFoldableImpl { + (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { + $($field:ident),* $(,)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s + $(where $($wc)*)* + { + fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( + &self, + folder: &mut V, + ) -> Self { + let $s { $($field,)* } = self; + $s { $($field: $crate::ty::fold::TypeFoldable::fold_with($field, folder),)* } + } + + fn super_visit_with>( + &self, + visitor: &mut V, + ) -> bool { + let $s { $($field,)* } = self; + false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))* + } + } + }; +} + +#[macro_export] +macro_rules! TupleStructTypeFoldableImpl { + (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { + $($field:ident),* $(,)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s + $(where $($wc)*)* + { + fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( + &self, + folder: &mut V, + ) -> Self { + let $s($($field,)*)= self; + $s($($crate::ty::fold::TypeFoldable::fold_with($field, folder),)*) + } + + fn super_visit_with>( + &self, + visitor: &mut V, + ) -> bool { + let $s($($field,)*) = self; + false $(|| $crate::ty::fold::TypeFoldable::visit_with($field, visitor))* + } + } + }; +} + +#[macro_export] +macro_rules! EnumTypeFoldableImpl { + (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { + $($variants:tt)* + } $(where $($wc:tt)*)*) => { + impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s + $(where $($wc)*)* + { + fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( + &self, + folder: &mut V, + ) -> Self { + EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) + } + + fn super_visit_with>( + &self, + visitor: &mut V, + ) -> bool { + EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) + } + } + }; + + (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { + match $this { + $($output)* + } + }; + + (@FoldVariants($this:expr, $folder:expr) + input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) + output( $($output:tt)*) ) => { + EnumTypeFoldableImpl!( + @FoldVariants($this, $folder) + input($($input)*) + output( + $variant ( $($variant_arg),* ) => { + $variant ( + $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* + ) + } + $($output)* + ) + ) + }; + + (@FoldVariants($this:expr, $folder:expr) + input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*) + output( $($output:tt)*) ) => { + EnumTypeFoldableImpl!( + @FoldVariants($this, $folder) + input($($input)*) + output( + $variant { $($variant_arg),* } => { + $variant { + $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( + $variant_arg, $folder + )),* } + } + $($output)* + ) + ) + }; + + (@FoldVariants($this:expr, $folder:expr) + input( ($variant:path), $($input:tt)*) + output( $($output:tt)*) ) => { + EnumTypeFoldableImpl!( + @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)*) ) => { + EnumTypeFoldableImpl!( + @VisitVariants($this, $visitor) + input($($input)*) + output( + $variant ( $($variant_arg),* ) => { + false $(|| $crate::ty::fold::TypeFoldable::visit_with( + $variant_arg, $visitor + ))* + } + $($output)* + ) + ) + }; + + (@VisitVariants($this:expr, $visitor:expr) + input( ($variant:path) { $($variant_arg:ident),* $(,)* } , $($input:tt)*) + output( $($output:tt)*) ) => { + EnumTypeFoldableImpl!( + @VisitVariants($this, $visitor) + input($($input)*) + output( + $variant { $($variant_arg),* } => { + false $(|| $crate::ty::fold::TypeFoldable::visit_with( + $variant_arg, $visitor + ))* + } + $($output)* + ) + ) + }; + + (@VisitVariants($this:expr, $visitor:expr) + input( ($variant:path), $($input:tt)*) + output( $($output:tt)*) ) => { + EnumTypeFoldableImpl!( + @VisitVariants($this, $visitor) + input($($input)*) + output( + $variant => { false } + $($output)* + ) + ) + }; +} + diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 45cb70d0070..9b75c19a875 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -76,3 +76,7 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec> { result } + +CloneTypeFoldableAndLiftImpls! { + Cache, +} diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e39765699f9..939710ffd2b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2109,148 +2109,90 @@ pub enum ClosureOutlivesSubject<'tcx> { * TypeFoldable implementations for MIR types */ -impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - Mir { - basic_blocks: self.basic_blocks.fold_with(folder), - visibility_scopes: self.visibility_scopes.clone(), - visibility_scope_info: self.visibility_scope_info.clone(), - promoted: self.promoted.fold_with(folder), - yield_ty: self.yield_ty.fold_with(folder), - generator_drop: self.generator_drop.fold_with(folder), - generator_layout: self.generator_layout.fold_with(folder), - local_decls: self.local_decls.fold_with(folder), - arg_count: self.arg_count, - upvar_decls: self.upvar_decls.clone(), - spread_arg: self.spread_arg, - span: self.span, - cache: cache::Cache::new() - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.basic_blocks.visit_with(visitor) || - self.generator_drop.visit_with(visitor) || - self.generator_layout.visit_with(visitor) || - self.yield_ty.visit_with(visitor) || - self.promoted.visit_with(visitor) || - self.local_decls.visit_with(visitor) - } +CloneTypeFoldableAndLiftImpls! { + Mutability, + SourceInfo, + UpvarDecl, + ValidationOp, + VisibilityScopeData, + VisibilityScope, + VisibilityScopeInfo, } -impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - GeneratorLayout { - fields: self.fields.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.fields.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { + basic_blocks, + visibility_scopes, + visibility_scope_info, + promoted, + yield_ty, + generator_drop, + generator_layout, + local_decls, + arg_count, + upvar_decls, + spread_arg, + span, + cache, } } -impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - LocalDecl { - ty: self.ty.fold_with(folder), - ..self.clone() - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> { + fields } } -impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - BasicBlockData { - statements: self.statements.fold_with(folder), - terminator: self.terminator.fold_with(folder), - is_cleanup: self.is_cleanup - } +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> { + mutability, + is_user_variable, + internal, + ty, + name, + source_info, + syntactic_scope, } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.statements.visit_with(visitor) || self.terminator.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> { + statements, + terminator, + is_cleanup, } } -impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ValidationOperand { - place: self.place.fold_with(folder), - ty: self.ty.fold_with(folder), - re: self.re, - mutbl: self.mutbl, - } +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> { + place, ty, re, mutbl } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.place.visit_with(visitor) || self.ty.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { + source_info, kind } } -impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - use mir::StatementKind::*; - - let kind = match self.kind { - Assign(ref place, ref rval) => Assign(place.fold_with(folder), rval.fold_with(folder)), - SetDiscriminant { ref place, variant_index } => SetDiscriminant { - place: place.fold_with(folder), - variant_index, - }, - StorageLive(ref local) => StorageLive(local.fold_with(folder)), - StorageDead(ref local) => StorageDead(local.fold_with(folder)), - InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm { - asm: asm.clone(), - outputs: outputs.fold_with(folder), - inputs: inputs.fold_with(folder) - }, - - // Note for future: If we want to expose the region scopes - // during the fold, we need to either generalize EndRegion - // to carry `[ty::Region]`, or extend the `TypeFolder` - // trait with a `fn fold_scope`. - EndRegion(ref region_scope) => EndRegion(region_scope.clone()), - - Validate(ref op, ref places) => - Validate(op.clone(), - places.iter().map(|operand| operand.fold_with(folder)).collect()), - - Nop => Nop, - }; - Statement { - source_info: self.source_info, - kind, - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> { + (StatementKind::Assign)(a, b), + (StatementKind::SetDiscriminant) { place, variant_index }, + (StatementKind::StorageLive)(a), + (StatementKind::StorageDead)(a), + (StatementKind::InlineAsm) { asm, outputs, inputs }, + (StatementKind::Validate)(a, b), + (StatementKind::EndRegion)(a), + (StatementKind::Nop), } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use mir::StatementKind::*; - - match self.kind { - Assign(ref place, ref rval) => { place.visit_with(visitor) || rval.visit_with(visitor) } - SetDiscriminant { ref place, .. } => place.visit_with(visitor), - StorageLive(ref local) | - StorageDead(ref local) => local.visit_with(visitor), - InlineAsm { ref outputs, ref inputs, .. } => - outputs.visit_with(visitor) || inputs.visit_with(visitor), - - // Note for future: If we want to expose the region scopes - // during the visit, we need to either generalize EndRegion - // to carry `[ty::Region]`, or extend the `TypeVisitor` - // trait with a `fn visit_scope`. - EndRegion(ref _scope) => false, - - Validate(ref _op, ref places) => - places.iter().any(|ty_and_place| ty_and_place.visit_with(visitor)), - - Nop => false, - } - } +EnumTypeFoldableImpl! { + impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate { + (ClearCrossCrate::Clear), + (ClearCrossCrate::Set)(a), + } where T: TypeFoldable<'tcx> } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 7d232ac20bf..d779ccd1736 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -16,7 +16,6 @@ use mir::*; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, Ty, TyCtxt}; -use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use hir; use ty::util::IntTypeExt; @@ -100,25 +99,10 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, } } -impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - PlaceTy::Ty { ty } => PlaceTy::Ty { ty: ty.fold_with(folder) }, - PlaceTy::Downcast { adt_def, substs, variant_index } => { - PlaceTy::Downcast { - adt_def, - substs: substs.fold_with(folder), - variant_index, - } - } - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - PlaceTy::Ty { ty } => ty.visit_with(visitor), - PlaceTy::Downcast { substs, .. } => substs.visit_with(visitor) - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> { + (PlaceTy::Ty) { ty }, + (PlaceTy::Downcast) { adt_def, substs, variant_index }, } } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 9dd5aaee7b7..99adc1fc873 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -363,258 +363,67 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableImplData { - impl_def_id: self.impl_def_id, - substs: self.substs.fold_with(folder), - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.substs.visit_with(visitor) || self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> { + impl_def_id, substs, nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableGeneratorData<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableGeneratorData { - closure_def_id: self.closure_def_id, - substs: self.substs.fold_with(folder), - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.substs.visit_with(visitor) || self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableGeneratorData<'tcx, N> { + closure_def_id, substs, nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableClosureData { - closure_def_id: self.closure_def_id, - substs: self.substs.fold_with(folder), - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.substs.visit_with(visitor) || self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> { + closure_def_id, substs, nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableAutoImplData { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableAutoImplData { - trait_def_id: self.trait_def_id, - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableAutoImplData { + trait_def_id, nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableBuiltinData { - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableBuiltinData { + nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableObjectData { - upcast_trait_ref: self.upcast_trait_ref.fold_with(folder), - vtable_base: self.vtable_base, - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.upcast_trait_ref.visit_with(visitor) || self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> { + upcast_trait_ref, vtable_base, nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::VtableFnPointerData { - fn_ty: self.fn_ty.fold_with(folder), - nested: self.nested.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.fn_ty.visit_with(visitor) || self.nested.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> { + fn_ty, + nested + } where N: TypeFoldable<'tcx> } -impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), - traits::VtableAutoImpl(ref t) => traits::VtableAutoImpl(t.fold_with(folder)), - traits::VtableGenerator(ref d) => { - traits::VtableGenerator(d.fold_with(folder)) - } - traits::VtableClosure(ref d) => { - traits::VtableClosure(d.fold_with(folder)) - } - traits::VtableFnPointer(ref d) => { - traits::VtableFnPointer(d.fold_with(folder)) - } - traits::VtableParam(ref n) => traits::VtableParam(n.fold_with(folder)), - traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)), - traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - traits::VtableImpl(ref v) => v.visit_with(visitor), - traits::VtableAutoImpl(ref t) => t.visit_with(visitor), - traits::VtableGenerator(ref d) => d.visit_with(visitor), - traits::VtableClosure(ref d) => d.visit_with(visitor), - traits::VtableFnPointer(ref d) => d.visit_with(visitor), - traits::VtableParam(ref n) => n.visit_with(visitor), - traits::VtableBuiltin(ref d) => d.visit_with(visitor), - traits::VtableObject(ref d) => d.visit_with(visitor), - } - } +EnumTypeFoldableImpl! { + impl<'tcx, N> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> { + (traits::VtableImpl)(a), + (traits::VtableAutoImpl)(a), + (traits::VtableGenerator)(a), + (traits::VtableClosure)(a), + (traits::VtableFnPointer)(a), + (traits::VtableParam)(a), + (traits::VtableBuiltin)(a), + (traits::VtableObject)(a), + } where N: TypeFoldable<'tcx> } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - Normalized { - value: self.value.fold_with(folder), - obligations: self.obligations.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.value.visit_with(visitor) || self.obligations.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, T> TypeFoldable<'tcx> for Normalized<'tcx, T> { + value, + obligations + } where T: TypeFoldable<'tcx> } -impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - super::ExprAssignable | - super::MatchExpressionArm { arm_span: _, source: _ } | - super::IfExpression | - super::IfExpressionWithNoElse | - super::MainFunctionType | - super::StartFunctionType | - super::IntrinsicType | - super::MethodReceiver | - super::MiscObligation | - super::SliceOrArrayElem | - super::TupleElem | - super::ItemObligation(_) | - super::AssignmentLhsSized | - super::TupleInitializerSized | - super::StructInitializerSized | - super::VariableType(_) | - super::ReturnType(_) | - super::SizedReturnType | - super::SizedYieldType | - super::ReturnNoExpression | - super::RepeatVec | - super::FieldSized(_) | - super::ConstSized | - super::SharedStatic | - super::BlockTailExpression(_) | - super::CompareImplMethodObligation { .. } => self.clone(), - - super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)), - super::ReferenceOutlivesReferent(ty) => { - super::ReferenceOutlivesReferent(ty.fold_with(folder)) - } - super::ObjectTypeBound(ty, r) => { - super::ObjectTypeBound(ty.fold_with(folder), r.fold_with(folder)) - } - super::ObjectCastObligation(ty) => { - super::ObjectCastObligation(ty.fold_with(folder)) - } - super::BuiltinDerivedObligation(ref cause) => { - super::BuiltinDerivedObligation(cause.fold_with(folder)) - } - super::ImplDerivedObligation(ref cause) => { - super::ImplDerivedObligation(cause.fold_with(folder)) - } - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - super::ExprAssignable | - super::MatchExpressionArm { arm_span: _, source: _ } | - super::IfExpression | - super::IfExpressionWithNoElse | - super::MainFunctionType | - super::StartFunctionType | - super::IntrinsicType | - super::MethodReceiver | - super::MiscObligation | - super::SliceOrArrayElem | - super::TupleElem | - super::ItemObligation(_) | - super::AssignmentLhsSized | - super::TupleInitializerSized | - super::StructInitializerSized | - super::VariableType(_) | - super::ReturnType(_) | - super::SizedReturnType | - super::SizedYieldType | - super::ReturnNoExpression | - super::RepeatVec | - super::FieldSized(_) | - super::ConstSized | - super::SharedStatic | - super::BlockTailExpression(_) | - super::CompareImplMethodObligation { .. } => false, - - super::ProjectionWf(proj) => proj.visit_with(visitor), - super::ReferenceOutlivesReferent(ty) => ty.visit_with(visitor), - super::ObjectTypeBound(ty, r) => ty.visit_with(visitor) || r.visit_with(visitor), - super::ObjectCastObligation(ty) => ty.visit_with(visitor), - super::BuiltinDerivedObligation(ref cause) => cause.visit_with(visitor), - super::ImplDerivedObligation(ref cause) => cause.visit_with(visitor) - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for traits::DerivedObligationCause<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::DerivedObligationCause { - parent_trait_ref: self.parent_trait_ref.fold_with(folder), - parent_code: self.parent_code.fold_with(folder) - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.parent_trait_ref.visit_with(visitor) || self.parent_code.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCause<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - traits::ObligationCause { - span: self.span, - body_id: self.body_id, - code: self.code.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.code.visit_with(visitor) - } -} diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 4cc7406af72..8071cd0c639 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -49,6 +49,9 @@ /// The TypeFoldable trait is implemented for every type that can be folded. /// Basically, every type that has a corresponding method in TypeFolder. +/// +/// To implement this conveniently, use the +/// `BraceStructTypeFoldableImpl` etc macros found in `macros.rs`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self; fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index bae1ce31a5e..0ca2769aa17 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -18,7 +18,6 @@ use traits::Reveal; use ty::subst::{UnpackedKind, Substs}; use ty::{self, Ty, TyCtxt, TypeFoldable}; -use ty::fold::{TypeVisitor, TypeFolder}; use ty::error::{ExpectedFound, TypeError}; use mir::interpret::{GlobalId, Value, PrimVal}; use util::common::ErrorReported; @@ -326,13 +325,9 @@ fn relate<'a, 'gcx, R>(relation: &mut R, #[derive(Debug, Clone)] struct GeneratorWitness<'tcx>(&'tcx ty::Slice>); -impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - GeneratorWitness(self.0.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) +TupleStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> { + a } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 78fccaa1131..0627bcdfb0e 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -28,153 +28,37 @@ // For things that don't carry any arena-allocated data (and are // copy...), just add them to this list. -macro_rules! CopyImpls { - ($($ty:ty,)+) => { - $( - impl<'tcx> Lift<'tcx> for $ty { - type Lifted = Self; - fn lift_to_tcx<'a, 'gcx>(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Option { - Some(*self) - } - } - - impl<'tcx> TypeFoldable<'tcx> for $ty { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _: &mut F) -> $ty { - *self - } - - fn super_visit_with>(&self, _: &mut F) -> bool { - false - } - } - )+ - } -} - -CopyImpls! { +CloneTypeFoldableAndLiftImpls! { (), + bool, + usize, + u64, + ::middle::region::Scope, + ::syntax::ast::FloatTy, + ::syntax::ast::NodeId, + ::syntax_pos::symbol::Symbol, + ::hir::def::Def, + ::hir::def_id::DefId, + ::hir::InlineAsm, + ::hir::MatchSource, + ::hir::Mutability, ::hir::Unsafety, ::syntax::abi::Abi, - ::hir::def_id::DefId, ::mir::Local, ::mir::Promoted, ::traits::Reveal, + ::ty::adjustment::AutoBorrowMutability, + ::ty::AdtKind, + // Including `BoundRegion` is a *bit* dubious, but direct + // references to bound region appear in `ty::Error`, and aren't + // really meant to be folded. In general, we can only fold a fully + // general `Region`. + ::ty::BoundRegion, + ::ty::ClosureKind, + ::ty::IntVarValue, ::syntax_pos::Span, } -/////////////////////////////////////////////////////////////////////////// -// Macros -// -// When possible, use one of these (relatively) convenient macros to write -// the impls for you. - -#[macro_export] -macro_rules! BraceStructLiftImpl { - (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path { - type Lifted = $lifted:ty; - $($field:ident),* $(,)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::ty::Lift<$tcx> for $s - $(where $($wc)*)* - { - type Lifted = $lifted; - - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> { - $(let $field = tcx.lift(&self.$field)?;)* - Some(Self::Lifted { $($field),* }) - } - } - }; -} - -#[macro_export] -macro_rules! EnumLiftImpl { - (impl<$($p:tt),*> Lift<$tcx:tt> for $s:path { - type Lifted = $lifted:ty; - $( - ($variant:path) ( $( $variant_arg:ident),* ) - ),* - $(,)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::ty::Lift<$tcx> for $s - $(where $($wc)*)* - { - type Lifted = $lifted; - - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<$lifted> { - match self { - $($variant ( $($variant_arg),* ) => { - Some($variant ( $(tcx.lift($variant_arg)?),* )) - })* - } - } - } - }; -} - -#[macro_export] -macro_rules! BraceStructTypeFoldableImpl { - (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { - $($field:ident),* $(,)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s - $(where $($wc)*)* - { - fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( - &self, - folder: &mut V, - ) -> Self { - let $s { $($field,)* } = self; - $s { $($field: $field.fold_with(folder),)* } - } - - fn super_visit_with>( - &self, - visitor: &mut V, - ) -> bool { - let $s { $($field,)* } = self; - false $(|| $field.visit_with(visitor))* - } - } - }; -} - -#[macro_export] -macro_rules! EnumTypeFoldableImpl { - (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { - $( - ($variant:path) ( $( $variant_arg:ident),* ) - ),* - $(,)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s - $(where $($wc)*)* - { - fn super_fold_with<'gcx: $tcx, V: $crate::ty::fold::TypeFolder<'gcx, $tcx>>( - &self, - folder: &mut V, - ) -> Self { - match self { - $($variant ( $($variant_arg),* ) => { - $variant ( $($variant_arg.fold_with(folder)),* ) - })* - } - } - - fn super_visit_with>( - &self, - visitor: &mut V, - ) -> bool { - match self { - $($variant ( $($variant_arg),* ) => { - false $(|| $variant_arg.visit_with(visitor))* - })* - } - } - } - }; -} - /////////////////////////////////////////////////////////////////////////// // Lift implementations @@ -776,6 +660,17 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::GlobalId<'a> { // can easily refactor the folding into the TypeFolder trait as // needed. +/// AdtDefs are basically the same as a DefId. +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _visitor: &mut V) -> bool { + false + } +} + impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) { (self.0.fold_with(folder), self.1.fold_with(folder)) @@ -786,14 +681,11 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Option { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.as_ref().map(|t| t.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } +EnumTypeFoldableImpl! { + impl<'tcx, T> TypeFoldable<'tcx> for Option { + (Some)(a), + (None), + } where T: TypeFoldable<'tcx> } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { @@ -881,22 +773,11 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - use ty::ExistentialPredicate::*; - match *self { - Trait(ref tr) => Trait(tr.fold_with(folder)), - Projection(ref p) => Projection(p.fold_with(folder)), - AutoTrait(did) => AutoTrait(did), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - ty::ExistentialPredicate::Trait(ref tr) => tr.visit_with(visitor), - ty::ExistentialPredicate::Projection(ref p) => p.visit_with(visitor), - ty::ExistentialPredicate::AutoTrait(_) => false, - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> { + (ty::ExistentialPredicate::Trait)(a), + (ty::ExistentialPredicate::Projection)(a), + (ty::ExistentialPredicate::AutoTrait)(a), } } @@ -1049,13 +930,9 @@ fn visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TypeAndMut { ty: self.ty.fold_with(folder), mutbl: self.mutbl } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> { + ty, mutbl } } @@ -1065,20 +942,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::GenSig<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let inputs_and_output = self.inputs_and_output.fold_with(folder); - ty::FnSig { - inputs_and_output: folder.tcx().intern_type_list(&inputs_and_output), - variadic: self.variadic, - unsafety: self.unsafety, - abi: self.abi, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.inputs().iter().any(|i| i.visit_with(visitor)) || - self.output().visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> { + inputs_and_output, variadic, unsafety, abi } } @@ -1117,28 +983,15 @@ fn visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::ClosureSubsts { - substs: self.substs.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.substs.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> { + substs, } } -impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorInterior<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::GeneratorInterior { - witness: self.witness.fold_with(folder), - movable: self.movable, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.witness.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorInterior<'tcx> { + witness, movable, } } @@ -1149,74 +1002,32 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - ty::adjustment::Adjust::NeverToAny | - ty::adjustment::Adjust::ReifyFnPointer | - ty::adjustment::Adjust::UnsafeFnPointer | - ty::adjustment::Adjust::ClosureFnPointer | - ty::adjustment::Adjust::MutToConstPointer | - ty::adjustment::Adjust::Unsize => self.clone(), - ty::adjustment::Adjust::Deref(ref overloaded) => { - ty::adjustment::Adjust::Deref(overloaded.fold_with(folder)) - } - ty::adjustment::Adjust::Borrow(ref autoref) => { - ty::adjustment::Adjust::Borrow(autoref.fold_with(folder)) - } - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - ty::adjustment::Adjust::NeverToAny | - ty::adjustment::Adjust::ReifyFnPointer | - ty::adjustment::Adjust::UnsafeFnPointer | - ty::adjustment::Adjust::ClosureFnPointer | - ty::adjustment::Adjust::MutToConstPointer | - ty::adjustment::Adjust::Unsize => false, - ty::adjustment::Adjust::Deref(ref overloaded) => { - overloaded.visit_with(visitor) - } - ty::adjustment::Adjust::Borrow(ref autoref) => { - autoref.visit_with(visitor) - } - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> { + (ty::adjustment::Adjust::NeverToAny), + (ty::adjustment::Adjust::ReifyFnPointer), + (ty::adjustment::Adjust::UnsafeFnPointer), + (ty::adjustment::Adjust::ClosureFnPointer), + (ty::adjustment::Adjust::MutToConstPointer), + (ty::adjustment::Adjust::Unsize), + (ty::adjustment::Adjust::Deref)(a), + (ty::adjustment::Adjust::Borrow)(a), } } -impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::adjustment::OverloadedDeref { - region: self.region.fold_with(folder), - mutbl: self.mutbl, - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.region.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> { + region, mutbl, } } -impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - ty::adjustment::AutoBorrow::Ref(ref r, m) => { - ty::adjustment::AutoBorrow::Ref(r.fold_with(folder), m) - } - ty::adjustment::AutoBorrow::RawPtr(m) => ty::adjustment::AutoBorrow::RawPtr(m) - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - ty::adjustment::AutoBorrow::Ref(r, _m) => r.visit_with(visitor), - ty::adjustment::AutoBorrow::RawPtr(_m) => false, - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { + (ty::adjustment::AutoBorrow::Ref)(a, b), + (ty::adjustment::AutoBorrow::RawPtr)(m), } } - BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { parent, predicates @@ -1234,43 +1045,17 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - match *self { - ty::Predicate::Trait(ref a) => - ty::Predicate::Trait(a.fold_with(folder)), - ty::Predicate::Subtype(ref binder) => - ty::Predicate::Subtype(binder.fold_with(folder)), - ty::Predicate::RegionOutlives(ref binder) => - ty::Predicate::RegionOutlives(binder.fold_with(folder)), - ty::Predicate::TypeOutlives(ref binder) => - ty::Predicate::TypeOutlives(binder.fold_with(folder)), - ty::Predicate::Projection(ref binder) => - ty::Predicate::Projection(binder.fold_with(folder)), - ty::Predicate::WellFormed(data) => - ty::Predicate::WellFormed(data.fold_with(folder)), - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => - ty::Predicate::ClosureKind(closure_def_id, closure_substs.fold_with(folder), kind), - ty::Predicate::ObjectSafe(trait_def_id) => - ty::Predicate::ObjectSafe(trait_def_id), - ty::Predicate::ConstEvaluatable(def_id, substs) => - ty::Predicate::ConstEvaluatable(def_id, substs.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - ty::Predicate::Trait(ref a) => a.visit_with(visitor), - ty::Predicate::Subtype(ref binder) => binder.visit_with(visitor), - ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor), - ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor), - ty::Predicate::Projection(ref binder) => binder.visit_with(visitor), - ty::Predicate::WellFormed(data) => data.visit_with(visitor), - ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => - closure_substs.visit_with(visitor), - ty::Predicate::ObjectSafe(_trait_def_id) => false, - ty::Predicate::ConstEvaluatable(_def_id, substs) => substs.visit_with(visitor), - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { + (ty::Predicate::Trait)(a), + (ty::Predicate::Subtype)(a), + (ty::Predicate::RegionOutlives)(a), + (ty::Predicate::TypeOutlives)(a), + (ty::Predicate::Projection)(a), + (ty::Predicate::WellFormed)(a), + (ty::Predicate::ClosureKind)(a, b, c), + (ty::Predicate::ObjectSafe)(a), + (ty::Predicate::ConstEvaluatable)(a, b), } } @@ -1298,71 +1083,40 @@ impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::SubtypePredicate { - a_is_expected: self.a_is_expected, - a: self.a.fold_with(folder), - b: self.b.fold_with(folder) - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.a.visit_with(visitor) || self.b.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, T> TypeFoldable<'tcx> for ty::ParamEnvAnd<'tcx, T> { + param_env, value + } where T: TypeFoldable<'tcx> } -impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitPredicate { - trait_ref: self.trait_ref.fold_with(folder) - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.trait_ref.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> { + a_is_expected, a, b } } -impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate - where T : TypeFoldable<'tcx>, - U : TypeFoldable<'tcx>, -{ - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::OutlivesPredicate(self.0.fold_with(folder), - self.1.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) || self.1.visit_with(visitor) +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> { + trait_ref } } -impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::ClosureUpvar { - def: self.def, - span: self.span, - ty: self.ty.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) - } +TupleStructTypeFoldableImpl! { + impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate { + a, b + } where T : TypeFoldable<'tcx>, U : TypeFoldable<'tcx>, } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::error::ExpectedFound { - expected: self.expected.fold_with(folder), - found: self.found.fold_with(folder), - } +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> { + def, span, ty } +} - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.expected.visit_with(visitor) || self.found.visit_with(visitor) - } +BraceStructTypeFoldableImpl! { + impl<'tcx, T> TypeFoldable<'tcx> for ty::error::ExpectedFound { + expected, found + } where T: TypeFoldable<'tcx> } impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { @@ -1375,69 +1129,28 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - use ty::error::TypeError::*; - - match *self { - Mismatch => Mismatch, - UnsafetyMismatch(x) => UnsafetyMismatch(x.fold_with(folder)), - AbiMismatch(x) => AbiMismatch(x.fold_with(folder)), - Mutability => Mutability, - TupleSize(x) => TupleSize(x), - FixedArraySize(x) => FixedArraySize(x), - ArgCount => ArgCount, - RegionsDoesNotOutlive(a, b) => { - RegionsDoesNotOutlive(a.fold_with(folder), b.fold_with(folder)) - }, - RegionsInsufficientlyPolymorphic(a, b) => { - RegionsInsufficientlyPolymorphic(a, b.fold_with(folder)) - }, - RegionsOverlyPolymorphic(a, b) => { - RegionsOverlyPolymorphic(a, b.fold_with(folder)) - }, - IntMismatch(x) => IntMismatch(x), - FloatMismatch(x) => FloatMismatch(x), - Traits(x) => Traits(x), - VariadicMismatch(x) => VariadicMismatch(x), - CyclicTy(t) => CyclicTy(t.fold_with(folder)), - ProjectionMismatched(x) => ProjectionMismatched(x), - ProjectionBoundsLength(x) => ProjectionBoundsLength(x), - Sorts(x) => Sorts(x.fold_with(folder)), - ExistentialMismatch(x) => ExistentialMismatch(x.fold_with(folder)), - OldStyleLUB(ref x) => OldStyleLUB(x.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use ty::error::TypeError::*; - - match *self { - UnsafetyMismatch(x) => x.visit_with(visitor), - AbiMismatch(x) => x.visit_with(visitor), - RegionsDoesNotOutlive(a, b) => { - a.visit_with(visitor) || b.visit_with(visitor) - }, - RegionsInsufficientlyPolymorphic(_, b) | - RegionsOverlyPolymorphic(_, b) => { - b.visit_with(visitor) - }, - Sorts(x) => x.visit_with(visitor), - OldStyleLUB(ref x) => x.visit_with(visitor), - ExistentialMismatch(x) => x.visit_with(visitor), - CyclicTy(t) => t.visit_with(visitor), - Mismatch | - Mutability | - TupleSize(_) | - FixedArraySize(_) | - ArgCount | - IntMismatch(_) | - FloatMismatch(_) | - Traits(_) | - VariadicMismatch(_) | - ProjectionMismatched(_) | - ProjectionBoundsLength(_) => false, - } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { + (ty::error::TypeError::Mismatch), + (ty::error::TypeError::UnsafetyMismatch)(x), + (ty::error::TypeError::AbiMismatch)(x), + (ty::error::TypeError::Mutability), + (ty::error::TypeError::TupleSize)(x), + (ty::error::TypeError::FixedArraySize)(x), + (ty::error::TypeError::ArgCount), + (ty::error::TypeError::RegionsDoesNotOutlive)(a, b), + (ty::error::TypeError::RegionsInsufficientlyPolymorphic)(a, b), + (ty::error::TypeError::RegionsOverlyPolymorphic)(a, b), + (ty::error::TypeError::IntMismatch)(x), + (ty::error::TypeError::FloatMismatch)(x), + (ty::error::TypeError::Traits)(x), + (ty::error::TypeError::VariadicMismatch)(x), + (ty::error::TypeError::CyclicTy)(t), + (ty::error::TypeError::ProjectionMismatched)(x), + (ty::error::TypeError::ProjectionBoundsLength)(x), + (ty::error::TypeError::Sorts)(x), + (ty::error::TypeError::ExistentialMismatch)(x), + (ty::error::TypeError::OldStyleLUB)(x), } } -- GitLab