about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/canonical/mod.rs38
-rw-r--r--src/librustc/infer/region_constraints/mod.rs9
-rw-r--r--src/librustc/macros.rs71
-rw-r--r--src/librustc/mir/interpret/mod.rs3
-rw-r--r--src/librustc/traits/mod.rs10
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs9
-rw-r--r--src/librustc/traits/query/normalize.rs9
-rw-r--r--src/librustc/traits/query/outlives_bounds.rs13
-rw-r--r--src/librustc/traits/query/type_op/ascribe_user_type.rs9
-rw-r--r--src/librustc/traits/query/type_op/eq.rs10
-rw-r--r--src/librustc/traits/query/type_op/implied_outlives_bounds.rs9
-rw-r--r--src/librustc/traits/query/type_op/normalize.rs9
-rw-r--r--src/librustc/traits/query/type_op/outlives.rs9
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs9
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs10
-rw-r--r--src/librustc/traits/structural_impls.rs49
-rw-r--r--src/librustc/ty/context.rs20
-rw-r--r--src/librustc/ty/instance.rs3
-rw-r--r--src/librustc/ty/structural_impls.rs24
-rw-r--r--src/librustc/ty/sty.rs2
-rw-r--r--src/librustc/ty/subst.rs20
-rw-r--r--src/librustc_macros/src/lib.rs2
-rw-r--r--src/librustc_macros/src/lift.rs50
-rw-r--r--src/librustc_traits/chalk_context/mod.rs12
24 files changed, 87 insertions, 322 deletions
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index ee79960259d..b0f65ac6e1b 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -32,7 +32,7 @@ use std::ops::Index;
 use syntax::source_map::Span;
 use crate::ty::fold::TypeFoldable;
 use crate::ty::subst::GenericArg;
-use crate::ty::{self, BoundVar, Lift, List, Region, TyCtxt};
+use crate::ty::{self, BoundVar, List, Region, TyCtxt};
 
 mod canonicalizer;
 
@@ -44,7 +44,7 @@ mod substitute;
 /// 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)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub struct Canonical<'tcx, V> {
     pub max_universe: ty::UniverseIndex,
     pub variables: CanonicalVarInfos<'tcx>,
@@ -65,7 +65,7 @@ impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
 /// variables. You will need to supply it later to instantiate the
 /// canonicalized query response.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub struct CanonicalVarValues<'tcx> {
     pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
 }
@@ -188,7 +188,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, TypeFoldable)]
+#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
 pub struct QueryResponse<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
     pub region_constraints: QueryRegionConstraints<'tcx>,
@@ -196,7 +196,7 @@ pub struct QueryResponse<'tcx, R> {
     pub value: R,
 }
 
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
 pub struct QueryRegionConstraints<'tcx> {
     pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
     pub member_constraints: Vec<MemberConstraint<'tcx>>,
@@ -469,13 +469,6 @@ CloneTypeFoldableImpls! {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
-        type Lifted = Canonical<'tcx, T::Lifted>;
-        max_universe, variables, value
-    } where T: Lift<'tcx>
-}
-
 impl<'tcx> CanonicalVarValues<'tcx> {
     pub fn len(&self) -> usize {
         self.var_values.len()
@@ -521,27 +514,6 @@ impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for CanonicalVarValues<'a> {
-        type Lifted = CanonicalVarValues<'tcx>;
-        var_values,
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
-        type Lifted = QueryResponse<'tcx, R::Lifted>;
-        var_values, region_constraints, certainty, value
-    } where R: Lift<'tcx>
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
-        type Lifted = QueryRegionConstraints<'tcx>;
-        outlives, member_constraints
-    }
-}
-
 impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
     type Output = GenericArg<'tcx>;
 
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 01182a73789..402449ce6cc 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, TypeFoldable)]
+#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
 pub struct MemberConstraint<'tcx> {
     /// The `DefId` of the opaque type causing this constraint: used for error reporting.
     pub opaque_type_def_id: DefId,
@@ -169,13 +169,6 @@ pub struct MemberConstraint<'tcx> {
     pub choice_regions: Lrc<Vec<Region<'tcx>>>,
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for MemberConstraint<'a> {
-        type Lifted = MemberConstraint<'tcx>;
-        opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
-    }
-}
-
 /// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
 /// associated type) must outlive the region `R`. `T` is known to
 /// outlive `RS`. Therefore, verify that `R <= RS[i]` for some
diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs
index 2d0538ad8e0..aae1c7a2992 100644
--- a/src/librustc/macros.rs
+++ b/src/librustc/macros.rs
@@ -254,77 +254,6 @@ macro_rules! CloneTypeFoldableAndLiftImpls {
 }
 
 #[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(&self, tcx: TyCtxt<$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;
-        $($variants:tt)*
-    } $(where $($wc:tt)*)*) => {
-        impl<$($p),*> $crate::ty::Lift<$tcx> for $s
-            $(where $($wc)*)*
-        {
-            type Lifted = $lifted;
-
-            fn lift_to_tcx(&self, tcx: TyCtxt<$tcx>) -> Option<$lifted> {
-                EnumLiftImpl!(@Variants(self, tcx) input($($variants)*) output())
-            }
-        }
-    };
-
-    (@Variants($this:expr, $tcx:expr) input() output($($output:tt)*)) => {
-        match $this {
-            $($output)*
-        }
-    };
-
-    (@Variants($this:expr, $tcx:expr)
-     input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumLiftImpl!(
-            @Variants($this, $tcx)
-                input($($input)*)
-                output(
-                    $variant ( $($variant_arg),* ) => {
-                        Some($variant ( $($tcx.lift($variant_arg)?),* ))
-                    }
-                    $($output)*
-                )
-        )
-    };
-
-    (@Variants($this:expr, $tcx:expr)
-     input( ($variant:path), $($input:tt)*)
-     output( $($output:tt)*) ) => {
-        EnumLiftImpl!(
-            @Variants($this, $tcx)
-                input($($input)*)
-                output(
-                    $variant => { Some($variant) }
-                    $($output)*
-                )
-        )
-    };
-}
-
-#[macro_export]
 macro_rules! EnumTypeFoldableImpl {
     (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
         $($variants:tt)*
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 6c31d54e081..31c50610ac4 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -124,7 +124,8 @@ use rustc_macros::HashStable;
 use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
 
 /// Uniquely identifies a specific constant or static.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(HashStable, Lift)]
 pub struct GlobalId<'tcx> {
     /// For a constant or static, the `Instance` of the item itself.
     /// For a promoted global, the `Instance` of the function they belong to.
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 42a74cac922..3aa355ce11a 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, TypeFoldable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
 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, TypeFoldable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
 pub enum WellFormed<'tcx> {
     Trait(ty::TraitPredicate<'tcx>),
     Ty(Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
 pub enum FromEnv<'tcx> {
     Trait(ty::TraitPredicate<'tcx>),
     Ty(Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
 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, TypeFoldable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, Lift)]
 pub enum GoalKind<'tcx> {
     Implies(Clauses<'tcx>, Goal<'tcx>),
     And(Goal<'tcx>, Goal<'tcx>),
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 4d6937d325e..93f56804a9f 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -79,7 +79,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
     }
 }
 
-#[derive(Clone, Debug, Default, TypeFoldable)]
+#[derive(Clone, Debug, Default, TypeFoldable, Lift)]
 pub struct DropckOutlivesResult<'tcx> {
     pub kinds: Vec<GenericArg<'tcx>>,
     pub overflows: Vec<Ty<'tcx>>,
@@ -152,13 +152,6 @@ impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
         result
     }
 }
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for DropckOutlivesResult<'a> {
-        type Lifted = DropckOutlivesResult<'tcx>;
-        kinds, overflows
-    }
-}
-
 impl_stable_hash_for!(struct DropckOutlivesResult<'tcx> {
     kinds, overflows
 });
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 5115119fa74..30528dcebda 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, TypeFoldable)]
+#[derive(Clone, Debug, TypeFoldable, Lift)]
 pub struct NormalizationResult<'tcx> {
     /// Result of normalization.
     pub normalized_ty: Ty<'tcx>,
@@ -194,13 +194,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for NormalizationResult<'a> {
-        type Lifted = NormalizationResult<'tcx>;
-        normalized_ty
-    }
-}
-
 impl_stable_hash_for!(struct NormalizationResult<'tcx> {
     normalized_ty
 });
diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs
index 93414b68982..d6cd2cce425 100644
--- a/src/librustc/traits/query/outlives_bounds.rs
+++ b/src/librustc/traits/query/outlives_bounds.rs
@@ -4,7 +4,7 @@ use crate::hir;
 use syntax::source_map::Span;
 use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
 use crate::traits::query::NoSolution;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Ty};
 
 use crate::ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -17,22 +17,13 @@ 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, TypeFoldable)]
+#[derive(Clone, Debug, TypeFoldable, Lift)]
 pub enum OutlivesBound<'tcx> {
     RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
     RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
     RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for self::OutlivesBound<'a> {
-        type Lifted = 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 259efb43de7..8b0ee5feed7 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable, Lift)]
 pub struct AscribeUserType<'tcx> {
     pub mir_ty: Ty<'tcx>,
     pub def_id: DefId,
@@ -39,13 +39,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
-        type Lifted = AscribeUserType<'tcx>;
-        mir_ty, def_id, user_substs
-    }
-}
-
 impl_stable_hash_for! {
     struct AscribeUserType<'tcx> {
         mir_ty, def_id, user_substs
diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs
index b51e8f89a31..5086994fbb6 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable, Lift)]
 pub struct Eq<'tcx> {
     pub a: Ty<'tcx>,
     pub b: Ty<'tcx>,
@@ -36,14 +36,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for Eq<'a> {
-        type Lifted = Eq<'tcx>;
-        a,
-        b,
-    }
-}
-
 impl_stable_hash_for! {
     struct Eq<'tcx> { a, b }
 }
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 59d1920f68a..f97b34f9e9a 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, TypeFoldable)]
+#[derive(Clone, Debug, TypeFoldable, Lift)]
 pub struct ImpliedOutlivesBounds<'tcx> {
     pub ty: Ty<'tcx>,
 }
@@ -40,13 +40,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ImpliedOutlivesBounds<'a> {
-        type Lifted = ImpliedOutlivesBounds<'tcx>;
-        ty,
-    }
-}
-
 impl_stable_hash_for! {
     struct ImpliedOutlivesBounds<'tcx> { ty }
 }
diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs
index 5b8164c3a24..798fc5224cc 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable, Lift)]
 pub struct Normalize<T> {
     pub value: T,
 }
@@ -83,13 +83,6 @@ impl Normalizable<'tcx> for ty::FnSig<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'tcx, T> Lift<'tcx> for Normalize<T> {
-        type Lifted = Normalize<T::Lifted>;
-        value,
-    } where T: Lift<'tcx>,
-}
-
 impl_stable_hash_for! {
     impl<T> for struct Normalize<T> {
         value
diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs
index 3d52452cf34..d2a7fdc8946 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, TypeFoldable, Lift)]
 pub struct DropckOutlives<'tcx> {
     dropped_ty: Ty<'tcx>,
 }
@@ -54,13 +54,6 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for DropckOutlives<'a> {
-        type Lifted = DropckOutlives<'tcx>;
-        dropped_ty
-    }
-}
-
 impl_stable_hash_for! {
     struct DropckOutlives<'tcx> { dropped_ty }
 }
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs
index d0dd50326dd..cbf485fcfe0 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable, Lift)]
 pub struct ProvePredicate<'tcx> {
     pub predicate: Predicate<'tcx>,
 }
@@ -45,13 +45,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ProvePredicate<'a> {
-        type Lifted = ProvePredicate<'tcx>;
-        predicate,
-    }
-}
-
 impl_stable_hash_for! {
     struct ProvePredicate<'tcx> { predicate }
 }
diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs
index 72ce91845c1..bd53e234a6a 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, TypeFoldable, Lift)]
 pub struct Subtype<'tcx> {
     pub sub: Ty<'tcx>,
     pub sup: Ty<'tcx>,
@@ -36,14 +36,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for Subtype<'a> {
-        type Lifted = Subtype<'tcx>;
-        sub,
-        sup,
-    }
-}
-
 impl_stable_hash_for! {
     struct Subtype<'tcx> { sub, sup }
 }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 56f1ad6031e..8c300da11fc 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -650,55 +650,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
     }
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::WhereClause<'a> {
-        type Lifted = traits::WhereClause<'tcx>;
-        (traits::WhereClause::Implemented)(trait_ref),
-        (traits::WhereClause::ProjectionEq)(projection),
-        (traits::WhereClause::TypeOutlives)(ty_outlives),
-        (traits::WhereClause::RegionOutlives)(region_outlives),
-    }
-}
-
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::WellFormed<'a> {
-        type Lifted = traits::WellFormed<'tcx>;
-        (traits::WellFormed::Trait)(trait_ref),
-        (traits::WellFormed::Ty)(ty),
-    }
-}
-
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::FromEnv<'a> {
-        type Lifted = traits::FromEnv<'tcx>;
-        (traits::FromEnv::Trait)(trait_ref),
-        (traits::FromEnv::Ty)(ty),
-    }
-}
-
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> {
-        type Lifted = traits::DomainGoal<'tcx>;
-        (traits::DomainGoal::Holds)(wc),
-        (traits::DomainGoal::WellFormed)(wf),
-        (traits::DomainGoal::FromEnv)(from_env),
-        (traits::DomainGoal::Normalize)(projection),
-    }
-}
-
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> {
-        type Lifted = 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)(kind, goal),
-        (traits::GoalKind::Subtype)(a, b),
-        (traits::GoalKind::CannotProve),
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
     type Lifted = traits::Environment<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d9e6af7fe48..41d069bf6ae 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -826,20 +826,13 @@ rustc_index::newtype_index! {
 pub type CanonicalUserTypeAnnotations<'tcx> =
     IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
 pub struct CanonicalUserTypeAnnotation<'tcx> {
     pub user_ty: CanonicalUserType<'tcx>,
     pub span: Span,
     pub inferred_ty: Ty<'tcx>,
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
-        type Lifted = CanonicalUserTypeAnnotation<'tcx>;
-        user_ty, span, inferred_ty
-    }
-}
-
 /// Canonicalized user type annotation.
 pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
 
@@ -892,7 +885,8 @@ 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, TypeFoldable)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub enum UserType<'tcx> {
     Ty(Ty<'tcx>),
 
@@ -901,14 +895,6 @@ pub enum UserType<'tcx> {
     TypeOf(DefId, UserSubsts<'tcx>),
 }
 
-EnumLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for UserType<'a> {
-        type Lifted = UserType<'tcx>;
-        (UserType::Ty)(ty),
-        (UserType::TypeOf)(def, substs),
-    }
-}
-
 impl<'tcx> CommonTypes<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
         let mk = |ty| interners.intern_ty(ty);
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 5139c8085a5..7eee0a5e2b5 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -12,7 +12,8 @@ use rustc_macros::HashStable;
 use std::fmt;
 use std::iter;
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable, Lift)]
 pub struct Instance<'tcx> {
     pub def: InstanceDef<'tcx>,
     pub substs: SubstsRef<'tcx>,
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 578955575af..ccac7720914 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -1,7 +1,6 @@
 //! This module contains implements of the `Lift` and `TypeFoldable`
 //! traits for various types in the Rust compiler. Most are written by
-//! hand, though we've recently added some macros (e.g.,
-//! `BraceStructLiftImpl!`) to help with the tedium.
+//! hand, though we've recently added some macros and proc-macros to help with the tedium.
 
 use crate::hir::def::Namespace;
 use crate::mir::ProjectionKind;
@@ -779,27 +778,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ty::TypeAndMut<'a> {
-        type Lifted = ty::TypeAndMut<'tcx>;
-        ty, mutbl
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> {
-        type Lifted = ty::Instance<'tcx>;
-        def, substs
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for interpret::GlobalId<'a> {
-        type Lifted = interpret::GlobalId<'tcx>;
-        instance, promoted
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 //
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 535d0e9584e..fa22709d66f 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)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub struct TypeAndMut<'tcx> {
     pub ty: Ty<'tcx>,
     pub mutbl: hir::Mutability,
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 82216e8c73d..a8a17fe9d7d 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -731,7 +731,7 @@ 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)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub struct UserSubsts<'tcx> {
     /// The substitutions for the item as given by the user.
     pub substs: SubstsRef<'tcx>,
@@ -741,14 +741,6 @@ pub struct UserSubsts<'tcx> {
     pub user_self_ty: Option<UserSelfTy<'tcx>>,
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for UserSubsts<'a> {
-        type Lifted = UserSubsts<'tcx>;
-        substs,
-        user_self_ty,
-    }
-}
-
 /// Specifies the user-given self type. In the case of a path that
 /// refers to a member in an inherent impl, this self type is
 /// sometimes needed to constrain the type parameters on the impl. For
@@ -766,16 +758,8 @@ BraceStructLiftImpl! {
 /// 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)]
-#[derive(HashStable, TypeFoldable)]
+#[derive(HashStable, TypeFoldable, Lift)]
 pub struct UserSelfTy<'tcx> {
     pub impl_def_id: DefId,
     pub self_ty: Ty<'tcx>,
 }
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for UserSelfTy<'a> {
-        type Lifted = UserSelfTy<'tcx>;
-        impl_def_id,
-        self_ty,
-    }
-}
diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs
index 351d60b9368..dce3820d284 100644
--- a/src/librustc_macros/src/lib.rs
+++ b/src/librustc_macros/src/lib.rs
@@ -10,6 +10,7 @@ use proc_macro::TokenStream;
 
 mod hash_stable;
 mod type_foldable;
+mod lift;
 mod query;
 mod symbols;
 
@@ -25,3 +26,4 @@ pub fn symbols(input: TokenStream) -> TokenStream {
 
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
 decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
+decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
diff --git a/src/librustc_macros/src/lift.rs b/src/librustc_macros/src/lift.rs
new file mode 100644
index 00000000000..23f30bcad2b
--- /dev/null
+++ b/src/librustc_macros/src/lift.rs
@@ -0,0 +1,50 @@
+use synstructure;
+use syn::{self, parse_quote};
+use proc_macro2;
+use quote::quote;
+
+pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    let tcx: syn::Lifetime = parse_quote!('tcx);
+    let newtcx: syn::GenericParam = parse_quote!('__lifted);
+
+    let lifted = {
+        let ast = s.ast();
+        let ident = &ast.ident;
+
+        // Replace `'tcx` lifetime by the `'__lifted` lifetime
+        let (_, generics, _) = ast.generics.split_for_impl();
+        let mut generics : syn::AngleBracketedGenericArguments = syn::parse_quote!{ #generics };
+        for arg in generics.args.iter_mut() {
+            match arg {
+                syn::GenericArgument::Lifetime(l) if *l == tcx => {
+                    *arg = parse_quote!('__lifted);
+                },
+                syn::GenericArgument::Type(t) => {
+                    *arg = syn::parse_quote!{ #t::Lifted };
+                },
+                _ => {},
+            }
+        }
+
+        quote!{ #ident #generics }
+    };
+
+    let body = s.each_variant(|vi| {
+        let bindings = &vi.bindings();
+        vi.construct(|_, index| {
+            let bi = &bindings[index];
+            quote!{ __tcx.lift(#bi)?  }
+        })
+    });
+
+    s.add_impl_generic(newtcx);
+    s.bound_impl(quote!(::rustc::ty::Lift<'__lifted>), quote!{
+        type Lifted = #lifted;
+
+        fn lift_to_tcx(&self, __tcx: ::rustc::ty::TyCtxt<'__lifted>) -> Option<#lifted> {
+            Some(match *self { #body })
+        }
+    })
+}
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index e3ea2748737..b0dcdc7486e 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -38,7 +38,7 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::{GenericArg, GenericArgKind};
 use syntax_pos::DUMMY_SP;
-use rustc_macros::TypeFoldable;
+use rustc_macros::{TypeFoldable, Lift};
 
 use std::fmt::{self, Debug};
 use std::marker::PhantomData;
@@ -66,7 +66,7 @@ crate struct UniverseMap;
 
 crate type RegionConstraint<'tcx> = ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>;
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, Lift)]
 crate struct ConstrainedSubst<'tcx> {
     subst: CanonicalVarValues<'tcx>,
     constraints: Vec<RegionConstraint<'tcx>>,
@@ -581,14 +581,6 @@ impl ExClauseFold<'tcx> for ChalkArenas<'tcx> {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ConstrainedSubst<'a> {
-        type Lifted = ConstrainedSubst<'tcx>;
-
-        subst, constraints
-    }
-}
-
 trait Upcast<'tcx>: 'tcx {
     type Upcasted: 'tcx;