]> git.lizzy.rs Git - rust.git/commitdiff
Split traits::structural_impls in two.
authorCamille GILLOT <gillot.camille@gmail.com>
Wed, 22 Jan 2020 12:42:04 +0000 (13:42 +0100)
committerCamille GILLOT <gillot.camille@gmail.com>
Wed, 5 Feb 2020 11:40:47 +0000 (12:40 +0100)
src/librustc/traits/structural_impls.rs
src/librustc/traits/types/mod.rs
src/librustc/traits/types/structural_impls.rs [new file with mode: 0644]

index 1db83c5bafac9e411ad84f44b857afb7c5b9f128..80731c7b1892fe3d82b79cd4eb0db9d8fea67378 100644 (file)
@@ -1,13 +1,9 @@
 use crate::traits;
 use crate::traits::project::Normalized;
+use crate::ty;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::{self, Lift, Ty, TyCtxt};
-use rustc_span::symbol::Symbol;
-use smallvec::SmallVec;
 
-use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
-use std::rc::Rc;
 
 // Structural impls for the structs in `traits`.
 
@@ -31,102 +27,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            super::VtableImpl(ref v) => write!(f, "{:?}", v),
-
-            super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
-
-            super::VtableClosure(ref d) => write!(f, "{:?}", d),
-
-            super::VtableGenerator(ref d) => write!(f, "{:?}", d),
-
-            super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
-
-            super::VtableObject(ref d) => write!(f, "{:?}", d),
-
-            super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
-
-            super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
-
-            super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
-        }
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
-            self.impl_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
-            self.generator_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
-            self.closure_def_id, self.substs, self.nested
-        )
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "VtableBuiltinData(nested={:?})", self.nested)
-    }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
-            self.trait_def_id, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
-            self.upcast_trait_ref, self.vtable_base, self.nested
-        )
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
-    }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
-            self.alias_def_id, self.substs, self.nested
-        )
-    }
-}
-
 impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
@@ -152,531 +52,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::WhereClause::*;
-
-        // Bypass `ty::print` because it does not print out anonymous regions.
-        // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
-        fn write_region_name<'tcx>(
-            r: ty::Region<'tcx>,
-            fmt: &mut fmt::Formatter<'_>,
-        ) -> fmt::Result {
-            match r {
-                ty::ReLateBound(index, br) => match br {
-                    ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
-                    ty::BoundRegion::BrAnon(var) => {
-                        if *index == ty::INNERMOST {
-                            write!(fmt, "'^{}", var)
-                        } else {
-                            write!(fmt, "'^{}_{}", index.index(), var)
-                        }
-                    }
-                    _ => write!(fmt, "'_"),
-                },
-
-                _ => write!(fmt, "{}", r),
-            }
-        }
-
-        match self {
-            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
-            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
-            RegionOutlives(predicate) => {
-                write!(fmt, "RegionOutlives({}: ", predicate.0)?;
-                write_region_name(predicate.1, fmt)?;
-                write!(fmt, ")")
-            }
-            TypeOutlives(predicate) => {
-                write!(fmt, "TypeOutlives({}: ", predicate.0)?;
-                write_region_name(predicate.1, fmt)?;
-                write!(fmt, ")")
-            }
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::WellFormed::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
-            Ty(ty) => write!(fmt, "WellFormed({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::FromEnv::*;
-
-        match self {
-            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
-            Ty(ty) => write!(fmt, "FromEnv({})", ty),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::DomainGoal::*;
-
-        match self {
-            Holds(wc) => write!(fmt, "{}", wc),
-            WellFormed(wf) => write!(fmt, "{}", wf),
-            FromEnv(from_env) => write!(fmt, "{}", from_env),
-            Normalize(projection) => {
-                write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
-            }
-        }
-    }
-}
-
-impl fmt::Display for traits::QuantifierKind {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::QuantifierKind::*;
-
-        match self {
-            Universal => write!(fmt, "forall"),
-            Existential => write!(fmt, "exists"),
-        }
-    }
-}
-
-/// Collect names for regions / types bound by a quantified goal / clause.
-/// This collector does not try to do anything clever like in `ty::print`, it's just used
-/// for debug output in tests anyway.
-struct BoundNamesCollector {
-    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
-    regions: BTreeSet<Symbol>,
-
-    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
-    // by the list of type parameters.
-    types: BTreeMap<u32, Symbol>,
-
-    binder_index: ty::DebruijnIndex,
-}
-
-impl BoundNamesCollector {
-    fn new() -> Self {
-        BoundNamesCollector {
-            regions: BTreeSet::new(),
-            types: BTreeMap::new(),
-            binder_index: ty::INNERMOST,
-        }
-    }
-
-    fn is_empty(&self) -> bool {
-        self.regions.is_empty() && self.types.is_empty()
-    }
-
-    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut start = true;
-        for r in &self.regions {
-            if !start {
-                write!(fmt, ", ")?;
-            }
-            start = false;
-            write!(fmt, "{}", r)?;
-        }
-        for (_, t) in &self.types {
-            if !start {
-                write!(fmt, ", ")?;
-            }
-            start = false;
-            write!(fmt, "{}", t)?;
-        }
-        Ok(())
-    }
-}
-
-impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
-    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-        match t.kind {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                self.types.insert(
-                    bound_ty.var.as_u32(),
-                    match bound_ty.kind {
-                        ty::BoundTyKind::Param(name) => name,
-                        ty::BoundTyKind::Anon => {
-                            Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
-                        }
-                    },
-                );
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        match r {
-            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
-                ty::BoundRegion::BrNamed(_, name) => {
-                    self.regions.insert(*name);
-                }
-
-                ty::BoundRegion::BrAnon(var) => {
-                    self.regions.insert(Symbol::intern(&format!("'^{}", var)));
-                }
-
-                _ => (),
-            },
-
-            _ => (),
-        };
-
-        r.super_visit_with(self)
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Goal<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::GoalKind::*;
-
-        match self {
-            Implies(hypotheses, goal) => {
-                write!(fmt, "if (")?;
-                for (index, hyp) in hypotheses.iter().enumerate() {
-                    if index > 0 {
-                        write!(fmt, ", ")?;
-                    }
-                    write!(fmt, "{}", hyp)?;
-                }
-                write!(fmt, ") {{ {} }}", goal)
-            }
-            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
-            Not(goal) => write!(fmt, "not {{ {} }}", goal),
-            DomainGoal(goal) => write!(fmt, "{}", goal),
-            Quantified(qkind, goal) => {
-                let mut collector = BoundNamesCollector::new();
-                goal.skip_binder().visit_with(&mut collector);
-
-                if !collector.is_empty() {
-                    write!(fmt, "{}<", qkind)?;
-                    collector.write_names(fmt)?;
-                    write!(fmt, "> {{ ")?;
-                }
-
-                write!(fmt, "{}", goal.skip_binder())?;
-
-                if !collector.is_empty() {
-                    write!(fmt, " }}")?;
-                }
-
-                Ok(())
-            }
-            Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
-            CannotProve => write!(fmt, "CannotProve"),
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let traits::ProgramClause { goal, hypotheses, .. } = self;
-        write!(fmt, "{}", goal)?;
-        if !hypotheses.is_empty() {
-            write!(fmt, " :- ")?;
-            for (index, condition) in hypotheses.iter().enumerate() {
-                if index > 0 {
-                    write!(fmt, ", ")?;
-                }
-                write!(fmt, "{}", condition)?;
-            }
-        }
-        write!(fmt, ".")
-    }
-}
-
-impl<'tcx> fmt::Display for traits::Clause<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use crate::traits::Clause::*;
-
-        match self {
-            Implies(clause) => write!(fmt, "{}", clause),
-            ForAll(clause) => {
-                let mut collector = BoundNamesCollector::new();
-                clause.skip_binder().visit_with(&mut collector);
-
-                if !collector.is_empty() {
-                    write!(fmt, "forall<")?;
-                    collector.write_names(fmt)?;
-                    write!(fmt, "> {{ ")?;
-                }
-
-                write!(fmt, "{}", clause.skip_binder())?;
-
-                if !collector.is_empty() {
-                    write!(fmt, " }}")?;
-                }
-
-                Ok(())
-            }
-        }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Lift implementations
-
-impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
-    type Lifted = traits::SelectionError<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            super::Unimplemented => Some(super::Unimplemented),
-            super::OutputTypeParameterMismatch(a, b, ref err) => {
-                tcx.lift(&(a, b)).and_then(|(a, b)| {
-                    tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
-                })
-            }
-            super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
-            super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
-            super::Overflow => Some(super::Overflow),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
-    type Lifted = traits::ObligationCauseCode<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            super::ReturnNoExpression => Some(super::ReturnNoExpression),
-            super::MiscObligation => Some(super::MiscObligation),
-            super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
-            super::TupleElem => Some(super::TupleElem),
-            super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
-            super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
-            super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
-            super::ReferenceOutlivesReferent(ty) => {
-                tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
-            }
-            super::ObjectTypeBound(ty, r) => tcx
-                .lift(&ty)
-                .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
-            super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
-            super::Coercion { source, target } => {
-                Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
-            }
-            super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
-            super::TupleInitializerSized => Some(super::TupleInitializerSized),
-            super::StructInitializerSized => Some(super::StructInitializerSized),
-            super::VariableType(id) => Some(super::VariableType(id)),
-            super::ReturnValue(id) => Some(super::ReturnValue(id)),
-            super::ReturnType => Some(super::ReturnType),
-            super::SizedArgumentType => Some(super::SizedArgumentType),
-            super::SizedReturnType => Some(super::SizedReturnType),
-            super::SizedYieldType => Some(super::SizedYieldType),
-            super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
-            super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
-            super::ConstSized => Some(super::ConstSized),
-            super::ConstPatternStructural => Some(super::ConstPatternStructural),
-            super::SharedStatic => Some(super::SharedStatic),
-            super::BuiltinDerivedObligation(ref cause) => {
-                tcx.lift(cause).map(super::BuiltinDerivedObligation)
-            }
-            super::ImplDerivedObligation(ref cause) => {
-                tcx.lift(cause).map(super::ImplDerivedObligation)
-            }
-            super::CompareImplMethodObligation {
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            } => Some(super::CompareImplMethodObligation {
-                item_name,
-                impl_item_def_id,
-                trait_item_def_id,
-            }),
-            super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
-                Some(super::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                })
-            }
-            super::ExprAssignable => Some(super::ExprAssignable),
-            super::MatchExpressionArm(box super::MatchExpressionArmCause {
-                arm_span,
-                source,
-                ref prior_arms,
-                last_ty,
-                scrut_hir_id,
-            }) => tcx.lift(&last_ty).map(|last_ty| {
-                super::MatchExpressionArm(box super::MatchExpressionArmCause {
-                    arm_span,
-                    source,
-                    prior_arms: prior_arms.clone(),
-                    last_ty,
-                    scrut_hir_id,
-                })
-            }),
-            super::Pattern { span, root_ty, origin_expr } => {
-                tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
-            }
-            super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
-                Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
-            }
-            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
-            super::MainFunctionType => Some(super::MainFunctionType),
-            super::StartFunctionType => Some(super::StartFunctionType),
-            super::IntrinsicType => Some(super::IntrinsicType),
-            super::MethodReceiver => Some(super::MethodReceiver),
-            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
-            super::TrivialBound => Some(super::TrivialBound),
-            super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
-        }
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
-    type Lifted = traits::DerivedObligationCause<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
-            tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
-                parent_trait_ref: trait_ref,
-                parent_code: Rc::new(code),
-            })
-        })
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
-    type Lifted = traits::ObligationCause<'tcx>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.code).map(|code| traits::ObligationCause {
-            span: self.span,
-            body_id: self.body_id,
-            code,
-        })
-    }
-}
-
-// For codegen only.
-impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
-    type Lifted = traits::Vtable<'tcx, ()>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        match self.clone() {
-            traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
-                tcx.lift(&substs).map(|substs| {
-                    traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
-                })
-            }
-            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
-            traits::VtableGenerator(traits::VtableGeneratorData {
-                generator_def_id,
-                substs,
-                nested,
-            }) => tcx.lift(&substs).map(|substs| {
-                traits::VtableGenerator(traits::VtableGeneratorData {
-                    generator_def_id: generator_def_id,
-                    substs: substs,
-                    nested: nested,
-                })
-            }),
-            traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
-                tcx.lift(&substs).map(|substs| {
-                    traits::VtableClosure(traits::VtableClosureData {
-                        closure_def_id,
-                        substs,
-                        nested,
-                    })
-                })
-            }
-            traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
-                tcx.lift(&fn_ty).map(|fn_ty| {
-                    traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
-                })
-            }
-            traits::VtableParam(n) => Some(traits::VtableParam(n)),
-            traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
-            traits::VtableObject(traits::VtableObjectData {
-                upcast_trait_ref,
-                vtable_base,
-                nested,
-            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
-                traits::VtableObject(traits::VtableObjectData {
-                    upcast_trait_ref: trait_ref,
-                    vtable_base,
-                    nested,
-                })
-            }),
-            traits::VtableTraitAlias(traits::VtableTraitAliasData {
-                alias_def_id,
-                substs,
-                nested,
-            }) => tcx.lift(&substs).map(|substs| {
-                traits::VtableTraitAlias(traits::VtableTraitAliasData {
-                    alias_def_id,
-                    substs,
-                    nested,
-                })
-            }),
-        }
-    }
-}
-
-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> {
-        tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
-    }
-}
-
-impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
-    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.environment).and_then(|environment| {
-            tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
-        })
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedExClause;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedDelayedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
-    }
-}
-
-impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
-where
-    C: chalk_engine::context::Context + Clone,
-    C: traits::ChalkContextLift<'tcx>,
-{
-    type Lifted = C::LiftedLiteral;
-
-    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 
@@ -694,80 +69,3 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         self.predicate.visit_with(visitor)
     }
 }
-
-CloneTypeFoldableAndLiftImpls! {
-    traits::QuantifierKind,
-}
-
-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().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
-        folder.tcx().intern_goals(&v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.iter().any(|t| t.visit_with(visitor))
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        let v = (**self).fold_with(folder);
-        folder.tcx().mk_goal(v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        (**self).visit_with(visitor)
-    }
-}
-
-CloneTypeFoldableAndLiftImpls! {
-    traits::ProgramClauseCategory,
-}
-
-impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'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]>>();
-        folder.tcx().intern_clauses(&v)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.iter().any(|t| t.visit_with(visitor))
-    }
-}
-
-impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
-where
-    C: traits::ExClauseFold<'tcx>,
-    C::Substitution: Clone,
-    C::RegionConstraint: Clone,
-{
-    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
-        <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
-    }
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
-        (chalk_engine::DelayedLiteral::CannotProve)(a),
-        (chalk_engine::DelayedLiteral::Negative)(a),
-        (chalk_engine::DelayedLiteral::Positive)(a, b),
-    } where
-        C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
-}
-
-EnumTypeFoldableImpl! {
-    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
-        (chalk_engine::Literal::Negative)(a),
-        (chalk_engine::Literal::Positive)(a),
-    } where
-        C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
-}
-
-CloneTypeFoldableAndLiftImpls! {
-    chalk_engine::TableIndex,
-}
index c795248802672f4e1ffe7642bb79292caad08d1c..b85a9d0193c8a7485f66d4e9fbafe253ff9df627 100644 (file)
@@ -4,6 +4,7 @@
 
 pub mod query;
 pub mod select;
+mod structural_impls;
 
 use crate::mir::interpret::ErrorHandled;
 use crate::ty::fold::{TypeFolder, TypeVisitor};
diff --git a/src/librustc/traits/types/structural_impls.rs b/src/librustc/traits/types/structural_impls.rs
new file mode 100644 (file)
index 0000000..48ed29f
--- /dev/null
@@ -0,0 +1,712 @@
+use crate::traits;
+use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::ty::{self, Lift, Ty, TyCtxt};
+use rustc_span::symbol::Symbol;
+use smallvec::SmallVec;
+
+use std::collections::{BTreeMap, BTreeSet};
+use std::fmt;
+use std::rc::Rc;
+
+// Structural impls for the structs in `traits`.
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            super::VtableImpl(ref v) => write!(f, "{:?}", v),
+
+            super::VtableAutoImpl(ref t) => write!(f, "{:?}", t),
+
+            super::VtableClosure(ref d) => write!(f, "{:?}", d),
+
+            super::VtableGenerator(ref d) => write!(f, "{:?}", d),
+
+            super::VtableFnPointer(ref d) => write!(f, "VtableFnPointer({:?})", d),
+
+            super::VtableObject(ref d) => write!(f, "{:?}", d),
+
+            super::VtableParam(ref n) => write!(f, "VtableParam({:?})", n),
+
+            super::VtableBuiltin(ref d) => write!(f, "{:?}", d),
+
+            super::VtableTraitAlias(ref d) => write!(f, "{:?}", d),
+        }
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableImplData(impl_def_id={:?}, substs={:?}, nested={:?})",
+            self.impl_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
+            self.generator_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableClosureData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
+            self.closure_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "VtableBuiltinData(nested={:?})", self.nested)
+    }
+}
+
+impl<N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
+            self.trait_def_id, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableObjectData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableObjectData(upcast={:?}, vtable_base={}, nested={:?})",
+            self.upcast_trait_ref, self.vtable_base, self.nested
+        )
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableFnPointerData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "VtableFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
+    }
+}
+
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableTraitAliasData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "VtableTraitAlias(alias_def_id={:?}, substs={:?}, nested={:?})",
+            self.alias_def_id, self.substs, self.nested
+        )
+    }
+}
+
+impl<'tcx> fmt::Display for traits::WhereClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::WhereClause::*;
+
+        // Bypass `ty::print` because it does not print out anonymous regions.
+        // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`.
+        fn write_region_name<'tcx>(
+            r: ty::Region<'tcx>,
+            fmt: &mut fmt::Formatter<'_>,
+        ) -> fmt::Result {
+            match r {
+                ty::ReLateBound(index, br) => match br {
+                    ty::BoundRegion::BrNamed(_, name) => write!(fmt, "{}", name),
+                    ty::BoundRegion::BrAnon(var) => {
+                        if *index == ty::INNERMOST {
+                            write!(fmt, "'^{}", var)
+                        } else {
+                            write!(fmt, "'^{}_{}", index.index(), var)
+                        }
+                    }
+                    _ => write!(fmt, "'_"),
+                },
+
+                _ => write!(fmt, "{}", r),
+            }
+        }
+
+        match self {
+            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+            RegionOutlives(predicate) => {
+                write!(fmt, "RegionOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+            TypeOutlives(predicate) => {
+                write!(fmt, "TypeOutlives({}: ", predicate.0)?;
+                write_region_name(predicate.1, fmt)?;
+                write!(fmt, ")")
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::WellFormed<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::WellFormed::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "WellFormed({})", trait_ref),
+            Ty(ty) => write!(fmt, "WellFormed({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::FromEnv<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::FromEnv::*;
+
+        match self {
+            Trait(trait_ref) => write!(fmt, "FromEnv({})", trait_ref),
+            Ty(ty) => write!(fmt, "FromEnv({})", ty),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::DomainGoal::*;
+
+        match self {
+            Holds(wc) => write!(fmt, "{}", wc),
+            WellFormed(wf) => write!(fmt, "{}", wf),
+            FromEnv(from_env) => write!(fmt, "{}", from_env),
+            Normalize(projection) => {
+                write!(fmt, "Normalize({} -> {})", projection.projection_ty, projection.ty)
+            }
+        }
+    }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::QuantifierKind::*;
+
+        match self {
+            Universal => write!(fmt, "forall"),
+            Existential => write!(fmt, "exists"),
+        }
+    }
+}
+
+/// Collect names for regions / types bound by a quantified goal / clause.
+/// This collector does not try to do anything clever like in `ty::print`, it's just used
+/// for debug output in tests anyway.
+struct BoundNamesCollector {
+    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
+    regions: BTreeSet<Symbol>,
+
+    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
+    // by the list of type parameters.
+    types: BTreeMap<u32, Symbol>,
+
+    binder_index: ty::DebruijnIndex,
+}
+
+impl BoundNamesCollector {
+    fn new() -> Self {
+        BoundNamesCollector {
+            regions: BTreeSet::new(),
+            types: BTreeMap::new(),
+            binder_index: ty::INNERMOST,
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.regions.is_empty() && self.types.is_empty()
+    }
+
+    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut start = true;
+        for r in &self.regions {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", r)?;
+        }
+        for (_, t) in &self.types {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", t)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
+    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+        match t.kind {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
+                self.types.insert(
+                    bound_ty.var.as_u32(),
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Param(name) => name,
+                        ty::BoundTyKind::Anon => {
+                            Symbol::intern(&format!("^{}", bound_ty.var.as_u32()))
+                        }
+                    },
+                );
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
+                ty::BoundRegion::BrNamed(_, name) => {
+                    self.regions.insert(*name);
+                }
+
+                ty::BoundRegion::BrAnon(var) => {
+                    self.regions.insert(Symbol::intern(&format!("'^{}", var)));
+                }
+
+                _ => (),
+            },
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::GoalKind::*;
+
+        match self {
+            Implies(hypotheses, goal) => {
+                write!(fmt, "if (")?;
+                for (index, hyp) in hypotheses.iter().enumerate() {
+                    if index > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{}", hyp)?;
+                }
+                write!(fmt, ") {{ {} }}", goal)
+            }
+            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+            Not(goal) => write!(fmt, "not {{ {} }}", goal),
+            DomainGoal(goal) => write!(fmt, "{}", goal),
+            Quantified(qkind, goal) => {
+                let mut collector = BoundNamesCollector::new();
+                goal.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "{}<", qkind)?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", goal.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+            Subtype(a, b) => write!(fmt, "{} <: {}", a, b),
+            CannotProve => write!(fmt, "CannotProve"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let traits::ProgramClause { goal, hypotheses, .. } = self;
+        write!(fmt, "{}", goal)?;
+        if !hypotheses.is_empty() {
+            write!(fmt, " :- ")?;
+            for (index, condition) in hypotheses.iter().enumerate() {
+                if index > 0 {
+                    write!(fmt, ", ")?;
+                }
+                write!(fmt, "{}", condition)?;
+            }
+        }
+        write!(fmt, ".")
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use crate::traits::Clause::*;
+
+        match self {
+            Implies(clause) => write!(fmt, "{}", clause),
+            ForAll(clause) => {
+                let mut collector = BoundNamesCollector::new();
+                clause.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "forall<")?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", clause.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
+            }
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Lift implementations
+
+impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
+    type Lifted = traits::SelectionError<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            super::Unimplemented => Some(super::Unimplemented),
+            super::OutputTypeParameterMismatch(a, b, ref err) => {
+                tcx.lift(&(a, b)).and_then(|(a, b)| {
+                    tcx.lift(err).map(|err| super::OutputTypeParameterMismatch(a, b, err))
+                })
+            }
+            super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
+            super::ConstEvalFailure(err) => Some(super::ConstEvalFailure(err)),
+            super::Overflow => Some(super::Overflow),
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
+    type Lifted = traits::ObligationCauseCode<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            super::ReturnNoExpression => Some(super::ReturnNoExpression),
+            super::MiscObligation => Some(super::MiscObligation),
+            super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
+            super::TupleElem => Some(super::TupleElem),
+            super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
+            super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
+            super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
+            super::ReferenceOutlivesReferent(ty) => {
+                tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
+            }
+            super::ObjectTypeBound(ty, r) => tcx
+                .lift(&ty)
+                .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))),
+            super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
+            super::Coercion { source, target } => {
+                Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? })
+            }
+            super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
+            super::TupleInitializerSized => Some(super::TupleInitializerSized),
+            super::StructInitializerSized => Some(super::StructInitializerSized),
+            super::VariableType(id) => Some(super::VariableType(id)),
+            super::ReturnValue(id) => Some(super::ReturnValue(id)),
+            super::ReturnType => Some(super::ReturnType),
+            super::SizedArgumentType => Some(super::SizedArgumentType),
+            super::SizedReturnType => Some(super::SizedReturnType),
+            super::SizedYieldType => Some(super::SizedYieldType),
+            super::RepeatVec(suggest_flag) => Some(super::RepeatVec(suggest_flag)),
+            super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
+            super::ConstSized => Some(super::ConstSized),
+            super::ConstPatternStructural => Some(super::ConstPatternStructural),
+            super::SharedStatic => Some(super::SharedStatic),
+            super::BuiltinDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::BuiltinDerivedObligation)
+            }
+            super::ImplDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::ImplDerivedObligation)
+            }
+            super::CompareImplMethodObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => Some(super::CompareImplMethodObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            }),
+            super::CompareImplTypeObligation { item_name, impl_item_def_id, trait_item_def_id } => {
+                Some(super::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                })
+            }
+            super::ExprAssignable => Some(super::ExprAssignable),
+            super::MatchExpressionArm(box super::MatchExpressionArmCause {
+                arm_span,
+                source,
+                ref prior_arms,
+                last_ty,
+                scrut_hir_id,
+            }) => tcx.lift(&last_ty).map(|last_ty| {
+                super::MatchExpressionArm(box super::MatchExpressionArmCause {
+                    arm_span,
+                    source,
+                    prior_arms: prior_arms.clone(),
+                    last_ty,
+                    scrut_hir_id,
+                })
+            }),
+            super::Pattern { span, root_ty, origin_expr } => {
+                tcx.lift(&root_ty).map(|root_ty| super::Pattern { span, root_ty, origin_expr })
+            }
+            super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
+                Some(super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }))
+            }
+            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
+            super::MainFunctionType => Some(super::MainFunctionType),
+            super::StartFunctionType => Some(super::StartFunctionType),
+            super::IntrinsicType => Some(super::IntrinsicType),
+            super::MethodReceiver => Some(super::MethodReceiver),
+            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
+            super::TrivialBound => Some(super::TrivialBound),
+            super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())),
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
+    type Lifted = traits::DerivedObligationCause<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
+            tcx.lift(&*self.parent_code).map(|code| traits::DerivedObligationCause {
+                parent_trait_ref: trait_ref,
+                parent_code: Rc::new(code),
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
+    type Lifted = traits::ObligationCause<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.code).map(|code| traits::ObligationCause {
+            span: self.span,
+            body_id: self.body_id,
+            code,
+        })
+    }
+}
+
+// For codegen only.
+impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
+    type Lifted = traits::Vtable<'tcx, ()>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        match self.clone() {
+            traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested }) => {
+                tcx.lift(&substs).map(|substs| {
+                    traits::VtableImpl(traits::VtableImplData { impl_def_id, substs, nested })
+                })
+            }
+            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
+            traits::VtableGenerator(traits::VtableGeneratorData {
+                generator_def_id,
+                substs,
+                nested,
+            }) => tcx.lift(&substs).map(|substs| {
+                traits::VtableGenerator(traits::VtableGeneratorData {
+                    generator_def_id: generator_def_id,
+                    substs: substs,
+                    nested: nested,
+                })
+            }),
+            traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => {
+                tcx.lift(&substs).map(|substs| {
+                    traits::VtableClosure(traits::VtableClosureData {
+                        closure_def_id,
+                        substs,
+                        nested,
+                    })
+                })
+            }
+            traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
+                tcx.lift(&fn_ty).map(|fn_ty| {
+                    traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
+                })
+            }
+            traits::VtableParam(n) => Some(traits::VtableParam(n)),
+            traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
+            traits::VtableObject(traits::VtableObjectData {
+                upcast_trait_ref,
+                vtable_base,
+                nested,
+            }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
+                traits::VtableObject(traits::VtableObjectData {
+                    upcast_trait_ref: trait_ref,
+                    vtable_base,
+                    nested,
+                })
+            }),
+            traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                alias_def_id,
+                substs,
+                nested,
+            }) => tcx.lift(&substs).map(|substs| {
+                traits::VtableTraitAlias(traits::VtableTraitAliasData {
+                    alias_def_id,
+                    substs,
+                    nested,
+                })
+            }),
+        }
+    }
+}
+
+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> {
+        tcx.lift(&self.clauses).map(|clauses| traits::Environment { clauses })
+    }
+}
+
+impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
+    type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.environment).and_then(|environment| {
+            tcx.lift(&self.goal).map(|goal| traits::InEnvironment { environment, goal })
+        })
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedExClause;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx)
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedDelayedLiteral;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx)
+    }
+}
+
+impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C>
+where
+    C: chalk_engine::context::Context + Clone,
+    C: traits::ChalkContextLift<'tcx>,
+{
+    type Lifted = C::LiftedLiteral;
+
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx)
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// TypeFoldable implementations.
+
+CloneTypeFoldableAndLiftImpls! {
+    traits::QuantifierKind,
+}
+
+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().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
+        folder.tcx().intern_goals(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        let v = (**self).fold_with(folder);
+        folder.tcx().mk_goal(v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        (**self).visit_with(visitor)
+    }
+}
+
+CloneTypeFoldableAndLiftImpls! {
+    traits::ProgramClauseCategory,
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'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]>>();
+        folder.tcx().intern_clauses(&v)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
+
+impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C>
+where
+    C: traits::ExClauseFold<'tcx>,
+    C::Substitution: Clone,
+    C::RegionConstraint: Clone,
+{
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor)
+    }
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> {
+        (chalk_engine::DelayedLiteral::CannotProve)(a),
+        (chalk_engine::DelayedLiteral::Negative)(a),
+        (chalk_engine::DelayedLiteral::Positive)(a, b),
+    } where
+        C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone,
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> {
+        (chalk_engine::Literal::Negative)(a),
+        (chalk_engine::Literal::Positive)(a),
+    } where
+        C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone,
+}
+
+CloneTypeFoldableAndLiftImpls! {
+    chalk_engine::TableIndex,
+}