about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/canonical/mod.rs36
-rw-r--r--src/librustc/infer/mod.rs12
-rw-r--r--src/librustc/infer/region_constraints/mod.rs17
-rw-r--r--src/librustc/mir/mod.rs110
-rw-r--r--src/librustc/mir/tcx.rs9
-rw-r--r--src/librustc/traits/mod.rs48
-rw-r--r--src/librustc/traits/project.rs2
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs8
-rw-r--r--src/librustc/traits/query/normalize.rs8
-rw-r--r--src/librustc/traits/query/outlives_bounds.rs10
-rw-r--r--src/librustc/traits/query/type_op/ascribe_user_type.rs8
-rw-r--r--src/librustc/traits/query/type_op/eq.rs9
-rw-r--r--src/librustc/traits/query/type_op/implied_outlives_bounds.rs8
-rw-r--r--src/librustc/traits/query/type_op/normalize.rs8
-rw-r--r--src/librustc/traits/query/type_op/outlives.rs8
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs8
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs9
-rw-r--r--src/librustc/traits/select.rs19
-rw-r--r--src/librustc/traits/structural_impls.rs140
-rw-r--r--src/librustc/ty/adjustment.rs8
-rw-r--r--src/librustc/ty/context.rs26
-rw-r--r--src/librustc/ty/error.rs4
-rw-r--r--src/librustc/ty/mod.rs24
-rw-r--r--src/librustc/ty/relate.rs8
-rw-r--r--src/librustc/ty/structural_impls.rs190
-rw-r--r--src/librustc/ty/sty.rs21
-rw-r--r--src/librustc/ty/subst.rs20
27 files changed, 90 insertions, 688 deletions
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index d833feeeb09..dfd0ab1a69d 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -44,7 +44,8 @@ mod substitute;
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable,
+    HashStable, TypeFoldable)]
 pub struct Canonical<'tcx, V> {
     pub max_universe: ty::UniverseIndex,
     pub variables: CanonicalVarInfos<'tcx>,
@@ -64,7 +65,8 @@ impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
 /// vectors with the original values that were replaced by canonical
 /// variables. You will need to supply it later to instantiate the
 /// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable,
+    HashStable, TypeFoldable)]
 pub struct CanonicalVarValues<'tcx> {
     pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
 }
@@ -187,7 +189,7 @@ pub enum CanonicalTyVarKind {
 /// After we execute a query with a canonicalized key, we get back a
 /// `Canonical<QueryResponse<..>>`. You can use
 /// `instantiate_query_result` to access the data in this result.
-#[derive(Clone, Debug, HashStable)]
+#[derive(Clone, Debug, HashStable, TypeFoldable)]
 pub struct QueryResponse<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
     pub region_constraints: QueryRegionConstraints<'tcx>,
@@ -195,7 +197,7 @@ pub struct QueryResponse<'tcx, R> {
     pub value: R,
 }
 
-#[derive(Clone, Debug, Default, HashStable)]
+#[derive(Clone, Debug, Default, HashStable, TypeFoldable)]
 pub struct QueryRegionConstraints<'tcx> {
     pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
     pub member_constraints: Vec<MemberConstraint<'tcx>>,
@@ -468,14 +470,6 @@ CloneTypeFoldableImpls! {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for Canonical<'tcx, C> {
-        max_universe,
-        variables,
-        value,
-    } where C: TypeFoldable<'tcx>
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
         type Lifted = Canonical<'tcx, T::Lifted>;
@@ -535,18 +529,6 @@ BraceStructLiftImpl! {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for CanonicalVarValues<'tcx> {
-        var_values,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, R> TypeFoldable<'tcx> for QueryResponse<'tcx, R> {
-        var_values, region_constraints, certainty, value
-    } where R: TypeFoldable<'tcx>,
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
         type Lifted = QueryResponse<'tcx, R::Lifted>;
@@ -554,12 +536,6 @@ BraceStructLiftImpl! {
     } where R: Lift<'tcx>
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
-        outlives, member_constraints
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
         type Lifted = QueryRegionConstraints<'tcx>;
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index e385d576b8c..cd02e2b0e7c 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -233,7 +233,7 @@ pub struct InferCtxt<'a, 'tcx> {
 pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
 
 /// See the `error_reporting` module for more details.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)]
 pub enum ValuePairs<'tcx> {
     Types(ExpectedFound<Ty<'tcx>>),
     Regions(ExpectedFound<ty::Region<'tcx>>),
@@ -1782,16 +1782,6 @@ impl RegionVariableOrigin {
     }
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
-        (ValuePairs::Types)(a),
-        (ValuePairs::Regions)(a),
-        (ValuePairs::Consts)(a),
-        (ValuePairs::TraitRefs)(a),
-        (ValuePairs::PolyTraitRefs)(a),
-    }
-}
-
 impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 8c6a7c9a376..01182a73789 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -151,7 +151,7 @@ impl Constraint<'_> {
 /// ```
 /// R0 member of [O1..On]
 /// ```
-#[derive(Debug, Clone, HashStable)]
+#[derive(Debug, Clone, HashStable, TypeFoldable)]
 pub struct MemberConstraint<'tcx> {
     /// The `DefId` of the opaque type causing this constraint: used for error reporting.
     pub opaque_type_def_id: DefId,
@@ -169,12 +169,6 @@ pub struct MemberConstraint<'tcx> {
     pub choice_regions: Lrc<Vec<Region<'tcx>>>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for MemberConstraint<'tcx> {
-        opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for MemberConstraint<'a> {
         type Lifted = MemberConstraint<'tcx>;
@@ -195,19 +189,12 @@ pub struct Verify<'tcx> {
     pub bound: VerifyBound<'tcx>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable)]
 pub enum GenericKind<'tcx> {
     Param(ty::ParamTy),
     Projection(ty::ProjectionTy<'tcx>),
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for GenericKind<'tcx> {
-        (GenericKind::Param)(a),
-        (GenericKind::Projection)(a),
-    }
-}
-
 /// Describes the things that some `GenericKind` value `G` is known to
 /// outlive. Each variant of `VerifyBound` can be thought of as a
 /// function:
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index fd2063e2da9..84ddaee17fe 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -86,7 +86,7 @@ impl MirPhase {
 }
 
 /// The lowered representation of a single function.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, TypeFoldable)]
 pub struct Body<'tcx> {
     /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock`
     /// that indexes into this vector.
@@ -446,7 +446,7 @@ impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, HashStable)]
+#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
 pub enum ClearCrossCrate<T> {
     Clear,
     Set(T),
@@ -723,7 +723,7 @@ impl_stable_hash_for!(struct BlockTailInfo { tail_result_is_ignored });
 ///
 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
 /// argument, or the return place.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct LocalDecl<'tcx> {
     /// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
     ///
@@ -1012,7 +1012,7 @@ impl BasicBlock {
 ///////////////////////////////////////////////////////////////////////////
 // BasicBlockData and Terminator
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct BasicBlockData<'tcx> {
     /// List of statements in this block.
     pub statements: Vec<Statement<'tcx>>,
@@ -1542,7 +1542,7 @@ impl<'tcx> TerminatorKind<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct Statement<'tcx> {
     pub source_info: SourceInfo,
     pub kind: StatementKind<'tcx>,
@@ -1568,7 +1568,7 @@ impl Statement<'_> {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum StatementKind<'tcx> {
     /// Write the RHS Rvalue to the LHS Place.
     Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
@@ -1676,7 +1676,7 @@ pub enum FakeReadCause {
     ForIndex,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct InlineAsm<'tcx> {
     pub asm: HirInlineAsm,
     pub outputs: Box<[Place<'tcx>]>,
@@ -2418,17 +2418,11 @@ pub struct Constant<'tcx> {
 /// The first will lead to the constraint `w: &'1 str` (for some
 /// inferred region `'1`). The second will lead to the constraint `w:
 /// &'static str`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct UserTypeProjections {
     pub(crate) contents: Vec<(UserTypeProjection, Span)>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
-        contents
-    }
-}
-
 impl<'tcx> UserTypeProjections {
     pub fn none() -> Self {
         UserTypeProjections { contents: vec![] }
@@ -2737,7 +2731,7 @@ rustc_index::newtype_index! {
 }
 
 /// The layout of generator state.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct GeneratorLayout<'tcx> {
     /// The type of every local stored inside the generator.
     pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
@@ -2936,92 +2930,6 @@ CloneTypeFoldableAndLiftImpls! {
     UserTypeAnnotationIndex,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for Body<'tcx> {
-        phase,
-        basic_blocks,
-        source_scopes,
-        source_scope_local_data,
-        yield_ty,
-        generator_drop,
-        generator_layout,
-        local_decls,
-        user_type_annotations,
-        arg_count,
-        __upvar_debuginfo_codegen_only_do_not_use,
-        spread_arg,
-        control_flow_destroyed,
-        span,
-        cache,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for GeneratorLayout<'tcx> {
-        field_tys,
-        variant_fields,
-        storage_conflicts,
-        __local_debuginfo_codegen_only_do_not_use,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
-        mutability,
-        is_user_variable,
-        internal,
-        ty,
-        user_ty,
-        name,
-        source_info,
-        is_block_tail,
-        visibility_scope,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
-        statements,
-        terminator,
-        is_cleanup,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
-        source_info, kind
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> {
-        (StatementKind::Assign)(a),
-        (StatementKind::FakeRead)(cause, place),
-        (StatementKind::SetDiscriminant) { place, variant_index },
-        (StatementKind::StorageLive)(a),
-        (StatementKind::StorageDead)(a),
-        (StatementKind::InlineAsm)(a),
-        (StatementKind::Retag)(kind, place),
-        (StatementKind::AscribeUserType)(a, v),
-        (StatementKind::Nop),
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for InlineAsm<'tcx> {
-        asm,
-        outputs,
-        inputs,
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
-        (ClearCrossCrate::Clear),
-        (ClearCrossCrate::Set)(a),
-    } where T: TypeFoldable<'tcx>
-}
-
 impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::TerminatorKind::*;
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index c65f2b04786..ccf7d8fbf86 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -10,7 +10,7 @@ use crate::ty::layout::VariantIdx;
 use crate::hir;
 use crate::ty::util::IntTypeExt;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct PlaceTy<'tcx> {
     pub ty: Ty<'tcx>,
     /// Downcast to a particular variant of an enum, if included.
@@ -111,13 +111,6 @@ impl<'tcx> PlaceTy<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
-        ty,
-        variant_index,
-    }
-}
-
 impl<'tcx> Place<'tcx> {
     pub fn ty_from<D>(
         base: &PlaceBase<'tcx>,
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index a29d8c66d81..48ec7d32d33 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -334,7 +334,7 @@ pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
 /// are used for representing the trait system in the form of
 /// logic programming clauses. They are part of the interface
 /// for the chalk SLG solver.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum WhereClause<'tcx> {
     Implemented(ty::TraitPredicate<'tcx>),
     ProjectionEq(ty::ProjectionPredicate<'tcx>),
@@ -342,19 +342,19 @@ pub enum WhereClause<'tcx> {
     TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum WellFormed<'tcx> {
     Trait(ty::TraitPredicate<'tcx>),
     Ty(Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum FromEnv<'tcx> {
     Trait(ty::TraitPredicate<'tcx>),
     Ty(Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum DomainGoal<'tcx> {
     Holds(WhereClause<'tcx>),
     WellFormed(WellFormed<'tcx>),
@@ -370,7 +370,7 @@ pub enum QuantifierKind {
     Existential,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum GoalKind<'tcx> {
     Implies(Clauses<'tcx>, Goal<'tcx>),
     And(Goal<'tcx>, Goal<'tcx>),
@@ -416,7 +416,7 @@ impl<'tcx> GoalKind<'tcx> {
 
 /// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
 /// Harrop Formulas".
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub enum Clause<'tcx> {
     Implies(ProgramClause<'tcx>),
     ForAll(ty::Binder<ProgramClause<'tcx>>),
@@ -440,7 +440,7 @@ pub type Clauses<'tcx> = &'tcx List<Clause<'tcx>>;
 /// it with the reverse implication operator `:-` to emphasize the way
 /// that programs are actually solved (via backchaining, which starts
 /// with the goal to solve and proceeds from there).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub struct ProgramClause<'tcx> {
     /// This goal will be considered true ...
     pub goal: DomainGoal<'tcx>,
@@ -460,7 +460,7 @@ pub enum ProgramClauseCategory {
 }
 
 /// A set of clauses that we assume to be true.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub struct Environment<'tcx> {
     pub clauses: Clauses<'tcx>,
 }
@@ -475,7 +475,7 @@ impl Environment<'tcx> {
 }
 
 /// Something (usually a goal), along with an environment.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
 pub struct InEnvironment<'tcx, G> {
     pub environment: Environment<'tcx>,
     pub goal: G,
@@ -483,7 +483,7 @@ pub struct InEnvironment<'tcx, G> {
 
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 
-#[derive(Clone,Debug)]
+#[derive(Clone,Debug,TypeFoldable)]
 pub enum SelectionError<'tcx> {
     Unimplemented,
     OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
@@ -494,16 +494,6 @@ pub enum SelectionError<'tcx> {
     Overflow,
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for SelectionError<'tcx> {
-        (SelectionError::Unimplemented),
-        (SelectionError::OutputTypeParameterMismatch)(a, b, c),
-        (SelectionError::TraitNotObjectSafe)(a),
-        (SelectionError::ConstEvalFailure)(a),
-        (SelectionError::Overflow),
-    }
-}
-
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
@@ -568,7 +558,7 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
 /// ### The type parameter `N`
 ///
 /// See explanation on `VtableImplData`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
@@ -616,14 +606,14 @@ pub enum Vtable<'tcx, N> {
 /// is `Obligation`, as one might expect. During codegen, however, this
 /// is `()`, because codegen only requires a shallow resolution of an
 /// impl, and nested obligations are satisfied later.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableImplData<'tcx, N> {
     pub impl_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
     pub nested: Vec<N>
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableGeneratorData<'tcx, N> {
     pub generator_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -632,7 +622,7 @@ pub struct VtableGeneratorData<'tcx, N> {
     pub nested: Vec<N>
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableClosureData<'tcx, N> {
     pub closure_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -641,20 +631,20 @@ pub struct VtableClosureData<'tcx, N> {
     pub nested: Vec<N>
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableAutoImplData<N> {
     pub trait_def_id: DefId,
     pub nested: Vec<N>
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableBuiltinData<N> {
     pub nested: Vec<N>
 }
 
 /// A vtable for some object-safe trait `Foo` automatically derived
 /// for the object type `Foo`.
-#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableObjectData<'tcx, N> {
     /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
     pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -667,13 +657,13 @@ pub struct VtableObjectData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableFnPointerData<'tcx, N> {
     pub fn_ty: Ty<'tcx>,
     pub nested: Vec<N>
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct VtableTraitAliasData<'tcx, N> {
     pub alias_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index d88bbe145d1..c345b9a969c 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -400,7 +400,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, TypeFoldable)]
 pub struct Normalized<'tcx,T> {
     pub value: T,
     pub obligations: Vec<PredicateObligation<'tcx>>,
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index eaf5971e459..d8e413446fc 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -77,7 +77,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     }
 }
 
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, TypeFoldable)]
 pub struct DropckOutlivesResult<'tcx> {
     pub kinds: Vec<GenericArg<'tcx>>,
     pub overflows: Vec<Ty<'tcx>>,
@@ -150,12 +150,6 @@ impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
         result
     }
 }
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for DropckOutlivesResult<'tcx> {
-        kinds, overflows
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for DropckOutlivesResult<'a> {
         type Lifted = DropckOutlivesResult<'tcx>;
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index ab42eab2844..5115119fa74 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -66,7 +66,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
 }
 
 /// Result from the `normalize_projection_ty` query.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub struct NormalizationResult<'tcx> {
     /// Result of normalization.
     pub normalized_ty: Ty<'tcx>,
@@ -194,12 +194,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for NormalizationResult<'tcx> {
-        normalized_ty
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for NormalizationResult<'a> {
         type Lifted = NormalizationResult<'tcx>;
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index eee084b7896..93414b68982 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -17,7 +17,7 @@ use std::mem;
 /// case they are called implied bounds). They are fed to the
 /// `OutlivesEnv` which in turn is supplied to the region checker and
 /// other parts of the inference system.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
@@ -33,14 +33,6 @@ EnumLiftImpl! {
     }
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for self::OutlivesBound<'tcx> {
-        (self::OutlivesBound::RegionSubRegion)(a, b),
-        (self::OutlivesBound::RegionSubParam)(a, b),
-        (self::OutlivesBound::RegionSubProjection)(a, b),
-    }
-}
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OutlivesBound<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs
index 34aa4ee78da..259efb43de7 100644
--- a/src/librustc/traits/query/type_op/ascribe_user_type.rs
+++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs
@@ -4,7 +4,7 @@ use crate::hir::def_id::DefId;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
 use crate::ty::subst::UserSubsts;
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable)]
 pub struct AscribeUserType<'tcx> {
     pub mir_ty: Ty<'tcx>,
     pub def_id: DefId,
@@ -39,12 +39,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
-        mir_ty, def_id, user_substs
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
         type Lifted = AscribeUserType<'tcx>;
diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs
index 3653f9268dc..b51e8f89a31 100644
--- a/src/librustc/traits/query/type_op/eq.rs
+++ b/src/librustc/traits/query/type_op/eq.rs
@@ -2,7 +2,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable)]
 pub struct Eq<'tcx> {
     pub a: Ty<'tcx>,
     pub b: Ty<'tcx>,
@@ -36,13 +36,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for Eq<'tcx> {
-        a,
-        b,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for Eq<'a> {
         type Lifted = Eq<'tcx>;
diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs
index 7aa98703411..59d1920f68a 100644
--- a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs
+++ b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs
@@ -3,7 +3,7 @@ use crate::traits::query::outlives_bounds::OutlivesBound;
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub struct ImpliedOutlivesBounds<'tcx> {
     pub ty: Ty<'tcx>,
 }
@@ -40,12 +40,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ImpliedOutlivesBounds<'tcx> {
-        ty,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> {
         type Lifted = ImpliedOutlivesBounds<'tcx>;
diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs
index 2138f792d45..5b8164c3a24 100644
--- a/src/librustc/traits/query/type_op/normalize.rs
+++ b/src/librustc/traits/query/type_op/normalize.rs
@@ -4,7 +4,7 @@ use crate::traits::query::Fallible;
 use crate::ty::fold::TypeFoldable;
 use crate::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable)]
 pub struct Normalize<T> {
     pub value: T,
 }
@@ -83,12 +83,6 @@ impl Normalizable<'tcx> for ty::FnSig<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, T> TypeFoldable<'tcx> for Normalize<T> {
-        value,
-    } where T: TypeFoldable<'tcx>,
-}
-
 BraceStructLiftImpl! {
     impl<'tcx, T> Lift<'tcx> for Normalize<T> {
         type Lifted = Normalize<T::Lifted>;
diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs
index 81c3857cbf8..3d52452cf34 100644
--- a/src/librustc/traits/query/type_op/outlives.rs
+++ b/src/librustc/traits/query/type_op/outlives.rs
@@ -3,7 +3,7 @@ use crate::traits::query::dropck_outlives::{DropckOutlivesResult, trivial_dropck
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct DropckOutlives<'tcx> {
     dropped_ty: Ty<'tcx>,
 }
@@ -54,12 +54,6 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for DropckOutlives<'tcx> {
-        dropped_ty
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for DropckOutlives<'a> {
         type Lifted = DropckOutlives<'tcx>;
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs
index 2a908d0f66e..d0dd50326dd 100644
--- a/src/librustc/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc/traits/query/type_op/prove_predicate.rs
@@ -2,7 +2,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Predicate, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable)]
 pub struct ProvePredicate<'tcx> {
     pub predicate: Predicate<'tcx>,
 }
@@ -45,12 +45,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ProvePredicate<'tcx> {
-        predicate,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for ProvePredicate<'a> {
         type Lifted = ProvePredicate<'tcx>;
diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs
index c89a55daa09..72ce91845c1 100644
--- a/src/librustc/traits/query/type_op/subtype.rs
+++ b/src/librustc/traits/query/type_op/subtype.rs
@@ -2,7 +2,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
 use crate::traits::query::Fallible;
 use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
 
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable)]
 pub struct Subtype<'tcx> {
     pub sub: Ty<'tcx>,
     pub sup: Ty<'tcx>,
@@ -36,13 +36,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for Subtype<'tcx> {
-        sub,
-        sup,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for Subtype<'a> {
         type Lifted = Subtype<'tcx>;
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 04b2597af22..608883d609f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -280,7 +280,7 @@ pub struct SelectionCache<'tcx> {
 /// required for associated types to work in default impls, as the bounds
 /// are visible both as projection bounds and as where-clauses from the
 /// parameter environment.
-#[derive(PartialEq, Eq, Debug, Clone)]
+#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
 enum SelectionCandidate<'tcx> {
     /// If has_nested is false, there are no *further* obligations
     BuiltinCandidate {
@@ -338,23 +338,6 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
     }
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for SelectionCandidate<'tcx> {
-        (SelectionCandidate::BuiltinCandidate) { has_nested },
-        (SelectionCandidate::ParamCandidate)(poly_trait_ref),
-        (SelectionCandidate::ImplCandidate)(def_id),
-        (SelectionCandidate::AutoImplCandidate)(def_id),
-        (SelectionCandidate::ProjectionCandidate),
-        (SelectionCandidate::ClosureCandidate),
-        (SelectionCandidate::GeneratorCandidate),
-        (SelectionCandidate::FnPointerCandidate),
-        (SelectionCandidate::TraitAliasCandidate)(def_id),
-        (SelectionCandidate::ObjectCandidate),
-        (SelectionCandidate::BuiltinObjectCandidate),
-        (SelectionCandidate::BuiltinUnsizeCandidate),
-    }
-}
-
 struct SelectionCandidateSet<'tcx> {
     // a list of candidates that definitely apply to the current
     // obligation (meaning: types unify).
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 59f2bb37548..56f1ad6031e 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -778,124 +778,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
-        impl_def_id, substs, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableGeneratorData<'tcx, N> {
-        generator_def_id, substs, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
-        closure_def_id, substs, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableAutoImplData<N> {
-        trait_def_id, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
-        nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx, N> {
-        upcast_trait_ref, vtable_base, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableFnPointerData<'tcx, N> {
-        fn_ty,
-        nested
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableTraitAliasData<'tcx, N> {
-        alias_def_id, substs, nested
-    } where N: TypeFoldable<'tcx>
-}
-
-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),
-        (traits::VtableTraitAlias)(a),
-    } where N: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, T> TypeFoldable<'tcx> for Normalized<'tcx, T> {
-        value,
-        obligations
-    } where T: TypeFoldable<'tcx>
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::WhereClause<'tcx> {
-        (traits::WhereClause::Implemented)(trait_ref),
-        (traits::WhereClause::ProjectionEq)(projection),
-        (traits::WhereClause::TypeOutlives)(ty_outlives),
-        (traits::WhereClause::RegionOutlives)(region_outlives),
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::WellFormed<'tcx> {
-        (traits::WellFormed::Trait)(trait_ref),
-        (traits::WellFormed::Ty)(ty),
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::FromEnv<'tcx> {
-        (traits::FromEnv::Trait)(trait_ref),
-        (traits::FromEnv::Ty)(ty),
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
-        (traits::DomainGoal::Holds)(wc),
-        (traits::DomainGoal::WellFormed)(wf),
-        (traits::DomainGoal::FromEnv)(from_env),
-        (traits::DomainGoal::Normalize)(projection),
-    }
-}
-
 CloneTypeFoldableAndLiftImpls! {
     traits::QuantifierKind,
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::GoalKind<'tcx> {
-        (traits::GoalKind::Implies)(hypotheses, goal),
-        (traits::GoalKind::And)(goal1, goal2),
-        (traits::GoalKind::Not)(goal),
-        (traits::GoalKind::DomainGoal)(domain_goal),
-        (traits::GoalKind::Quantified)(qkind, goal),
-        (traits::GoalKind::Subtype)(a, b),
-        (traits::GoalKind::CannotProve),
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Goal<'tcx>> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
@@ -920,36 +806,10 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
-        goal,
-        hypotheses,
-        category,
-    }
-}
-
 CloneTypeFoldableAndLiftImpls! {
     traits::ProgramClauseCategory,
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
-        (traits::Clause::Implies)(clause),
-        (traits::Clause::ForAll)(clause),
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for traits::Environment<'tcx> { clauses }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, G> TypeFoldable<'tcx> for traits::InEnvironment<'tcx, G> {
-        environment,
-        goal
-    } where G: TypeFoldable<'tcx>
-}
-
 impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter()
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index f5ab1eb38c3..342644752b6 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -76,13 +76,13 @@ pub enum PointerCast {
 ///    At some point, of course, `Box` should move out of the compiler, in which
 ///    case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
 ///    Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct Adjustment<'tcx> {
     pub kind: Adjust<'tcx>,
     pub target: Ty<'tcx>,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum Adjust<'tcx> {
     /// Go from ! to any type.
     NeverToAny,
@@ -100,7 +100,7 @@ pub enum Adjust<'tcx> {
 /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
 /// The target type is `U` in both cases, with the region and mutability
 /// being those shared by both the receiver and the returned reference.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct OverloadedDeref<'tcx> {
     pub region: ty::Region<'tcx>,
     pub mutbl: hir::Mutability,
@@ -151,7 +151,7 @@ impl From<AutoBorrowMutability> for hir::Mutability {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum AutoBorrow<'tcx> {
     /// Converts from T to &T.
     Ref(ty::Region<'tcx>, AutoBorrowMutability),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index a15acb00c17..d80f3e5c6b6 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -307,7 +307,8 @@ pub struct ResolvedOpaqueTy<'tcx> {
 ///
 /// Here, we would store the type `T`, the span of the value `x`, and the "scope-span" for
 /// the scope that contains `x`.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, HashStable, PartialEq)]
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, HashStable, PartialEq,
+    TypeFoldable)]
 pub struct GeneratorInteriorTypeCause<'tcx> {
     /// Type of the captured binding.
     pub ty: Ty<'tcx>,
@@ -317,12 +318,6 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
     pub scope_span: Option<Span>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for GeneratorInteriorTypeCause<'tcx> {
-        ty, span, scope_span
-    }
-}
-
 #[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct TypeckTables<'tcx> {
     /// The HirId::owner all ItemLocalIds in this table are relative to.
@@ -831,19 +826,13 @@ rustc_index::newtype_index! {
 pub type CanonicalUserTypeAnnotations<'tcx> =
     IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct CanonicalUserTypeAnnotation<'tcx> {
     pub user_ty: CanonicalUserType<'tcx>,
     pub span: Span,
     pub inferred_ty: Ty<'tcx>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
-        user_ty, span, inferred_ty
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
         type Lifted = CanonicalUserTypeAnnotation<'tcx>;
@@ -903,7 +892,7 @@ impl CanonicalUserType<'tcx> {
 /// A user-given type annotation attached to a constant. These arise
 /// from constants that are named via paths, like `Foo::<A>::new` and
 /// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum UserType<'tcx> {
     Ty(Ty<'tcx>),
 
@@ -912,13 +901,6 @@ pub enum UserType<'tcx> {
     TypeOf(DefId, UserSubsts<'tcx>),
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserType<'tcx> {
-        (UserType::Ty)(ty),
-        (UserType::TypeOf)(def, substs),
-    }
-}
-
 EnumLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for UserType<'a> {
         type Lifted = UserType<'tcx>;
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index c61d559af53..febea68ddbb 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -10,14 +10,14 @@ use syntax_pos::Span;
 
 use crate::hir;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
 pub struct ExpectedFound<T> {
     pub expected: T,
     pub found: T,
 }
 
 // Data structures used in type unification
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub enum TypeError<'tcx> {
     Mismatch,
     UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e4ed1cd198e..5c6f963371f 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -166,7 +166,7 @@ impl AssocItemContainer {
 /// The "header" of an impl is everything outside the body: a Self type, a trait
 /// ref (in the case of a trait impl), and a set of predicates (from the
 /// bounds / where-clauses).
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub struct ImplHeader<'tcx> {
     pub impl_def_id: DefId,
     pub self_ty: Ty<'tcx>,
@@ -832,7 +832,7 @@ pub struct UpvarBorrow<'tcx> {
 pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
 pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, TypeFoldable)]
 pub struct ClosureUpvar<'tcx> {
     pub res: Res,
     pub span: Span,
@@ -1097,7 +1097,8 @@ impl<'tcx> GenericPredicates<'tcx> {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+         HashStable, TypeFoldable)]
 pub enum Predicate<'tcx> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -1247,7 +1248,8 @@ impl<'tcx> Predicate<'tcx> {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+         HashStable, TypeFoldable)]
 pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>
 }
@@ -1276,7 +1278,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord,
-         Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+         Hash, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
 pub type PolyOutlivesPredicate<A, B> = ty::Binder<OutlivesPredicate<A, B>>;
 pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
@@ -1284,7 +1286,8 @@ pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'t
 pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>;
 pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>;
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable,
+         HashStable, TypeFoldable)]
 pub struct SubtypePredicate<'tcx> {
     pub a_is_expected: bool,
     pub a: Ty<'tcx>,
@@ -1304,7 +1307,8 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+         HashStable, TypeFoldable)]
 pub struct ProjectionPredicate<'tcx> {
     pub projection_ty: ProjectionTy<'tcx>,
     pub ty: Ty<'tcx>,
@@ -1534,7 +1538,7 @@ impl<'tcx> Predicate<'tcx> {
 /// `[[], [U:Bar<T>]]`. Now if there were some particular reference
 /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
 /// [usize:Bar<isize>]]`.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub struct InstantiatedPredicates<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
@@ -1658,7 +1662,7 @@ pub type PlaceholderConst = Placeholder<BoundVar>;
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
 /// particular point.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeFoldable)]
 pub struct ParamEnv<'tcx> {
     /// `Obligation`s that the caller must satisfy. This is basically
     /// the set of bounds on the in-scope type parameters, translated
@@ -1764,7 +1768,7 @@ impl<'tcx> ParamEnv<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
 pub struct ParamEnvAnd<'tcx, T> {
     pub param_env: ParamEnv<'tcx>,
     pub value: T,
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 9b5cdc489a8..57415e37560 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -307,15 +307,9 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, TypeFoldable)]
 struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
 
-TupleStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for GeneratorWitness<'tcx> {
-        a
-    }
-}
-
 impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 5d78d563e9a..266549e5f63 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -916,10 +916,6 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds, def_id }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
@@ -931,14 +927,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
     }
 }
 
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> {
-        (ty::ExistentialPredicate::Trait)(a),
-        (ty::ExistentialPredicate::Projection)(a),
-        (ty::ExistentialPredicate::AutoTrait)(a),
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
@@ -1125,41 +1113,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {
-        ty, mutbl
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::GenSig<'tcx> {
-        yield_ty, return_ty
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
-        inputs_and_output, c_variadic, unsafety, abi
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { def_id, substs }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { def_id, substs }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ImplHeader<'tcx> {
-        impl_def_id,
-        self_ty,
-        trait_ref,
-        predicates,
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> Self {
         *self
@@ -1178,47 +1131,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
-        substs,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorSubsts<'tcx> {
-        substs,
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
-        kind,
-        target,
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
-        (ty::adjustment::Adjust::NeverToAny),
-        (ty::adjustment::Adjust::Pointer)(a),
-        (ty::adjustment::Adjust::Deref)(a),
-        (ty::adjustment::Adjust::Borrow)(a),
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::OverloadedDeref<'tcx> {
-        region, mutbl,
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
-        (ty::adjustment::AutoBorrow::Ref)(a, b),
-        (ty::adjustment::AutoBorrow::RawPtr)(m),
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         // This code is hot enough that it's worth specializing for a list of
@@ -1243,80 +1155,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
     }
 }
 
-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),
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
-        projection_ty, ty
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
-        ty, substs, item_def_id
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
-        substs, item_def_id
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
-        predicates
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, T> TypeFoldable<'tcx> for ty::ParamEnvAnd<'tcx, T> {
-        param_env, value
-    } where T: TypeFoldable<'tcx>
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
-        a_is_expected, a, b
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
-        trait_ref
-    }
-}
-
-TupleStructTypeFoldableImpl! {
-    impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U> {
-        a, b
-    } where T : TypeFoldable<'tcx>, U : TypeFoldable<'tcx>,
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
-        res, span, ty
-    }
-}
-
-BraceStructTypeFoldableImpl! {
-    impl<'tcx, T> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
-        expected, found
-    } where T: TypeFoldable<'tcx>
-}
-
 impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.iter().map(|x| x.fold_with(folder)).collect()
@@ -1327,34 +1165,6 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T>
     }
 }
 
-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::RegionsPlaceholderMismatch),
-        (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::ConstMismatch)(x),
-        (ty::error::TypeError::IntrinsicCast),
-        (ty::error::TypeError::ObjectUnsafeCoercion)(x),
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let ty = self.ty.fold_with(folder);
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 51cf7550c30..0f8f4152e7d 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -30,7 +30,7 @@ use self::InferTy::*;
 use self::TyKind::*;
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord,
-         Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+         Hash, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct TypeAndMut<'tcx> {
     pub ty: Ty<'tcx>,
     pub mutbl: hir::Mutability,
@@ -304,7 +304,7 @@ static_assert_size!(TyKind<'_>, 24);
 /// type parameters is similar, but the role of CK and CS are
 /// different. CK represents the "yield type" and CS represents the
 /// "return type" of the generator.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with the types of the upvars.
@@ -391,7 +391,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
 }
 
 /// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, TypeFoldable)]
 pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
@@ -592,7 +592,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash,
-         RustcEncodable, RustcDecodable, HashStable)]
+         RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum ExistentialPredicate<'tcx> {
     /// E.g., `Iterator`.
     Trait(ExistentialTraitRef<'tcx>),
@@ -742,7 +742,8 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
 /// Note that a `TraitRef` introduces a level of region binding, to
 /// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>`
 /// or higher-ranked object types.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+         HashStable, TypeFoldable)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -814,7 +815,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
 /// The substitutions don't include the erased `Self`, only trait
 /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         RustcEncodable, RustcDecodable, HashStable)]
+         RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct ExistentialTraitRef<'tcx> {
     pub def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -986,7 +987,7 @@ impl<T> Binder<T> {
 /// Represents the projection of an associated type. In explicit UFCS
 /// form this would be written `<T as Trait<..>>::N`.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord,
-         Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+         Hash, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct ProjectionTy<'tcx> {
     /// The parameters of the associated item.
     pub substs: SubstsRef<'tcx>,
@@ -1033,7 +1034,7 @@ impl<'tcx> ProjectionTy<'tcx> {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, TypeFoldable)]
 pub struct GenSig<'tcx> {
     pub yield_ty: Ty<'tcx>,
     pub return_ty: Ty<'tcx>,
@@ -1057,7 +1058,7 @@ impl<'tcx> PolyGenSig<'tcx> {
 /// - `output`: is the return type.
 /// - `c_variadic`: indicates whether this is a C-variadic function.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord,
-         Hash, RustcEncodable, RustcDecodable, HashStable)]
+         Hash, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct FnSig<'tcx> {
     pub inputs_and_output: &'tcx List<Ty<'tcx>>,
     pub c_variadic: bool,
@@ -1404,7 +1405,7 @@ impl From<BoundVar> for BoundTy {
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
-         Debug, RustcEncodable, RustcDecodable, HashStable)]
+         Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct ExistentialProjection<'tcx> {
     pub item_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 29721979099..3c8da15cc22 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -731,7 +731,8 @@ pub type CanonicalUserSubsts<'tcx> = Canonical<'tcx, UserSubsts<'tcx>>;
 
 /// Stores the user-given substs to reach some fully qualified path
 /// (e.g., `<T>::Item` or `<T as Trait>::Item`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+    HashStable, TypeFoldable)]
 pub struct UserSubsts<'tcx> {
     /// The substitutions for the item as given by the user.
     pub substs: SubstsRef<'tcx>,
@@ -741,13 +742,6 @@ pub struct UserSubsts<'tcx> {
     pub user_self_ty: Option<UserSelfTy<'tcx>>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserSubsts<'tcx> {
-        substs,
-        user_self_ty,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for UserSubsts<'a> {
         type Lifted = UserSubsts<'tcx>;
@@ -772,19 +766,13 @@ BraceStructLiftImpl! {
 /// the impl (with the substs from `UserSubsts`) and apply those to
 /// the self type, giving `Foo<?A>`. Finally, we unify that with
 /// the self type here, which contains `?A` to be `&'static u32`
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable,
+    HashStable, TypeFoldable)]
 pub struct UserSelfTy<'tcx> {
     pub impl_def_id: DefId,
     pub self_ty: Ty<'tcx>,
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserSelfTy<'tcx> {
-        impl_def_id,
-        self_ty,
-    }
-}
-
 BraceStructLiftImpl! {
     impl<'a, 'tcx> Lift<'tcx> for UserSelfTy<'a> {
         type Lifted = UserSelfTy<'tcx>;