about summary refs log tree commit diff
path: root/src/librustc_infer/traits
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_infer/traits')
-rw-r--r--src/librustc_infer/traits/auto_trait.rs837
-rw-r--r--src/librustc_infer/traits/codegen/mod.rs110
-rw-r--r--src/librustc_infer/traits/coherence.rs540
-rw-r--r--src/librustc_infer/traits/engine.rs10
-rw-r--r--src/librustc_infer/traits/error_reporting/mod.rs1555
-rw-r--r--src/librustc_infer/traits/error_reporting/on_unimplemented.rs223
-rw-r--r--src/librustc_infer/traits/error_reporting/suggestions.rs1707
-rw-r--r--src/librustc_infer/traits/fulfill.rs556
-rw-r--r--src/librustc_infer/traits/misc.rs71
-rw-r--r--src/librustc_infer/traits/mod.rs530
-rw-r--r--src/librustc_infer/traits/object_safety.rs777
-rw-r--r--src/librustc_infer/traits/on_unimplemented.rs383
-rw-r--r--src/librustc_infer/traits/project.rs1509
-rw-r--r--src/librustc_infer/traits/query/dropck_outlives.rs137
-rw-r--r--src/librustc_infer/traits/query/evaluate_obligation.rs75
-rw-r--r--src/librustc_infer/traits/query/method_autoderef.rs1
-rw-r--r--src/librustc_infer/traits/query/mod.rs15
-rw-r--r--src/librustc_infer/traits/query/normalize.rs189
-rw-r--r--src/librustc_infer/traits/query/outlives_bounds.rs103
-rw-r--r--src/librustc_infer/traits/query/type_op/ascribe_user_type.rs23
-rw-r--r--src/librustc_infer/traits/query/type_op/custom.rs106
-rw-r--r--src/librustc_infer/traits/query/type_op/eq.rs23
-rw-r--r--src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs41
-rw-r--r--src/librustc_infer/traits/query/type_op/mod.rs136
-rw-r--r--src/librustc_infer/traits/query/type_op/normalize.rs68
-rw-r--r--src/librustc_infer/traits/query/type_op/outlives.rs55
-rw-r--r--src/librustc_infer/traits/query/type_op/prove_predicate.rs37
-rw-r--r--src/librustc_infer/traits/query/type_op/subtype.rs20
-rw-r--r--src/librustc_infer/traits/select.rs3823
-rw-r--r--src/librustc_infer/traits/specialize/mod.rs472
-rw-r--r--src/librustc_infer/traits/specialize/specialization_graph.rs379
-rw-r--r--src/librustc_infer/traits/structural_impls.rs4
-rw-r--r--src/librustc_infer/traits/structural_match.rs216
-rw-r--r--src/librustc_infer/traits/util.rs388
-rw-r--r--src/librustc_infer/traits/wf.rs753
35 files changed, 44 insertions, 15828 deletions
diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs
deleted file mode 100644
index 1a4f899ac85..00000000000
--- a/src/librustc_infer/traits/auto_trait.rs
+++ /dev/null
@@ -1,837 +0,0 @@
-//! Support code for rustdoc and external tools.
-//! You really don't want to be using this unless you need to.
-
-use super::*;
-
-use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::infer::InferCtxt;
-use rustc::ty::fold::TypeFolder;
-use rustc::ty::{Region, RegionVid};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
-use std::collections::hash_map::Entry;
-use std::collections::VecDeque;
-
-// FIXME(twk): this is obviously not nice to duplicate like that
-#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
-pub enum RegionTarget<'tcx> {
-    Region(Region<'tcx>),
-    RegionVid(RegionVid),
-}
-
-#[derive(Default, Debug, Clone)]
-pub struct RegionDeps<'tcx> {
-    larger: FxHashSet<RegionTarget<'tcx>>,
-    smaller: FxHashSet<RegionTarget<'tcx>>,
-}
-
-pub enum AutoTraitResult<A> {
-    ExplicitImpl,
-    PositiveImpl(A),
-    NegativeImpl,
-}
-
-impl<A> AutoTraitResult<A> {
-    fn is_auto(&self) -> bool {
-        match *self {
-            AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
-            _ => false,
-        }
-    }
-}
-
-pub struct AutoTraitInfo<'cx> {
-    pub full_user_env: ty::ParamEnv<'cx>,
-    pub region_data: RegionConstraintData<'cx>,
-    pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
-}
-
-pub struct AutoTraitFinder<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> AutoTraitFinder<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
-        AutoTraitFinder { tcx }
-    }
-
-    /// Makes a best effort to determine whether and under which conditions an auto trait is
-    /// implemented for a type. For example, if you have
-    ///
-    /// ```
-    /// struct Foo<T> { data: Box<T> }
-    /// ```
-    ///
-    /// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
-    /// The analysis attempts to account for custom impls as well as other complex cases. This
-    /// result is intended for use by rustdoc and other such consumers.
-    ///
-    /// (Note that due to the coinductive nature of Send, the full and correct result is actually
-    /// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
-    /// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
-    /// But this is often not the best way to present to the user.)
-    ///
-    /// Warning: The API should be considered highly unstable, and it may be refactored or removed
-    /// in the future.
-    pub fn find_auto_trait_generics<A>(
-        &self,
-        ty: Ty<'tcx>,
-        orig_env: ty::ParamEnv<'tcx>,
-        trait_did: DefId,
-        auto_trait_callback: impl Fn(&InferCtxt<'_, 'tcx>, AutoTraitInfo<'tcx>) -> A,
-    ) -> AutoTraitResult<A> {
-        let tcx = self.tcx;
-
-        let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
-
-        let trait_pred = ty::Binder::bind(trait_ref);
-
-        let bail_out = tcx.infer_ctxt().enter(|infcx| {
-            let mut selcx = SelectionContext::with_negative(&infcx, true);
-            let result = selcx.select(&Obligation::new(
-                ObligationCause::dummy(),
-                orig_env,
-                trait_pred.to_poly_trait_predicate(),
-            ));
-
-            match result {
-                Ok(Some(Vtable::VtableImpl(_))) => {
-                    debug!(
-                        "find_auto_trait_generics({:?}): \
-                         manual impl found, bailing out",
-                        trait_ref
-                    );
-                    true
-                }
-                _ => false,
-            }
-        });
-
-        // If an explicit impl exists, it always takes priority over an auto impl
-        if bail_out {
-            return AutoTraitResult::ExplicitImpl;
-        }
-
-        return tcx.infer_ctxt().enter(|mut infcx| {
-            let mut fresh_preds = FxHashSet::default();
-
-            // Due to the way projections are handled by SelectionContext, we need to run
-            // evaluate_predicates twice: once on the original param env, and once on the result of
-            // the first evaluate_predicates call.
-            //
-            // The problem is this: most of rustc, including SelectionContext and traits::project,
-            // are designed to work with a concrete usage of a type (e.g., Vec<u8>
-            // fn<T>() { Vec<T> }. This information will generally never change - given
-            // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
-            // If we're unable to prove that 'T' implements a particular trait, we're done -
-            // there's nothing left to do but error out.
-            //
-            // However, synthesizing an auto trait impl works differently. Here, we start out with
-            // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
-            // with - and progressively discover the conditions we need to fulfill for it to
-            // implement a certain auto trait. This ends up breaking two assumptions made by trait
-            // selection and projection:
-            //
-            // * We can always cache the result of a particular trait selection for the lifetime of
-            // an InfCtxt
-            // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
-            // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
-            //
-            // We fix the first assumption by manually clearing out all of the InferCtxt's caches
-            // in between calls to SelectionContext.select. This allows us to keep all of the
-            // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
-            // them between calls.
-            //
-            // We fix the second assumption by reprocessing the result of our first call to
-            // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
-            // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
-            // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
-            // SelectionContext to return it back to us.
-
-            let (new_env, user_env) = match self.evaluate_predicates(
-                &mut infcx,
-                trait_did,
-                ty,
-                orig_env,
-                orig_env,
-                &mut fresh_preds,
-                false,
-            ) {
-                Some(e) => e,
-                None => return AutoTraitResult::NegativeImpl,
-            };
-
-            let (full_env, full_user_env) = self
-                .evaluate_predicates(
-                    &mut infcx,
-                    trait_did,
-                    ty,
-                    new_env,
-                    user_env,
-                    &mut fresh_preds,
-                    true,
-                )
-                .unwrap_or_else(|| {
-                    panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
-                });
-
-            debug!(
-                "find_auto_trait_generics({:?}): fulfilling \
-                 with {:?}",
-                trait_ref, full_env
-            );
-            infcx.clear_caches();
-
-            // At this point, we already have all of the bounds we need. FulfillmentContext is used
-            // to store all of the necessary region/lifetime bounds in the InferContext, as well as
-            // an additional sanity check.
-            let mut fulfill = FulfillmentContext::new();
-            fulfill.register_bound(
-                &infcx,
-                full_env,
-                ty,
-                trait_did,
-                ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID),
-            );
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, e)
-            });
-
-            let body_id_map: FxHashMap<_, _> = infcx
-                .inner
-                .borrow()
-                .region_obligations
-                .iter()
-                .map(|&(id, _)| (id, vec![]))
-                .collect();
-
-            infcx.process_registered_region_obligations(&body_id_map, None, full_env);
-
-            let region_data = infcx
-                .inner
-                .borrow_mut()
-                .unwrap_region_constraints()
-                .region_constraint_data()
-                .clone();
-
-            let vid_to_region = self.map_vid_to_region(&region_data);
-
-            let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
-
-            return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info));
-        });
-    }
-}
-
-impl AutoTraitFinder<'tcx> {
-    /// The core logic responsible for computing the bounds for our synthesized impl.
-    ///
-    /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
-    /// `FulfillmentContext`, we recursively select the nested obligations of predicates we
-    /// encounter. However, whenever we encounter an `UnimplementedError` involving a type
-    /// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
-    /// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
-    ///
-    /// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
-    /// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
-    /// user code. According, it considers all possible ways that a `Predicate` could be met, which
-    /// isn't always what we want for a synthesized impl. For example, given the predicate `T:
-    /// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
-    /// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
-    /// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
-    /// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
-    /// like this:
-    ///
-    ///     impl<T> Send for Foo<T> where T: IntoIterator
-    ///
-    /// While it might be technically true that Foo implements Send where `T: IntoIterator`,
-    /// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
-    ///
-    /// For this reason, `evaluate_predicates` handles predicates with type variables specially.
-    /// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
-    /// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
-    /// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
-    /// needs to hold.
-    ///
-    /// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
-    /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
-    /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
-    /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
-    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
-    /// else `SelectionContext` will choke on the missing predicates. However, this should never
-    /// show up in the final synthesized generics: we don't want our generated docs page to contain
-    /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
-    /// separate `user_env`, which only holds the predicates that will actually be displayed to the
-    /// user.
-    fn evaluate_predicates(
-        &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        trait_did: DefId,
-        ty: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        user_env: ty::ParamEnv<'tcx>,
-        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        only_projections: bool,
-    ) -> Option<(ty::ParamEnv<'tcx>, ty::ParamEnv<'tcx>)> {
-        let tcx = infcx.tcx;
-
-        let mut select = SelectionContext::with_negative(&infcx, true);
-
-        let mut already_visited = FxHashSet::default();
-        let mut predicates = VecDeque::new();
-        predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
-            trait_ref: ty::TraitRef {
-                def_id: trait_did,
-                substs: infcx.tcx.mk_substs_trait(ty, &[]),
-            },
-        }));
-
-        let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
-        let mut user_computed_preds: FxHashSet<_> =
-            user_env.caller_bounds.iter().cloned().collect();
-
-        let mut new_env = param_env;
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
-
-        while let Some(pred) = predicates.pop_front() {
-            infcx.clear_caches();
-
-            if !already_visited.insert(pred) {
-                continue;
-            }
-
-            // Call `infcx.resolve_vars_if_possible` to see if we can
-            // get rid of any inference variables.
-            let obligation = infcx.resolve_vars_if_possible(&Obligation::new(
-                dummy_cause.clone(),
-                new_env,
-                pred,
-            ));
-            let result = select.select(&obligation);
-
-            match &result {
-                &Ok(Some(ref vtable)) => {
-                    // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
-                    // we immediately bail out, since it's impossible for us to continue.
-                    match vtable {
-                        Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
-                            // Blame 'tidy' for the weird bracket placement.
-                            if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative {
-                                debug!(
-                                    "evaluate_nested_obligations: found explicit negative impl\
-                                        {:?}, bailing out",
-                                    impl_def_id
-                                );
-                                return None;
-                            }
-                        }
-                        _ => {}
-                    }
-
-                    let obligations = vtable.clone().nested_obligations().into_iter();
-
-                    if !self.evaluate_nested_obligations(
-                        ty,
-                        obligations,
-                        &mut user_computed_preds,
-                        fresh_preds,
-                        &mut predicates,
-                        &mut select,
-                        only_projections,
-                    ) {
-                        return None;
-                    }
-                }
-                &Ok(None) => {}
-                &Err(SelectionError::Unimplemented) => {
-                    if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
-                        already_visited.remove(&pred);
-                        self.add_user_pred(
-                            &mut user_computed_preds,
-                            ty::Predicate::Trait(pred, hir::Constness::NotConst),
-                        );
-                        predicates.push_back(pred);
-                    } else {
-                        debug!(
-                            "evaluate_nested_obligations: `Unimplemented` found, bailing: \
-                             {:?} {:?} {:?}",
-                            ty,
-                            pred,
-                            pred.skip_binder().trait_ref.substs
-                        );
-                        return None;
-                    }
-                }
-                _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
-            };
-
-            computed_preds.extend(user_computed_preds.iter().cloned());
-            let normalized_preds =
-                elaborate_predicates(tcx, computed_preds.iter().cloned().collect());
-            new_env =
-                ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
-        }
-
-        let final_user_env = ty::ParamEnv::new(
-            tcx.mk_predicates(user_computed_preds.into_iter()),
-            user_env.reveal,
-            None,
-        );
-        debug!(
-            "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
-             '{:?}'",
-            ty, trait_did, new_env, final_user_env
-        );
-
-        return Some((new_env, final_user_env));
-    }
-
-    /// This method is designed to work around the following issue:
-    /// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
-    /// progressively building a `ParamEnv` based on the results we get.
-    /// However, our usage of `SelectionContext` differs from its normal use within the compiler,
-    /// in that we capture and re-reprocess predicates from `Unimplemented` errors.
-    ///
-    /// This can lead to a corner case when dealing with region parameters.
-    /// During our selection loop in `evaluate_predicates`, we might end up with
-    /// two trait predicates that differ only in their region parameters:
-    /// one containing a HRTB lifetime parameter, and one containing a 'normal'
-    /// lifetime parameter. For example:
-    ///
-    ///     T as MyTrait<'a>
-    ///     T as MyTrait<'static>
-    ///
-    /// If we put both of these predicates in our computed `ParamEnv`, we'll
-    /// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
-    ///
-    /// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
-    /// Our end goal is to generate a user-visible description of the conditions
-    /// under which a type implements an auto trait. A trait predicate involving
-    /// a HRTB means that the type needs to work with any choice of lifetime,
-    /// not just one specific lifetime (e.g., `'static`).
-    fn add_user_pred<'c>(
-        &self,
-        user_computed_preds: &mut FxHashSet<ty::Predicate<'c>>,
-        new_pred: ty::Predicate<'c>,
-    ) {
-        let mut should_add_new = true;
-        user_computed_preds.retain(|&old_pred| {
-            match (&new_pred, old_pred) {
-                (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
-                    if new_trait.def_id() == old_trait.def_id() {
-                        let new_substs = new_trait.skip_binder().trait_ref.substs;
-                        let old_substs = old_trait.skip_binder().trait_ref.substs;
-
-                        if !new_substs.types().eq(old_substs.types()) {
-                            // We can't compare lifetimes if the types are different,
-                            // so skip checking `old_pred`.
-                            return true;
-                        }
-
-                        for (new_region, old_region) in
-                            new_substs.regions().zip(old_substs.regions())
-                        {
-                            match (new_region, old_region) {
-                                // If both predicates have an `ReLateBound` (a HRTB) in the
-                                // same spot, we do nothing.
-                                (
-                                    ty::RegionKind::ReLateBound(_, _),
-                                    ty::RegionKind::ReLateBound(_, _),
-                                ) => {}
-
-                                (ty::RegionKind::ReLateBound(_, _), _)
-                                | (_, ty::RegionKind::ReVar(_)) => {
-                                    // One of these is true:
-                                    // The new predicate has a HRTB in a spot where the old
-                                    // predicate does not (if they both had a HRTB, the previous
-                                    // match arm would have executed). A HRBT is a 'stricter'
-                                    // bound than anything else, so we want to keep the newer
-                                    // predicate (with the HRBT) in place of the old predicate.
-                                    //
-                                    // OR
-                                    //
-                                    // The old predicate has a region variable where the new
-                                    // predicate has some other kind of region. An region
-                                    // variable isn't something we can actually display to a user,
-                                    // so we choose their new predicate (which doesn't have a region
-                                    // varaible).
-                                    //
-                                    // In both cases, we want to remove the old predicate,
-                                    // from `user_computed_preds`, and replace it with the new
-                                    // one. Having both the old and the new
-                                    // predicate in a `ParamEnv` would confuse `SelectionContext`.
-                                    //
-                                    // We're currently in the predicate passed to 'retain',
-                                    // so we return `false` to remove the old predicate from
-                                    // `user_computed_preds`.
-                                    return false;
-                                }
-                                (_, ty::RegionKind::ReLateBound(_, _))
-                                | (ty::RegionKind::ReVar(_), _) => {
-                                    // This is the opposite situation as the previous arm.
-                                    // One of these is true:
-                                    //
-                                    // The old predicate has a HRTB lifetime in a place where the
-                                    // new predicate does not.
-                                    //
-                                    // OR
-                                    //
-                                    // The new predicate has a region variable where the old
-                                    // predicate has some other type of region.
-                                    //
-                                    // We want to leave the old
-                                    // predicate in `user_computed_preds`, and skip adding
-                                    // new_pred to `user_computed_params`.
-                                    should_add_new = false
-                                }
-                                _ => {}
-                            }
-                        }
-                    }
-                }
-                _ => {}
-            }
-            return true;
-        });
-
-        if should_add_new {
-            user_computed_preds.insert(new_pred);
-        }
-    }
-
-    /// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
-    /// to each other, we match `ty::RegionVid`s to `ty::Region`s.
-    fn map_vid_to_region<'cx>(
-        &self,
-        regions: &RegionConstraintData<'cx>,
-    ) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
-        let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
-        let mut finished_map = FxHashMap::default();
-
-        for constraint in regions.constraints.keys() {
-            match constraint {
-                &Constraint::VarSubVar(r1, r2) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
-                        deps1.larger.insert(RegionTarget::RegionVid(r2));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
-                    deps2.smaller.insert(RegionTarget::RegionVid(r1));
-                }
-                &Constraint::RegSubVar(region, vid) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default();
-                        deps1.larger.insert(RegionTarget::RegionVid(vid));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
-                    deps2.smaller.insert(RegionTarget::Region(region));
-                }
-                &Constraint::VarSubReg(vid, region) => {
-                    finished_map.insert(vid, region);
-                }
-                &Constraint::RegSubReg(r1, r2) => {
-                    {
-                        let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default();
-                        deps1.larger.insert(RegionTarget::Region(r2));
-                    }
-
-                    let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default();
-                    deps2.smaller.insert(RegionTarget::Region(r1));
-                }
-            }
-        }
-
-        while !vid_map.is_empty() {
-            let target = *vid_map.keys().next().expect("Keys somehow empty");
-            let deps = vid_map.remove(&target).expect("Entry somehow missing");
-
-            for smaller in deps.smaller.iter() {
-                for larger in deps.larger.iter() {
-                    match (smaller, larger) {
-                        (&RegionTarget::Region(_), &RegionTarget::Region(_)) => {
-                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
-                                let smaller_deps = v.into_mut();
-                                smaller_deps.larger.insert(*larger);
-                                smaller_deps.larger.remove(&target);
-                            }
-
-                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
-                                let larger_deps = v.into_mut();
-                                larger_deps.smaller.insert(*smaller);
-                                larger_deps.smaller.remove(&target);
-                            }
-                        }
-                        (&RegionTarget::RegionVid(v1), &RegionTarget::Region(r1)) => {
-                            finished_map.insert(v1, r1);
-                        }
-                        (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
-                            // Do nothing; we don't care about regions that are smaller than vids.
-                        }
-                        (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
-                            if let Entry::Occupied(v) = vid_map.entry(*smaller) {
-                                let smaller_deps = v.into_mut();
-                                smaller_deps.larger.insert(*larger);
-                                smaller_deps.larger.remove(&target);
-                            }
-
-                            if let Entry::Occupied(v) = vid_map.entry(*larger) {
-                                let larger_deps = v.into_mut();
-                                larger_deps.smaller.insert(*smaller);
-                                larger_deps.smaller.remove(&target);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        finished_map
-    }
-
-    fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
-        return self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types());
-    }
-
-    pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
-        return match ty.kind {
-            ty::Param(_) => true,
-            ty::Projection(p) => self.is_of_param(p.self_ty()),
-            _ => false,
-        };
-    }
-
-    fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
-        match p.ty().skip_binder().kind {
-            ty::Projection(proj) if proj == p.skip_binder().projection_ty => true,
-            _ => false,
-        }
-    }
-
-    fn evaluate_nested_obligations(
-        &self,
-        ty: Ty<'_>,
-        nested: impl Iterator<Item = Obligation<'tcx, ty::Predicate<'tcx>>>,
-        computed_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        fresh_preds: &mut FxHashSet<ty::Predicate<'tcx>>,
-        predicates: &mut VecDeque<ty::PolyTraitPredicate<'tcx>>,
-        select: &mut SelectionContext<'_, 'tcx>,
-        only_projections: bool,
-    ) -> bool {
-        let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID);
-
-        for (obligation, mut predicate) in nested.map(|o| (o.clone(), o.predicate)) {
-            let is_new_pred = fresh_preds.insert(self.clean_pred(select.infcx(), predicate));
-
-            // Resolve any inference variables that we can, to help selection succeed
-            predicate = select.infcx().resolve_vars_if_possible(&predicate);
-
-            // We only add a predicate as a user-displayable bound if
-            // it involves a generic parameter, and doesn't contain
-            // any inference variables.
-            //
-            // Displaying a bound involving a concrete type (instead of a generic
-            // parameter) would be pointless, since it's always true
-            // (e.g. u8: Copy)
-            // Displaying an inference variable is impossible, since they're
-            // an internal compiler detail without a defined visual representation
-            //
-            // We check this by calling is_of_param on the relevant types
-            // from the various possible predicates
-            match &predicate {
-                &ty::Predicate::Trait(p, _) => {
-                    if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
-                        && !only_projections
-                        && is_new_pred
-                    {
-                        self.add_user_pred(computed_preds, predicate);
-                    }
-                    predicates.push_back(p);
-                }
-                &ty::Predicate::Projection(p) => {
-                    debug!(
-                        "evaluate_nested_obligations: examining projection predicate {:?}",
-                        predicate
-                    );
-
-                    // As described above, we only want to display
-                    // bounds which include a generic parameter but don't include
-                    // an inference variable.
-                    // Additionally, we check if we've seen this predicate before,
-                    // to avoid rendering duplicate bounds to the user.
-                    if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
-                        && !p.ty().skip_binder().has_infer_types()
-                        && is_new_pred
-                    {
-                        debug!(
-                            "evaluate_nested_obligations: adding projection predicate\
-                            to computed_preds: {:?}",
-                            predicate
-                        );
-
-                        // Under unusual circumstances, we can end up with a self-refeential
-                        // projection predicate. For example:
-                        // <T as MyType>::Value == <T as MyType>::Value
-                        // Not only is displaying this to the user pointless,
-                        // having it in the ParamEnv will cause an issue if we try to call
-                        // poly_project_and_unify_type on the predicate, since this kind of
-                        // predicate will normally never end up in a ParamEnv.
-                        //
-                        // For these reasons, we ignore these weird predicates,
-                        // ensuring that we're able to properly synthesize an auto trait impl
-                        if self.is_self_referential_projection(p) {
-                            debug!(
-                                "evaluate_nested_obligations: encountered a projection
-                                 predicate equating a type with itself! Skipping"
-                            );
-                        } else {
-                            self.add_user_pred(computed_preds, predicate);
-                        }
-                    }
-
-                    // There are three possible cases when we project a predicate:
-                    //
-                    // 1. We encounter an error. This means that it's impossible for
-                    // our current type to implement the auto trait - there's bound
-                    // that we could add to our ParamEnv that would 'fix' this kind
-                    // of error, as it's not caused by an unimplemented type.
-                    //
-                    // 2. We successfully project the predicate (Ok(Some(_))), generating
-                    //  some subobligations. We then process these subobligations
-                    //  like any other generated sub-obligations.
-                    //
-                    // 3. We receieve an 'ambiguous' result (Ok(None))
-                    // If we were actually trying to compile a crate,
-                    // we would need to re-process this obligation later.
-                    // However, all we care about is finding out what bounds
-                    // are needed for our type to implement a particular auto trait.
-                    // We've already added this obligation to our computed ParamEnv
-                    // above (if it was necessary). Therefore, we don't need
-                    // to do any further processing of the obligation.
-                    //
-                    // Note that we *must* try to project *all* projection predicates
-                    // we encounter, even ones without inference variable.
-                    // This ensures that we detect any projection errors,
-                    // which indicate that our type can *never* implement the given
-                    // auto trait. In that case, we will generate an explicit negative
-                    // impl (e.g. 'impl !Send for MyType'). However, we don't
-                    // try to process any of the generated subobligations -
-                    // they contain no new information, since we already know
-                    // that our type implements the projected-through trait,
-                    // and can lead to weird region issues.
-                    //
-                    // Normally, we'll generate a negative impl as a result of encountering
-                    // a type with an explicit negative impl of an auto trait
-                    // (for example, raw pointers have !Send and !Sync impls)
-                    // However, through some **interesting** manipulations of the type
-                    // system, it's actually possible to write a type that never
-                    // implements an auto trait due to a projection error, not a normal
-                    // negative impl error. To properly handle this case, we need
-                    // to ensure that we catch any potential projection errors,
-                    // and turn them into an explicit negative impl for our type.
-                    debug!("Projecting and unifying projection predicate {:?}", predicate);
-
-                    match poly_project_and_unify_type(select, &obligation.with(p)) {
-                        Err(e) => {
-                            debug!(
-                                "evaluate_nested_obligations: Unable to unify predicate \
-                                 '{:?}' '{:?}', bailing out",
-                                ty, e
-                            );
-                            return false;
-                        }
-                        Ok(Some(v)) => {
-                            // We only care about sub-obligations
-                            // when we started out trying to unify
-                            // some inference variables. See the comment above
-                            // for more infomration
-                            if p.ty().skip_binder().has_infer_types() {
-                                if !self.evaluate_nested_obligations(
-                                    ty,
-                                    v.clone().iter().cloned(),
-                                    computed_preds,
-                                    fresh_preds,
-                                    predicates,
-                                    select,
-                                    only_projections,
-                                ) {
-                                    return false;
-                                }
-                            }
-                        }
-                        Ok(None) => {
-                            // It's ok not to make progress when hvave no inference variables -
-                            // in that case, we were only performing unifcation to check if an
-                            // error occurred (which would indicate that it's impossible for our
-                            // type to implement the auto trait).
-                            // However, we should always make progress (either by generating
-                            // subobligations or getting an error) when we started off with
-                            // inference variables
-                            if p.ty().skip_binder().has_infer_types() {
-                                panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
-                            }
-                        }
-                    }
-                }
-                &ty::Predicate::RegionOutlives(ref binder) => {
-                    if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
-                        return false;
-                    }
-                }
-                &ty::Predicate::TypeOutlives(ref binder) => {
-                    match (
-                        binder.no_bound_vars(),
-                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
-                    ) {
-                        (None, Some(t_a)) => {
-                            select.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                select.infcx().tcx.lifetimes.re_static,
-                                &dummy_cause,
-                            );
-                        }
-                        (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
-                            select.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                r_b,
-                                &dummy_cause,
-                            );
-                        }
-                        _ => {}
-                    };
-                }
-                _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate),
-            };
-        }
-        return true;
-    }
-
-    pub fn clean_pred(
-        &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        p: ty::Predicate<'tcx>,
-    ) -> ty::Predicate<'tcx> {
-        infcx.freshen(p)
-    }
-}
-
-// Replaces all ReVars in a type with ty::Region's, using the provided map
-pub struct RegionReplacer<'a, 'tcx> {
-    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
-            _ => None,
-        })
-        .unwrap_or_else(|| r.super_fold_with(self))
-    }
-}
diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs
deleted file mode 100644
index bd4129a4de7..00000000000
--- a/src/librustc_infer/traits/codegen/mod.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// This file contains various trait resolution methods used by codegen.
-// They all assume regions can be erased and monomorphic types.  It
-// seems likely that they should eventually be merged into more
-// general routines.
-
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::{
-    FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
-};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, TyCtxt};
-
-/// Attempts to resolve an obligation to a vtable. The result is
-/// a shallow vtable resolution, meaning that we do not
-/// (necessarily) resolve all nested obligations on the impl. Note
-/// that type check should guarantee to us that all nested
-/// obligations *could be* resolved if we wanted to.
-/// Assumes that this is run after the entire crate has been successfully type-checked.
-pub fn codegen_fulfill_obligation<'tcx>(
-    ty: TyCtxt<'tcx>,
-    (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
-) -> Vtable<'tcx, ()> {
-    // Remove any references to regions; this helps improve caching.
-    let trait_ref = ty.erase_regions(&trait_ref);
-
-    debug!(
-        "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
-        (param_env, trait_ref),
-        trait_ref.def_id()
-    );
-
-    // Do the initial selection for the obligation. This yields the
-    // shallow result we are looking for -- that is, what specific impl.
-    ty.infer_ctxt().enter(|infcx| {
-        let mut selcx = SelectionContext::new(&infcx);
-
-        let obligation_cause = ObligationCause::dummy();
-        let obligation =
-            Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
-
-        let selection = match selcx.select(&obligation) {
-            Ok(Some(selection)) => selection,
-            Ok(None) => {
-                // Ambiguity can happen when monomorphizing during trans
-                // expands to some humongo type that never occurred
-                // statically -- this humongo type can then overflow,
-                // leading to an ambiguous result. So report this as an
-                // overflow bug, since I believe this is the only case
-                // where ambiguity can result.
-                bug!(
-                    "Encountered ambiguity selecting `{:?}` during codegen, \
-                      presuming due to overflow",
-                    trait_ref
-                )
-            }
-            Err(e) => {
-                bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
-            }
-        };
-
-        debug!("fulfill_obligation: selection={:?}", selection);
-
-        // Currently, we use a fulfillment context to completely resolve
-        // all nested obligations. This is because they can inform the
-        // inference of the impl's type parameters.
-        let mut fulfill_cx = FulfillmentContext::new();
-        let vtable = selection.map(|predicate| {
-            debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
-            fulfill_cx.register_predicate_obligation(&infcx, predicate);
-        });
-        let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable);
-
-        info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
-        vtable
-    })
-}
-
-// # Global Cache
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    /// Finishes processes any obligations that remain in the
-    /// fulfillment context, and then returns the result with all type
-    /// variables removed and regions erased. Because this is intended
-    /// for use after type-check has completed, if any errors occur,
-    /// it will panic. It is used during normalization and other cases
-    /// where processing the obligations in `fulfill_cx` may cause
-    /// type inference variables that appear in `result` to be
-    /// unified, and hence we need to process those obligations to get
-    /// the complete picture of the type.
-    fn drain_fulfillment_cx_or_panic<T>(
-        &self,
-        fulfill_cx: &mut FulfillmentContext<'tcx>,
-        result: &T,
-    ) -> T
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!("drain_fulfillment_cx_or_panic()");
-
-        // In principle, we only need to do this so long as `result`
-        // contains unbound type parameters. It could be a slight
-        // optimization to stop iterating early.
-        if let Err(errors) = fulfill_cx.select_all_or_error(self) {
-            bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
-        }
-
-        let result = self.resolve_vars_if_possible(result);
-        self.tcx.erase_regions(&result)
-    }
-}
diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs
deleted file mode 100644
index 0dec5ae6da5..00000000000
--- a/src/librustc_infer/traits/coherence.rs
+++ /dev/null
@@ -1,540 +0,0 @@
-//! See Rustc Guide chapters on [trait-resolution] and [trait-specialization] for more info on how
-//! this works.
-//!
-//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
-//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
-
-use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt};
-use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::SkipLeakCheck;
-use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
-
-/// Whether we do the orphan check relative to this crate or
-/// to some remote crate.
-#[derive(Copy, Clone, Debug)]
-enum InCrate {
-    Local,
-    Remote,
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum Conflict {
-    Upstream,
-    Downstream,
-}
-
-pub struct OverlapResult<'tcx> {
-    pub impl_header: ty::ImplHeader<'tcx>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
-
-    /// `true` if the overlap might've been permitted before the shift
-    /// to universes.
-    pub involves_placeholder: bool,
-}
-
-pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) {
-    err.note(
-        "this behavior recently changed as a result of a bug fix; \
-         see rust-lang/rust#56105 for details",
-    );
-}
-
-/// If there are types that satisfy both impls, invokes `on_overlap`
-/// with a suitably-freshened `ImplHeader` with those types
-/// substituted. Otherwise, invokes `no_overlap`.
-pub fn overlapping_impls<F1, F2, R>(
-    tcx: TyCtxt<'_>,
-    impl1_def_id: DefId,
-    impl2_def_id: DefId,
-    skip_leak_check: SkipLeakCheck,
-    on_overlap: F1,
-    no_overlap: F2,
-) -> R
-where
-    F1: FnOnce(OverlapResult<'_>) -> R,
-    F2: FnOnce() -> R,
-{
-    debug!(
-        "overlapping_impls(\
-           impl1_def_id={:?}, \
-           impl2_def_id={:?})",
-        impl1_def_id, impl2_def_id,
-    );
-
-    let overlaps = tcx.infer_ctxt().enter(|infcx| {
-        let selcx = &mut SelectionContext::intercrate(&infcx);
-        overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
-    });
-
-    if !overlaps {
-        return no_overlap();
-    }
-
-    // In the case where we detect an error, run the check again, but
-    // this time tracking intercrate ambuiguity causes for better
-    // diagnostics. (These take time and can lead to false errors.)
-    tcx.infer_ctxt().enter(|infcx| {
-        let selcx = &mut SelectionContext::intercrate(&infcx);
-        selcx.enable_tracking_intercrate_ambiguity_causes();
-        on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap())
-    })
-}
-
-fn with_fresh_ty_vars<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: DefId,
-) -> ty::ImplHeader<'tcx> {
-    let tcx = selcx.tcx();
-    let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
-
-    let header = ty::ImplHeader {
-        impl_def_id,
-        self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
-        trait_ref: tcx.impl_trait_ref(impl_def_id).subst(tcx, impl_substs),
-        predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
-    };
-
-    let Normalized { value: mut header, obligations } =
-        traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);
-
-    header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
-    header
-}
-
-/// Can both impl `a` and impl `b` be satisfied by a common type (including
-/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
-fn overlap<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    skip_leak_check: SkipLeakCheck,
-    a_def_id: DefId,
-    b_def_id: DefId,
-) -> Option<OverlapResult<'tcx>> {
-    debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
-
-    selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
-        overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)
-    })
-}
-
-fn overlap_within_probe(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    a_def_id: DefId,
-    b_def_id: DefId,
-    snapshot: &CombinedSnapshot<'_, 'tcx>,
-) -> Option<OverlapResult<'tcx>> {
-    // For the purposes of this check, we don't bring any placeholder
-    // types into scope; instead, we replace the generic types with
-    // fresh type variables, and hence we do our evaluations in an
-    // empty environment.
-    let param_env = ty::ParamEnv::empty();
-
-    let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
-    let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
-
-    debug!("overlap: a_impl_header={:?}", a_impl_header);
-    debug!("overlap: b_impl_header={:?}", b_impl_header);
-
-    // Do `a` and `b` unify? If not, no overlap.
-    let obligations = match selcx
-        .infcx()
-        .at(&ObligationCause::dummy(), param_env)
-        .eq_impl_headers(&a_impl_header, &b_impl_header)
-    {
-        Ok(InferOk { obligations, value: () }) => obligations,
-        Err(_) => {
-            return None;
-        }
-    };
-
-    debug!("overlap: unification check succeeded");
-
-    // Are any of the obligations unsatisfiable? If so, no overlap.
-    let infcx = selcx.infcx();
-    let opt_failing_obligation = a_impl_header
-        .predicates
-        .iter()
-        .chain(&b_impl_header.predicates)
-        .map(|p| infcx.resolve_vars_if_possible(p))
-        .map(|p| Obligation {
-            cause: ObligationCause::dummy(),
-            param_env,
-            recursion_depth: 0,
-            predicate: p,
-        })
-        .chain(obligations)
-        .find(|o| !selcx.predicate_may_hold_fatal(o));
-    // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
-    // to the canonical trait query form, `infcx.predicate_may_hold`, once
-    // the new system supports intercrate mode (which coherence needs).
-
-    if let Some(failing_obligation) = opt_failing_obligation {
-        debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
-        return None;
-    }
-
-    let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header);
-    let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
-    debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
-
-    let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) {
-        Some(true) => true,
-        _ => false,
-    };
-
-    Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
-}
-
-pub fn trait_ref_is_knowable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-) -> Option<Conflict> {
-    debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Remote).is_ok() {
-        // A downstream or cousin crate is allowed to implement some
-        // substitution of this trait-ref.
-        return Some(Conflict::Downstream);
-    }
-
-    if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
-        // This is a local or fundamental trait, so future-compatibility
-        // is no concern. We know that downstream/cousin crates are not
-        // allowed to implement a substitution of this trait ref, which
-        // means impls could only come from dependencies of this crate,
-        // which we already know about.
-        return None;
-    }
-
-    // This is a remote non-fundamental trait, so if another crate
-    // can be the "final owner" of a substitution of this trait-ref,
-    // they are allowed to implement it future-compatibly.
-    //
-    // However, if we are a final owner, then nobody else can be,
-    // and if we are an intermediate owner, then we don't care
-    // about future-compatibility, which means that we're OK if
-    // we are an owner.
-    if orphan_check_trait_ref(tcx, trait_ref, InCrate::Local).is_ok() {
-        debug!("trait_ref_is_knowable: orphan check passed");
-        return None;
-    } else {
-        debug!("trait_ref_is_knowable: nonlocal, nonfundamental, unowned");
-        return Some(Conflict::Upstream);
-    }
-}
-
-pub fn trait_ref_is_local_or_fundamental<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-) -> bool {
-    trait_ref.def_id.krate == LOCAL_CRATE || tcx.has_attr(trait_ref.def_id, sym::fundamental)
-}
-
-pub enum OrphanCheckErr<'tcx> {
-    NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
-    UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
-}
-
-/// Checks the coherence orphan rules. `impl_def_id` should be the
-/// `DefId` of a trait impl. To pass, either the trait must be local, or else
-/// two conditions must be satisfied:
-///
-/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
-/// 2. Some local type must appear in `Self`.
-pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
-    debug!("orphan_check({:?})", impl_def_id);
-
-    // We only except this routine to be invoked on implementations
-    // of a trait, not inherent implementations.
-    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-    debug!("orphan_check: trait_ref={:?}", trait_ref);
-
-    // If the *trait* is local to the crate, ok.
-    if trait_ref.def_id.is_local() {
-        debug!("trait {:?} is local to current crate", trait_ref.def_id);
-        return Ok(());
-    }
-
-    orphan_check_trait_ref(tcx, trait_ref, InCrate::Local)
-}
-
-/// Checks whether a trait-ref is potentially implementable by a crate.
-///
-/// The current rule is that a trait-ref orphan checks in a crate C:
-///
-/// 1. Order the parameters in the trait-ref in subst order - Self first,
-///    others linearly (e.g., `<U as Foo<V, W>>` is U < V < W).
-/// 2. Of these type parameters, there is at least one type parameter
-///    in which, walking the type as a tree, you can reach a type local
-///    to C where all types in-between are fundamental types. Call the
-///    first such parameter the "local key parameter".
-///     - e.g., `Box<LocalType>` is OK, because you can visit LocalType
-///       going through `Box`, which is fundamental.
-///     - similarly, `FundamentalPair<Vec<()>, Box<LocalType>>` is OK for
-///       the same reason.
-///     - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
-///       not local), `Vec<LocalType>` is bad, because `Vec<->` is between
-///       the local type and the type parameter.
-/// 3. Every type parameter before the local key parameter is fully known in C.
-///     - e.g., `impl<T> T: Trait<LocalType>` is bad, because `T` might be
-///       an unknown type.
-///     - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
-///       occurs before `T`.
-/// 4. Every type in the local key parameter not known in C, going
-///    through the parameter's type tree, must appear only as a subtree of
-///    a type local to C, with only fundamental types between the type
-///    local to C and the local key parameter.
-///     - e.g., `Vec<LocalType<T>>>` (or equivalently `Box<Vec<LocalType<T>>>`)
-///     is bad, because the only local type with `T` as a subtree is
-///     `LocalType<T>`, and `Vec<->` is between it and the type parameter.
-///     - similarly, `FundamentalPair<LocalType<T>, T>` is bad, because
-///     the second occurrence of `T` is not a subtree of *any* local type.
-///     - however, `LocalType<Vec<T>>` is OK, because `T` is a subtree of
-///     `LocalType<Vec<T>>`, which is local and has no types between it and
-///     the type parameter.
-///
-/// The orphan rules actually serve several different purposes:
-///
-/// 1. They enable link-safety - i.e., 2 mutually-unknowing crates (where
-///    every type local to one crate is unknown in the other) can't implement
-///    the same trait-ref. This follows because it can be seen that no such
-///    type can orphan-check in 2 such crates.
-///
-///    To check that a local impl follows the orphan rules, we check it in
-///    InCrate::Local mode, using type parameters for the "generic" types.
-///
-/// 2. They ground negative reasoning for coherence. If a user wants to
-///    write both a conditional blanket impl and a specific impl, we need to
-///    make sure they do not overlap. For example, if we write
-///    ```
-///    impl<T> IntoIterator for Vec<T>
-///    impl<T: Iterator> IntoIterator for T
-///    ```
-///    We need to be able to prove that `Vec<$0>: !Iterator` for every type $0.
-///    We can observe that this holds in the current crate, but we need to make
-///    sure this will also hold in all unknown crates (both "independent" crates,
-///    which we need for link-safety, and also child crates, because we don't want
-///    child crates to get error for impl conflicts in a *dependency*).
-///
-///    For that, we only allow negative reasoning if, for every assignment to the
-///    inference variables, every unknown crate would get an orphan error if they
-///    try to implement this trait-ref. To check for this, we use InCrate::Remote
-///    mode. That is sound because we already know all the impls from known crates.
-///
-/// 3. For non-#[fundamental] traits, they guarantee that parent crates can
-///    add "non-blanket" impls without breaking negative reasoning in dependent
-///    crates. This is the "rebalancing coherence" (RFC 1023) restriction.
-///
-///    For that, we only a allow crate to perform negative reasoning on
-///    non-local-non-#[fundamental] only if there's a local key parameter as per (2).
-///
-///    Because we never perform negative reasoning generically (coherence does
-///    not involve type parameters), this can be interpreted as doing the full
-///    orphan check (using InCrate::Local mode), substituting non-local known
-///    types for all inference variables.
-///
-///    This allows for crates to future-compatibly add impls as long as they
-///    can't apply to types with a key parameter in a child crate - applying
-///    the rules, this basically means that every type parameter in the impl
-///    must appear behind a non-fundamental type (because this is not a
-///    type-system requirement, crate owners might also go for "semantic
-///    future-compatibility" involving things such as sealed traits, but
-///    the above requirement is sufficient, and is necessary in "open world"
-///    cases).
-///
-/// Note that this function is never called for types that have both type
-/// parameters and inference variables.
-fn orphan_check_trait_ref<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    in_crate: InCrate,
-) -> Result<(), OrphanCheckErr<'tcx>> {
-    debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
-
-    if trait_ref.needs_infer() && trait_ref.needs_subst() {
-        bug!(
-            "can't orphan check a trait ref with both params and inference variables {:?}",
-            trait_ref
-        );
-    }
-
-    // Given impl<P1..=Pn> Trait<T1..=Tn> for T0, an impl is valid only
-    // if at least one of the following is true:
-    //
-    // - Trait is a local trait
-    // (already checked in orphan_check prior to calling this function)
-    // - All of
-    //     - At least one of the types T0..=Tn must be a local type.
-    //      Let Ti be the first such type.
-    //     - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
-    //
-    fn uncover_fundamental_ty<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
-        in_crate: InCrate,
-    ) -> Vec<Ty<'tcx>> {
-        if fundamental_ty(ty) && ty_is_non_local(ty, in_crate).is_some() {
-            ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect()
-        } else {
-            vec![ty]
-        }
-    }
-
-    let mut non_local_spans = vec![];
-    for (i, input_ty) in
-        trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).enumerate()
-    {
-        debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
-        let non_local_tys = ty_is_non_local(input_ty, in_crate);
-        if non_local_tys.is_none() {
-            debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
-            return Ok(());
-        } else if let ty::Param(_) = input_ty.kind {
-            debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
-            let local_type = trait_ref
-                .input_types()
-                .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
-                .find(|ty| ty_is_non_local_constructor(ty, in_crate).is_none());
-
-            debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
-
-            return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type));
-        }
-        if let Some(non_local_tys) = non_local_tys {
-            for input_ty in non_local_tys {
-                non_local_spans.push((input_ty, i == 0));
-            }
-        }
-    }
-    // If we exit above loop, never found a local type.
-    debug!("orphan_check_trait_ref: no local type");
-    Err(OrphanCheckErr::NonLocalInputType(non_local_spans))
-}
-
-fn ty_is_non_local<'t>(ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
-    match ty_is_non_local_constructor(ty, in_crate) {
-        Some(ty) => {
-            if !fundamental_ty(ty) {
-                Some(vec![ty])
-            } else {
-                let tys: Vec<_> = ty
-                    .walk_shallow()
-                    .filter_map(|t| ty_is_non_local(t, in_crate))
-                    .flat_map(|i| i)
-                    .collect();
-                if tys.is_empty() { None } else { Some(tys) }
-            }
-        }
-        None => None,
-    }
-}
-
-fn fundamental_ty(ty: Ty<'_>) -> bool {
-    match ty.kind {
-        ty::Ref(..) => true,
-        ty::Adt(def, _) => def.is_fundamental(),
-        _ => false,
-    }
-}
-
-fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
-    match in_crate {
-        // The type is local to *this* crate - it will not be
-        // local in any other crate.
-        InCrate::Remote => false,
-        InCrate::Local => def_id.is_local(),
-    }
-}
-
-fn ty_is_non_local_constructor<'tcx>(ty: Ty<'tcx>, in_crate: InCrate) -> Option<Ty<'tcx>> {
-    debug!("ty_is_non_local_constructor({:?})", ty);
-
-    match ty.kind {
-        ty::Bool
-        | ty::Char
-        | ty::Int(..)
-        | ty::Uint(..)
-        | ty::Float(..)
-        | ty::Str
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::Array(..)
-        | ty::Slice(..)
-        | ty::RawPtr(..)
-        | ty::Ref(..)
-        | ty::Never
-        | ty::Tuple(..)
-        | ty::Param(..)
-        | ty::Projection(..) => Some(ty),
-
-        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
-            InCrate::Local => Some(ty),
-            // The inference variable might be unified with a local
-            // type in that remote crate.
-            InCrate::Remote => None,
-        },
-
-        ty::Adt(def, _) => {
-            if def_id_is_local(def.did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
-        ty::Foreign(did) => {
-            if def_id_is_local(did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
-        ty::Opaque(..) => {
-            // This merits some explanation.
-            // Normally, opaque types are not involed when performing
-            // coherence checking, since it is illegal to directly
-            // implement a trait on an opaque type. However, we might
-            // end up looking at an opaque type during coherence checking
-            // if an opaque type gets used within another type (e.g. as
-            // a type parameter). This requires us to decide whether or
-            // not an opaque type should be considered 'local' or not.
-            //
-            // We choose to treat all opaque types as non-local, even
-            // those that appear within the same crate. This seems
-            // somewhat suprising at first, but makes sense when
-            // you consider that opaque types are supposed to hide
-            // the underlying type *within the same crate*. When an
-            // opaque type is used from outside the module
-            // where it is declared, it should be impossible to observe
-            // anyything about it other than the traits that it implements.
-            //
-            // The alternative would be to look at the underlying type
-            // to determine whether or not the opaque type itself should
-            // be considered local. However, this could make it a breaking change
-            // to switch the underlying ('defining') type from a local type
-            // to a remote type. This would violate the rule that opaque
-            // types should be completely opaque apart from the traits
-            // that they implement, so we don't use this behavior.
-            Some(ty)
-        }
-
-        ty::Dynamic(ref tt, ..) => {
-            if let Some(principal) = tt.principal() {
-                if def_id_is_local(principal.def_id(), in_crate) { None } else { Some(ty) }
-            } else {
-                Some(ty)
-            }
-        }
-
-        ty::Error => None,
-
-        ty::UnnormalizedProjection(..)
-        | ty::Closure(..)
-        | ty::Generator(..)
-        | ty::GeneratorWitness(..) => bug!("ty_is_local invoked on unexpected type: {:?}", ty),
-    }
-}
diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs
index e23810dd161..a95257ba682 100644
--- a/src/librustc_infer/traits/engine.rs
+++ b/src/librustc_infer/traits/engine.rs
@@ -1,9 +1,9 @@
 use crate::infer::InferCtxt;
 use crate::traits::Obligation;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_hir::def_id::DefId;
+use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
 
-use super::{FulfillmentContext, FulfillmentError};
+use super::FulfillmentError;
 use super::{ObligationCause, PredicateObligation};
 
 pub trait TraitEngine<'tcx>: 'tcx {
@@ -76,9 +76,3 @@ impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
         }
     }
 }
-
-impl dyn TraitEngine<'tcx> {
-    pub fn new(_tcx: TyCtxt<'tcx>) -> Box<Self> {
-        Box::new(FulfillmentContext::new())
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs
index 63c3f827c2e..9206166d0bd 100644
--- a/src/librustc_infer/traits/error_reporting/mod.rs
+++ b/src/librustc_infer/traits/error_reporting/mod.rs
@@ -1,452 +1,16 @@
-pub mod on_unimplemented;
-pub mod suggestions;
+use super::ObjectSafetyViolation;
 
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc::mir::interpret::ErrorHandled;
-use rustc::session::DiagnosticMessageId;
-use rustc::ty::error::ExpectedFound;
-use rustc::ty::fast_reject;
-use rustc::ty::fold::TypeFolder;
-use rustc::ty::SubtypePredicate;
-use rustc::ty::{
-    self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use crate::infer::InferCtxt;
 use rustc_ast::ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
-use rustc_span::source_map::SourceMap;
-use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::Span;
 use std::fmt;
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|&predicate| ErrorDescriptor { predicate, index: None })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // We want to ignore desugarings here: spans are equivalent even
-            // if one is the result of a desugaring and the other is not.
-            let mut span = error.obligation.cause.span;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate,
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // We do this in 2 passes because we want to display errors in order, though
-        // maybe it *is* better to sort errors by span or something.
-        let mut is_suppressed = vec![false; errors.len()];
-        for (_, error_set) in error_map.iter() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
-            if let ty::Predicate::Trait(implication, _) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
-        let all_impls = self.tcx.all_impls(trait_ref.def_id());
-
-        match simp {
-            Some(simp) => all_impls
-                .iter()
-                .filter_map(|&def_id| {
-                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(!cycle.is_empty());
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
     pub fn report_extra_impl_obligation(
         &self,
         error_span: Span,
@@ -456,12 +20,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         requirement: &dyn fmt::Display,
     ) -> DiagnosticBuilder<'tcx> {
         let msg = "impl has stricter requirements than trait";
-        let sp = self.tcx.sess.source_map().def_span(error_span);
+        let sp = self.tcx.sess.source_map().guess_head_span(error_span);
 
         let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
 
         if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-            let span = self.tcx.sess.source_map().def_span(trait_item_span);
+            let span = self.tcx.sess.source_map().guess_head_span(trait_item_span);
             err.span_label(span, format!("definition of `{}` from trait", item_name));
         }
 
@@ -469,550 +33,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         err
     }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span =
-                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate, _) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{}`", t),
-                                    format!("within `{}`, ", t),
-                                    s.map(|s| (format!("within this `{}`", t), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                     conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            message.unwrap_or_else(|| format!(
-                                "the trait bound `{}` is not satisfied{}",
-                                trait_ref.without_const().to_predicate(),
-                                post_message,
-                            ))
-                        );
-
-                        let explanation =
-                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
-                                "consider using `()`, or a `Result`".to_owned()
-                            } else {
-                                format!(
-                                    "{}the trait `{}` is not implemented for `{}`",
-                                    pre_message,
-                                    trait_ref.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
-                            err.emit();
-                            return;
-                        }
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types_or_consts()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // these notes will often be of the form
-                            //     "the type `T` can't be frobnicated"
-                            // which is somewhat confusing.
-                            self.suggest_restricting_param_bound(
-                                &mut err,
-                                &trait_ref,
-                                obligation.cause.body_id,
-                            );
-                        } else {
-                            if !have_alt_message {
-                                // Can't show anything else useful, try to find similar impls.
-                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                                self.report_similar_impl_candidates(impl_candidates, &mut err);
-                            }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(
-                                    predicate,
-                                    hir::Constness::NotConst,
-                                ),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "the trait is implemented for `()`. \
-                                     Possibly this error has been caused by changes to \
-                                     Rust's type-inference algorithm (see issue #48950 \
-                                     <https://github.com/rust-lang/rust/issues/48950> \
-                                     for more information). Consider whether you meant to use \
-                                     the type `()` here instead.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        // WF predicates cannot themselves make
-                        // errors. They can only block due to
-                        // ambiguity; otherwise, they always
-                        // degenerate into other obligations
-                        // (which may fail).
-                        span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| self.tcx.hir().span_if_local(did))
-                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
-
-                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-                    // We check closures twice, with obligations flowing in different directions,
-                    // but we want to complain about them only once.
-                    return;
-                }
-
-                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
-                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-                    _ => vec![ArgKind::empty()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            ConstEvalFailure(ErrorHandled::TooGeneric) => {
-                // In this instance, we have a const expression containing an unevaluated
-                // generic parameter. We have no idea whether this expression is valid or
-                // not (e.g. it might result in an error), but we don't want to just assume
-                // that it's okay, because that might result in post-monomorphisation time
-                // errors. The onus is really on the caller to provide values that it can
-                // prove are well-formed.
-                let mut err = self
-                    .tcx
-                    .sess
-                    .struct_span_err(span, "constant expression depends on a generic parameter");
-                // FIXME(const_generics): we should suggest to the user how they can resolve this
-                // issue. However, this is currently not actually possible
-                // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
-                err.note("this may fail depending on what value the parameter takes");
-                err
-            }
-
-            // Already reported in the query.
-            ConstEvalFailure(ErrorHandled::Reported) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-        self.point_at_returns_when_relevant(&mut err, &obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
 }
 
 pub fn report_object_safety_error(
@@ -1026,7 +46,7 @@ pub fn report_object_safety_error(
         hir::Node::Item(item) => Some(item.ident.span),
         _ => None,
     });
-    let span = tcx.sess.source_map().def_span(span);
+    let span = tcx.sess.source_map().guess_head_span(span);
     let mut err = struct_span_err!(
         tcx.sess,
         span,
@@ -1084,560 +104,3 @@ pub fn report_object_safety_error(
 
     err
 }
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data, _) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and dont add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                cleaned_pred.without_const().to_predicate(),
-            );
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-            self.suggest_unsized_bound_if_applicable(err, obligation);
-        }
-    }
-
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        if let (
-            ty::Predicate::Trait(pred, _),
-            ObligationCauseCode::BindingObligation(item_def_id, span),
-        ) = (&obligation.predicate, &obligation.cause.code)
-        {
-            if let (Some(generics), true) = (
-                self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
-                Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
-            ) {
-                for param in generics.params {
-                    if param.span == *span
-                        && !param.bounds.iter().any(|bound| {
-                            bound.trait_def_id() == self.tcx.lang_items().sized_trait()
-                        })
-                    {
-                        let (span, separator) = match param.bounds {
-                            [] => (span.shrink_to_hi(), ":"),
-                            [.., bound] => (bound.span().shrink_to_hi(), " + "),
-                        };
-                        err.span_suggestion(
-                            span,
-                            "consider relaxing the implicit `Sized` restriction",
-                            format!("{} ?Sized", separator),
-                            Applicability::MachineApplicable,
-                        );
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    tcx: TyCtxt<'_>,
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-    def_id: Option<DefId>,
-) -> bool {
-    const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
-    const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
-    const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
-
-    let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
-
-    let param = if let Some(param) = param {
-        param
-    } else {
-        return false;
-    };
-
-    if def_id == tcx.lang_items().sized_trait() {
-        // Type parameters are already `Sized` by default.
-        err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
-        return true;
-    }
-
-    if param_name.starts_with("impl ") {
-        // If there's an `impl Trait` used in argument position, suggest
-        // restricting it:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             help: consider further restricting this bound with `+ Bar`
-        //
-        // Suggestion for tools in this case is:
-        //
-        //   fn foo(t: impl Foo) { ... }
-        //             --------
-        //             |
-        //             replace with: `impl Foo + Bar`
-
-        err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
-
-        err.tool_only_span_suggestion(
-            param.span,
-            MSG_RESTRICT_BOUND_FURTHER,
-            format!("{} + {}", param_name, constraint),
-            Applicability::MachineApplicable,
-        );
-
-        return true;
-    }
-
-    if generics.where_clause.predicates.is_empty() {
-        if let Some(bounds_span) = param.bounds_span() {
-            // If user has provided some bounds, suggest restricting them:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //             ---
-            //             |
-            //             help: consider further restricting this bound with `+ Bar`
-            //
-            // Suggestion for tools in this case is:
-            //
-            //   fn foo<T: Foo>(t: T) { ... }
-            //          --
-            //          |
-            //          replace with: `T: Bar +`
-
-            err.span_help(
-                bounds_span,
-                &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-            );
-
-            let span_hi = param.span.with_hi(span.hi());
-            let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-            if span_hi != param.span && span_with_colon != span_hi {
-                err.tool_only_span_suggestion(
-                    span_with_colon,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        } else {
-            // If user hasn't provided any bounds, suggest adding a new one:
-            //
-            //   fn foo<T>(t: T) { ... }
-            //          - help: consider restricting this type parameter with `T: Foo`
-
-            err.span_help(
-                param.span,
-                &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-            );
-
-            err.tool_only_span_suggestion(
-                param.span,
-                MSG_RESTRICT_TYPE,
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        }
-
-        true
-    } else {
-        // This part is a bit tricky, because using the `where` clause user can
-        // provide zero, one or many bounds for the same type parameter, so we
-        // have following cases to consider:
-        //
-        // 1) When the type parameter has been provided zero bounds
-        //
-        //    Message:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //             - help: consider restricting this type parameter with `where X: Bar`
-        //
-        //    Suggestion:
-        //      fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
-        //                                           - insert: `, X: Bar`
-        //
-        //
-        // 2) When the type parameter has been provided one bound
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^^^^^
-        //                            |
-        //                            help: consider further restricting this bound with `+ Bar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo { ... }
-        //                            ^^
-        //                            |
-        //                            replace with: `T: Bar +`
-        //
-        //
-        // 3) When the type parameter has been provided many bounds
-        //
-        //    Message:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //             - help: consider further restricting this type parameter with `where T: Zar`
-        //
-        //    Suggestion:
-        //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
-        //                                          - insert: `, T: Zar`
-
-        let mut param_spans = Vec::new();
-
-        for predicate in generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                span, bounded_ty, ..
-            }) = predicate
-            {
-                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                    if let Some(segment) = path.segments.first() {
-                        if segment.ident.to_string() == param_name {
-                            param_spans.push(span);
-                        }
-                    }
-                }
-            }
-        }
-
-        let where_clause_span =
-            generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
-
-        match &param_spans[..] {
-            &[] => {
-                err.span_help(
-                    param.span,
-                    &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_TYPE,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            &[&param_span] => {
-                err.span_help(
-                    param_span,
-                    &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
-                );
-
-                let span_hi = param_span.with_hi(span.hi());
-                let span_with_colon = source_map.span_through_char(span_hi, ':');
-
-                if span_hi != param_span && span_with_colon != span_hi {
-                    err.tool_only_span_suggestion(
-                        span_with_colon,
-                        MSG_RESTRICT_BOUND_FURTHER,
-                        format!("{}: {} +", param_name, constraint),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-
-            _ => {
-                err.span_help(
-                    param.span,
-                    &format!(
-                        "{} `where {}: {}`",
-                        MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
-                    ),
-                );
-
-                err.tool_only_span_suggestion(
-                    where_clause_span,
-                    MSG_RESTRICT_BOUND_FURTHER,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
-
-        true
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs
deleted file mode 100644
index 87c1107bd42..00000000000
--- a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs
+++ /dev/null
@@ -1,223 +0,0 @@
-use super::{
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
-};
-use crate::infer::InferCtxt;
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, GenericParamDefKind};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::sym;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
-        let tcx = self.tcx;
-        let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
-        let trait_self_ty = trait_ref.self_ty();
-
-        let mut self_match_impls = vec![];
-        let mut fuzzy_match_impls = vec![];
-
-        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
-
-            let impl_self_ty = impl_trait_ref.self_ty();
-
-            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
-
-                if trait_ref
-                    .substs
-                    .types()
-                    .skip(1)
-                    .zip(impl_trait_ref.substs.types().skip(1))
-                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
-                {
-                    fuzzy_match_impls.push(def_id);
-                }
-            }
-        });
-
-        let impl_def_id = if self_match_impls.len() == 1 {
-            self_match_impls[0]
-        } else if fuzzy_match_impls.len() == 1 {
-            fuzzy_match_impls[0]
-        } else {
-            return None;
-        };
-
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
-    }
-
-    /// Used to set on_unimplemented's `ItemContext`
-    /// to be the enclosing (async) block/function/closure
-    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
-        let hir = &self.tcx.hir();
-        let node = hir.find(hir_id)?;
-        match &node {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
-                self.describe_generator(*body_id).or_else(|| {
-                    Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                        "an async function"
-                    } else {
-                        "a function"
-                    })
-                })
-            }
-            hir::Node::TraitItem(hir::TraitItem {
-                kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
-            hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Method(sig, body_id),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async method"
-                } else {
-                    "a method"
-                })
-            }),
-            hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-                ..
-            }) => self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            }),
-            hir::Node::Expr(hir::Expr { .. }) => {
-                let parent_hid = hir.get_parent_node(hir_id);
-                if parent_hid != hir_id {
-                    return self.describe_enclosure(parent_hid);
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        }
-    }
-
-    crate fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
-
-        let mut flags = vec![];
-        flags.push((
-            sym::item_context,
-            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
-        ));
-
-        match obligation.cause.code {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..) => {}
-            _ => {
-                // this is a "direct", user-specified, rather than derived,
-                // obligation.
-                flags.push((sym::direct, None));
-            }
-        }
-
-        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
-            // FIXME: maybe also have some way of handling methods
-            // from other traits? That would require name resolution,
-            // which we might want to be some sort of hygienic.
-            //
-            // Currently I'm leaving it for what I need for `try`.
-            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                let method = self.tcx.item_name(item);
-                flags.push((sym::from_method, None));
-                flags.push((sym::from_method, Some(method.to_string())));
-            }
-        }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
-        }
-        let generics = self.tcx.generics_of(def_id);
-        let self_ty = trait_ref.self_ty();
-        // This is also included through the generics list as `Self`,
-        // but the parser won't allow you to use it
-        flags.push((sym::_Self, Some(self_ty.to_string())));
-        if let Some(def) = self_ty.ty_adt_def() {
-            // We also want to be able to select self's original
-            // signature with no type arguments resolved
-            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
-        }
-
-        for param in generics.params.iter() {
-            let value = match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                    trait_ref.substs[param.index as usize].to_string()
-                }
-                GenericParamDefKind::Lifetime => continue,
-            };
-            let name = param.name;
-            flags.push((name, Some(value)));
-        }
-
-        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push((sym::crate_local, None));
-        }
-
-        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
-        if self_ty.is_integral() {
-            flags.push((sym::_Self, Some("{integral}".to_owned())));
-        }
-
-        if let ty::Array(aty, len) = self_ty.kind {
-            flags.push((sym::_Self, Some("[]".to_owned())));
-            flags.push((sym::_Self, Some(format!("[{}]", aty))));
-            if let Some(def) = aty.ty_adt_def() {
-                // We also want to be able to select the array's type's original
-                // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
-            }
-        }
-        if let ty::Dynamic(traits, _) = self_ty.kind {
-            for t in *traits.skip_binder() {
-                match t {
-                    ty::ExistentialPredicate::Trait(trait_ref) => {
-                        flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
-                    }
-                    _ => {}
-                }
-            }
-        }
-
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
-            command.evaluate(self.tcx, trait_ref, &flags[..])
-        } else {
-            OnUnimplementedNote::default()
-        }
-    }
-}
diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs
deleted file mode 100644
index d05955fb858..00000000000
--- a/src/librustc_infer/traits/error_reporting/suggestions.rs
+++ /dev/null
@@ -1,1707 +0,0 @@
-use super::{
-    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
-    PredicateObligation,
-};
-
-use crate::infer::InferCtxt;
-use crate::traits::error_reporting::suggest_constraining_type_param;
-
-use rustc::ty::TypeckTables;
-use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_errors::{
-    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
-};
-use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::Node;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::{MultiSpan, Span, DUMMY_SP};
-use std::fmt;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_restricting_param_bound(
-        &self,
-        mut err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'_>,
-        body_id: hir::HirId,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (param_ty, projection) = match &self_ty.kind {
-            ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
-            _ => return,
-        };
-
-        let suggest_restriction =
-            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
-                let span = generics.where_clause.span_for_predicates_or_empty_place();
-                if !span.from_expansion() && span.desugaring_kind().is_none() {
-                    err.span_suggestion(
-                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
-                        &format!("consider further restricting {}", msg),
-                        format!(
-                            "{} {} ",
-                            if !generics.where_clause.predicates.is_empty() {
-                                ","
-                            } else {
-                                " where"
-                            },
-                            trait_ref.without_const().to_predicate(),
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            };
-
-        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
-        //        don't suggest `T: Sized + ?Sized`.
-        let mut hir_id = body_id;
-        while let Some(node) = self.tcx.hir().find(hir_id) {
-            match node {
-                hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                }) if param_ty && self_ty == self.tcx.types.self_param => {
-                    // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    generics,
-                    kind: hir::ImplItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl { generics, .. }, ..
-                }) if projection.is_some() => {
-                    // Missing associated type bound.
-                    suggest_restriction(&generics, "the associated type", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Enum(_, generics), span, ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Union(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl { generics, .. },
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_, generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TyAlias(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TraitAlias(generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
-                    span,
-                    ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
-                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
-                    if param_ty =>
-                {
-                    // Missing generic type parameter bound.
-                    let param_name = self_ty.to_string();
-                    let constraint = trait_ref.print_only_trait_path().to_string();
-                    if suggest_constraining_type_param(
-                        self.tcx,
-                        generics,
-                        &mut err,
-                        &param_name,
-                        &constraint,
-                        self.tcx.sess.source_map(),
-                        *span,
-                        Some(trait_ref.def_id()),
-                    ) {
-                        return;
-                    }
-                }
-
-                hir::Node::Crate => return,
-
-                _ => {}
-            }
-
-            hir_id = self.tcx.hir().get_parent_item(hir_id);
-        }
-    }
-
-    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
-    /// suggestion to borrow the initializer in order to use have a slice instead.
-    crate fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /// Given a closure's `DefId`, return the given name of the closure.
-    ///
-    /// This doesn't account for reassignments, but it's only used for suggestions.
-    crate fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut DiagnosticBuilder<'_>,
-        msg: &str,
-    ) -> Option<String> {
-        let get_name =
-            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
-                // Get the local name of this closure. This can be inaccurate because
-                // of the possibility of reassignment, but this should be good enough.
-                match &kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
-                        Some(format!("{}", name))
-                    }
-                    _ => {
-                        err.note(&msg);
-                        None
-                    }
-                }
-            };
-
-        let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id)?;
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
-            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
-                get_name(err, &local.pat.kind)
-            }
-            // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
-            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
-            _ => return None,
-        }
-    }
-
-    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
-    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
-    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    crate fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (def_id, output_ty, callable) = match self_ty.kind {
-            ty::Closure(def_id, substs) => {
-                (def_id, self.closure_sig(def_id, substs).output(), "closure")
-            }
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
-            _ => return,
-        };
-        let msg = format!("use parentheses to call the {}", callable);
-
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
-
-        match self.evaluate_obligation(&obligation) {
-            Ok(EvaluationResult::EvaluatedToOk)
-            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
-            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
-            _ => return,
-        }
-        let hir = self.tcx.hir();
-        // Get the name of the callable and the arguments to be used in the suggestion.
-        let snippet = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
-                ..
-            })) => {
-                err.span_label(*span, "consider calling this closure");
-                let name = match self.get_closure_name(def_id, err, &msg) {
-                    Some(name) => name,
-                    None => return,
-                };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                format!("{}({})", name, args)
-            }
-            Some(hir::Node::Item(hir::Item {
-                ident,
-                kind: hir::ItemKind::Fn(.., body_id),
-                ..
-            })) => {
-                err.span_label(ident.span, "consider calling this function");
-                let body = hir.body(*body_id);
-                let args = body
-                    .params
-                    .iter()
-                    .map(|arg| match &arg.pat.kind {
-                        hir::PatKind::Binding(_, _, ident, None)
-                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
-                        // should suggest a method call.
-                        if ident.name != kw::SelfLower => ident.to_string(),
-                        _ => "_".to_string(),
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                format!("{}({})", ident, args)
-            }
-            _ => return,
-        };
-        if points_at_arg {
-            // When the obligation error has been ensured to have been caused by
-            // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
-            err.span_suggestion(
-                obligation.cause.span,
-                &msg,
-                snippet,
-                Applicability::HasPlaceholders,
-            );
-        } else {
-            err.help(&format!("{}: `{}`", msg, snippet));
-        }
-    }
-
-    crate fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-        has_custom_message: bool,
-    ) -> bool {
-        if !points_at_arg {
-            return false;
-        }
-
-        let span = obligation.cause.span;
-        let param_env = obligation.param_env;
-        let trait_ref = trait_ref.skip_binder();
-
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation = Obligation::new(
-                ObligationCause::dummy(),
-                param_env,
-                new_trait_ref.without_const().to_predicate(),
-            );
-            if self.predicate_must_hold_modulo_regions(&new_obligation) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    // We have a very specific type of error, where just borrowing this argument
-                    // might solve the problem. In cases like this, the important part is the
-                    // original type obligation, not the last one that failed, which is arbitrary.
-                    // Because of this, we modify the error to refer to the original obligation and
-                    // return early in the caller.
-                    let msg = format!(
-                        "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                    );
-                    if has_custom_message {
-                        err.note(&msg);
-                    } else {
-                        err.message = vec![(msg, Style::NoStyle)];
-                    }
-                    if snippet.starts_with('&') {
-                        // This is already a literal borrow and the obligation is failing
-                        // somewhere else in the obligation chain. Do not suggest non-sense.
-                        return false;
-                    }
-                    err.span_label(
-                        span,
-                        &format!(
-                            "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                        ),
-                    );
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return true;
-                }
-            }
-        }
-        false
-    }
-
-    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
-    /// suggest removing these references until we reach a type that implements the trait.
-    crate fn suggest_remove_reference(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let trait_ref = trait_ref.skip_binder();
-        let span = obligation.cause.span;
-
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-
-            let mut trait_type = trait_ref.self_ty();
-
-            for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
-
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
-                        obligation.param_env,
-                    );
-
-                    if self.predicate_may_hold(&new_obligation) {
-                        let sp = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-
-                        let remove_refs = refs_remaining + 1;
-
-                        let msg = if remove_refs == 1 {
-                            "consider removing the leading `&`-reference".to_string()
-                        } else {
-                            format!("consider removing {} leading `&`-references", remove_refs)
-                        };
-
-                        err.span_suggestion_short(
-                            sp,
-                            &msg,
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                        break;
-                    }
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    /// Check if the trait bound is implemented for a different mutability and note it in the
-    /// final error.
-    crate fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let span = obligation.cause.span;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-            let trait_ref = self.resolve_vars_if_possible(trait_ref);
-            if trait_ref.has_infer_types_or_consts() {
-                // Do not ICE while trying to find if a reborrow would succeed on a trait with
-                // unresolved bindings.
-                return;
-            }
-
-            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
-                let trait_type = match mutability {
-                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
-                };
-
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                );
-
-                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
-                {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
-                        err.span_suggestion(
-                            sp,
-                            "consider changing this borrow's mutability",
-                            "&mut ".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        err.note(&format!(
-                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
-                            trait_ref.print_only_trait_path(),
-                            trait_type,
-                            trait_ref.skip_binder().self_ty(),
-                        ));
-                    }
-                }
-            }
-        }
-    }
-
-    crate fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
-        {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && "()" == &trait_ref.self_ty().to_string()
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                        err.span_label(sp, "consider removing this semicolon");
-                    }
-                }
-            }
-        }
-    }
-
-    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
-    /// applicable and signal that the error has been expanded appropriately and needs to be
-    /// emitted.
-    crate fn suggest_impl_trait(
-        &self,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) -> bool {
-        match obligation.cause.code.peel_derives() {
-            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return false,
-        }
-
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id),
-            ..
-        })) = node
-        {
-            (sig, body_id)
-        } else {
-            return false;
-        };
-        let body = hir.body(*body_id);
-        let trait_ref = self.resolve_vars_if_possible(trait_ref);
-        let ty = trait_ref.skip_binder().self_ty();
-        let is_object_safe = match ty.kind {
-            ty::Dynamic(predicates, _) => {
-                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
-                predicates
-                    .principal_def_id()
-                    .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
-            }
-            // We only want to suggest `impl Trait` to `dyn Trait`s.
-            // For example, `fn foo() -> str` needs to be filtered out.
-            _ => return false,
-        };
-
-        let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output {
-            ret_ty
-        } else {
-            return false;
-        };
-
-        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
-        // cases like `fn foo() -> (dyn Trait, i32) {}`.
-        // Recursively look for `TraitObject` types and if there's only one, use that span to
-        // suggest `impl Trait`.
-
-        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
-        // otherwise suggest using `Box<dyn Trait>` or an enum.
-        let mut visitor = ReturnsVisitor::default();
-        visitor.visit_body(&body);
-
-        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
-
-        let mut ret_types = visitor
-            .returns
-            .iter()
-            .filter_map(|expr| tables.node_type_opt(expr.hir_id))
-            .map(|ty| self.resolve_vars_if_possible(&ty));
-        let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
-            (None, true),
-            |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
-                let ty = self.resolve_vars_if_possible(&ty);
-                same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
-                (Some(ty), same)
-            },
-        );
-        let all_returns_conform_to_trait =
-            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
-                match ty_ret_ty.kind {
-                    ty::Dynamic(predicates, _) => {
-                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
-                        let param_env = ty::ParamEnv::empty();
-                        ret_types.all(|returned_ty| {
-                            predicates.iter().all(|predicate| {
-                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
-                                let obl = Obligation::new(cause.clone(), param_env, pred);
-                                self.predicate_may_hold(&obl)
-                            })
-                        })
-                    }
-                    _ => false,
-                }
-            } else {
-                true
-            };
-
-        let (snippet, last_ty) =
-            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
-                // Verify that we're dealing with a return `dyn Trait`
-                ret_ty.span.overlaps(span),
-                &ret_ty.kind,
-                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
-                // If any of the return types does not conform to the trait, then we can't
-                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
-                all_returns_conform_to_trait,
-                last_ty,
-            ) {
-                (snippet, last_ty)
-            } else {
-                return false;
-            };
-        err.code(error_code!(E0746));
-        err.set_primary_message("return type cannot have an unboxed trait object");
-        err.children.clear();
-        let impl_trait_msg = "for information on `impl Trait`, see \
-            <https://doc.rust-lang.org/book/ch10-02-traits.html\
-            #returning-types-that-implement-traits>";
-        let trait_obj_msg = "for information on trait objects, see \
-            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
-            #using-trait-objects-that-allow-for-values-of-different-types>";
-        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
-        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
-        if all_returns_have_same_type {
-            // Suggest `-> impl Trait`.
-            err.span_suggestion(
-                ret_ty.span,
-                &format!(
-                    "return `impl {1}` instead, as all return paths are of type `{}`, \
-                        which implements `{1}`",
-                    last_ty, trait_obj,
-                ),
-                format!("impl {}", trait_obj),
-                Applicability::MachineApplicable,
-            );
-            err.note(impl_trait_msg);
-        } else {
-            if is_object_safe {
-                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
-                // Get all the return values and collect their span and suggestion.
-                let mut suggestions = visitor
-                    .returns
-                    .iter()
-                    .map(|expr| {
-                        (
-                            expr.span,
-                            format!(
-                                "Box::new({})",
-                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
-                            ),
-                        )
-                    })
-                    .collect::<Vec<_>>();
-                // Add the suggestion for the return type.
-                suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
-                err.multipart_suggestion(
-                    "return a boxed trait object instead",
-                    suggestions,
-                    Applicability::MaybeIncorrect,
-                );
-            } else {
-                // This is currently not possible to trigger because E0038 takes precedence, but
-                // leave it in for completeness in case anything changes in an earlier stage.
-                err.note(&format!(
-                    "if trait `{}` was object safe, you could return a trait object",
-                    trait_obj,
-                ));
-            }
-            err.note(trait_obj_msg);
-            err.note(&format!(
-                "if all the returned values were of the same type you could use \
-                    `impl {}` as the return type",
-                trait_obj,
-            ));
-            err.note(impl_trait_msg);
-            err.note("you can create a new `enum` with a variant for each returned type");
-        }
-        true
-    }
-
-    crate fn point_at_returns_when_relevant(
-        &self,
-        err: &mut DiagnosticBuilder<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        match obligation.cause.code.peel_derives() {
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return,
-        }
-
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
-            node
-        {
-            let body = hir.body(*body_id);
-            // Point at all the `return`s in the function as they have failed trait bounds.
-            let mut visitor = ReturnsVisitor::default();
-            visitor.visit_body(&body);
-            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
-            for expr in &visitor.returns {
-                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
-                    let ty = self.resolve_vars_if_possible(&returned_ty);
-                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
-                }
-            }
-        }
-    }
-
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    crate fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_ref: ty::PolyTraitRef<'tcx>,
-        found: ty::PolyTraitRef<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
-        crate fn build_fn_sig_string<'tcx>(
-            tcx: TyCtxt<'tcx>,
-            trait_ref: &ty::TraitRef<'tcx>,
-        ) -> String {
-            let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
-                    ::std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            };
-            ty::Binder::bind(sig).to_string()
-        }
-
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0631,
-            "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
-        );
-
-        let found_str = format!(
-            "expected signature of `{}`",
-            build_fn_sig_string(self.tcx, found.skip_binder())
-        );
-        err.span_label(span, found_str);
-
-        let found_span = found_span.unwrap_or(span);
-        let expected_str = format!(
-            "found signature of `{}`",
-            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
-        );
-        err.span_label(found_span, expected_str);
-
-        err
-    }
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    crate fn suggest_fully_qualified_path(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        def_id: DefId,
-        span: Span,
-        trait_ref: DefId,
-    ) {
-        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
-            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
-                err.note(&format!(
-                    "{}s cannot be accessed directly on a `trait`, they can only be \
-                        accessed through a specific `impl`",
-                    assoc_item.kind.suggestion_descr(),
-                ));
-                err.span_suggestion(
-                    span,
-                    "use the fully qualified path to an implementation",
-                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
-                    Applicability::HasPlaceholders,
-                );
-            }
-        }
-    }
-
-    /// Adds an async-await specific note to the diagnostic when the future does not implement
-    /// an auto trait because of a captured type.
-    ///
-    /// ```ignore (diagnostic)
-    /// note: future does not implement `Qux` as this value is used across an await
-    ///   --> $DIR/issue-64130-3-other.rs:17:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
-    /// is "replaced" with a different message and a more specific error.
-    ///
-    /// ```ignore (diagnostic)
-    /// error: future cannot be sent between threads safely
-    ///   --> $DIR/issue-64130-2-send.rs:21:5
-    ///    |
-    /// LL | fn is_send<T: Send>(t: T) { }
-    ///    |    -------    ---- required by this bound in `is_send`
-    /// ...
-    /// LL |     is_send(bar());
-    ///    |     ^^^^^^^ future returned by `bar` is not send
-    ///    |
-    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
-    ///            implemented for `Foo`
-    /// note: future is not send as this value is used across an await
-    ///   --> $DIR/issue-64130-2-send.rs:15:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// Returns `true` if an async-await specific note was added to the diagnostic.
-    crate fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
-                obligation.cause.span={:?}",
-            obligation.predicate, obligation.cause.span
-        );
-        let source_map = self.tcx.sess.source_map();
-
-        // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator to be present.
-        //
-        // When a future does not implement a trait because of a captured type in one of the
-        // generators somewhere in the call stack, then the result is a chain of obligations.
-        //
-        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
-        // future is passed as an argument to a function C which requires a `Send` type, then the
-        // chain looks something like this:
-        //
-        // - `BuiltinDerivedObligation` with a generator witness (B)
-        // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with a generator witness (A)
-        // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BindingObligation` with `impl_send (Send requirement)
-        //
-        // The first obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator has information about where the bound was introduced. At
-        // least one generator should be present for this diagnostic to be modified.
-        let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p, _) => {
-                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
-            }
-            _ => (None, None),
-        };
-        let mut generator = None;
-        let mut last_generator = None;
-        let mut next_code = Some(&obligation.cause.code);
-        while let Some(code) = next_code {
-            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
-            match code {
-                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    let ty = derived_obligation.parent_trait_ref.self_ty();
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
-                        derived_obligation.parent_trait_ref, ty.kind
-                    );
-
-                    match ty.kind {
-                        ty::Generator(did, ..) => {
-                            generator = generator.or(Some(did));
-                            last_generator = Some(did);
-                        }
-                        ty::GeneratorWitness(..) => {}
-                        _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
-                            target_ty = Some(ty);
-                        }
-                        _ => {}
-                    }
-
-                    next_code = Some(derived_obligation.parent_code.as_ref());
-                }
-                _ => break,
-            }
-        }
-
-        // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
-        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
-            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
-                (generator_did, trait_ref, target_ty)
-            }
-            _ => return false,
-        };
-
-        let span = self.tcx.def_span(generator_did);
-
-        // Do not ICE on closure typeck (#66868).
-        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
-            return false;
-        }
-
-        // Get the tables from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
-        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
-             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
-            generator_did,
-            generator_did_root,
-            in_progress_tables.as_ref().map(|t| t.local_id_root),
-            span
-        );
-        let query_tables;
-        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
-            Some(t) if t.local_id_root == Some(generator_did_root) => t,
-            _ => {
-                query_tables = self.tcx.typeck_tables_of(generator_did);
-                &query_tables
-            }
-        };
-
-        // Look for a type inside the generator interior that matches the target type to get
-        // a span.
-        let target_ty_erased = self.tcx.erase_regions(&target_ty);
-        let target_span = tables
-            .generator_interior_types
-            .iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
-                // Careful: the regions for types that appear in the
-                // generator interior are not generally known, so we
-                // want to erase them when comparing (and anyway,
-                // `Send` and other bounds are generally unaffected by
-                // the choice of region).  When erasing regions, we
-                // also have to erase late-bound regions. This is
-                // because the types that appear in the generator
-                // interior generally contain "bound regions" to
-                // represent regions that are part of the suspended
-                // generator frame. Bound regions are preserved by
-                // `erase_regions` and so we must also call
-                // `erase_late_bound_regions`.
-                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
-                let ty_erased = self.tcx.erase_regions(&ty_erased);
-                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
-                debug!(
-                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
-                        target_ty_erased={:?} eq={:?}",
-                    ty_erased, target_ty_erased, eq
-                );
-                eq
-            })
-            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
-                (span, source_map.span_to_snippet(*span), scope_span, expr)
-            });
-
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
-                generator_interior_types={:?} target_span={:?}",
-            target_ty, tables.generator_interior_types, target_span
-        );
-        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
-            self.note_obligation_cause_for_async_await(
-                err,
-                *target_span,
-                scope_span,
-                *expr,
-                snippet,
-                generator_did,
-                last_generator,
-                trait_ref,
-                target_ty,
-                tables,
-                obligation,
-                next_code,
-            );
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Unconditionally adds the diagnostic note described in
-    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    crate fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        target_span: Span,
-        scope_span: &Option<Span>,
-        expr: Option<hir::HirId>,
-        snippet: String,
-        first_generator: DefId,
-        last_generator: Option<DefId>,
-        trait_ref: ty::TraitRef<'_>,
-        target_ty: Ty<'tcx>,
-        tables: &ty::TypeckTables<'_>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    ) {
-        let source_map = self.tcx.sess.source_map();
-
-        let is_async_fn = self
-            .tcx
-            .parent(first_generator)
-            .map(|parent_did| self.tcx.asyncness(parent_did))
-            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
-            .unwrap_or(false);
-        let is_async_move = self
-            .tcx
-            .hir()
-            .as_local_hir_id(first_generator)
-            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
-            .map(|body_id| self.tcx.hir().body(body_id))
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
-            .unwrap_or(false);
-        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
-
-        // Special case the primary error message when send or sync is the trait that was
-        // not implemented.
-        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
-        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
-        let hir = self.tcx.hir();
-        let trait_explanation = if is_send || is_sync {
-            let (trait_name, trait_verb) =
-                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
-
-            err.clear_code();
-            err.set_primary_message(format!(
-                "future cannot be {} between threads safely",
-                trait_verb
-            ));
-
-            let original_span = err.span.primary_span().unwrap();
-            let mut span = MultiSpan::from_span(original_span);
-
-            let message = if let Some(name) = last_generator
-                .and_then(|generator_did| self.tcx.parent(generator_did))
-                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
-                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
-            {
-                format!("future returned by `{}` is not {}", name, trait_name)
-            } else {
-                format!("future is not {}", trait_name)
-            };
-
-            span.push_span_label(original_span, message);
-            err.set_span(span);
-
-            format!("is not {}", trait_name)
-        } else {
-            format!("does not implement `{}`", trait_ref.print_only_trait_path())
-        };
-
-        // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
-        let mut span = MultiSpan::from_span(await_span);
-        span.push_span_label(
-            await_span,
-            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
-        );
-
-        span.push_span_label(target_span, format!("has type `{}`", target_ty));
-
-        // If available, use the scope span to annotate the drop location.
-        if let Some(scope_span) = scope_span {
-            span.push_span_label(
-                source_map.end_point(*scope_span),
-                format!("`{}` is later dropped here", snippet),
-            );
-        }
-
-        err.span_note(
-            span,
-            &format!(
-                "future {} as this value is used across an {}",
-                trait_explanation, await_or_yield,
-            ),
-        );
-
-        if let Some(expr_id) = expr {
-            let expr = hir.expect_expr(expr_id);
-            debug!("target_ty evaluated from {:?}", expr);
-
-            let parent = hir.get_parent_node(expr_id);
-            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
-                let parent_span = hir.span(parent);
-                let parent_did = parent.owner_def_id();
-                // ```rust
-                // impl T {
-                //     fn foo(&self) -> i32 {}
-                // }
-                // T.foo();
-                // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
-                // ```
-                //
-                let is_region_borrow =
-                    tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
-
-                // ```rust
-                // struct Foo(*const u8);
-                // bar(Foo(std::ptr::null())).await;
-                //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
-                // ```
-                debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
-                let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
-                    Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
-                    _ => false,
-                };
-
-                if (tables.is_method_call(e) && is_region_borrow)
-                    || is_raw_borrow_inside_fn_like_call
-                {
-                    err.span_help(
-                        parent_span,
-                        "consider moving this into a `let` \
-                        binding to create a shorter lived borrow",
-                    );
-                }
-            }
-        }
-
-        // Add a note for the item obligation that remains - normally a note pointing to the
-        // bound that introduced the obligation (e.g. `T: Send`).
-        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
-        self.note_obligation_cause_code(
-            err,
-            &obligation.predicate,
-            next_code.unwrap(),
-            &mut Vec::new(),
-        );
-    }
-
-    crate fn note_obligation_cause_code<T>(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        predicate: &T,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-    ) where
-        T: fmt::Display,
-    {
-        let tcx = self.tcx;
-        match *cause_code {
-            ObligationCauseCode::ExprAssignable
-            | ObligationCauseCode::MatchExpressionArm { .. }
-            | ObligationCauseCode::Pattern { .. }
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::IfExpressionWithNoElse
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver
-            | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::MiscObligation => {}
-            ObligationCauseCode::SliceOrArrayElem => {
-                err.note("slice and array elements must have `Sized` type");
-            }
-            ObligationCauseCode::TupleElem => {
-                err.note("only the last element of a tuple may have a dynamically sized type");
-            }
-            ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
-            }
-            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
-                ));
-            }
-            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!(
-                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
-                    region, object_ty,
-                ));
-            }
-            ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by `{}`", item_name);
-
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by this bound in `{}`", item_name);
-                if let Some(ident) = tcx.opt_item_name(item_def_id) {
-                    err.span_label(ident.span, "");
-                }
-                if span != DUMMY_SP {
-                    err.span_label(span, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
-                err.note(&format!(
-                    "required for the cast to the object type `{}`",
-                    self.ty_to_string(object_ty)
-                ));
-            }
-            ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
-            }
-            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
-                err.note(
-                    "the `Copy` trait is required because the repeated element will be copied",
-                );
-                if suggest_const_in_array_repeat_expressions {
-                    err.note(
-                        "this array initializer can be evaluated at compile-time, see issue \
-                         #48147 <https://github.com/rust-lang/rust/issues/49147> \
-                         for more information",
-                    );
-                    if tcx.sess.opts.unstable_features.is_nightly_build() {
-                        err.help(
-                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
-                             crate attributes to enable",
-                        );
-                    }
-                }
-            }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedArgumentType => {
-                err.note("all function arguments must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedReturnType => {
-                err.note("the return type of a function must have a statically known size");
-            }
-            ObligationCauseCode::SizedYieldType => {
-                err.note("the yield type of a generator must have a statically known size");
-            }
-            ObligationCauseCode::AssignmentLhsSized => {
-                err.note("the left-hand-side of an assignment must have a statically known size");
-            }
-            ObligationCauseCode::TupleInitializerSized => {
-                err.note("tuples must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::StructInitializerSized => {
-                err.note("structs must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
-                AdtKind::Struct => {
-                    if last {
-                        err.note(
-                            "the last field of a packed struct may only have a \
-                             dynamically sized type if it does not need drop to be run",
-                        );
-                    } else {
-                        err.note(
-                            "only the last field of a struct may have a dynamically sized type",
-                        );
-                    }
-                }
-                AdtKind::Union => {
-                    err.note("no field of a union may have a dynamically sized type");
-                }
-                AdtKind::Enum => {
-                    err.note("no field of an enum variant may have a dynamically sized type");
-                }
-            },
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
-            }
-            ObligationCauseCode::ConstPatternStructural => {
-                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
-            }
-            ObligationCauseCode::SharedStatic => {
-                err.note("shared static variables must have a type that implements `Sync`");
-            }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.skip_binder().self_ty();
-                err.note(&format!("required because it appears within the type `{}`", ty));
-                obligated_types.push(ty);
-
-                let parent_predicate = parent_trait_ref.without_const().to_predicate();
-                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
-                    self.note_obligation_cause_code(
-                        err,
-                        &parent_predicate,
-                        &data.parent_code,
-                        obligated_types,
-                    );
-                }
-            }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                err.note(&format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_ref.print_only_trait_path(),
-                    parent_trait_ref.skip_binder().self_ty()
-                ));
-                let parent_predicate = parent_trait_ref.without_const().to_predicate();
-                self.note_obligation_cause_code(
-                    err,
-                    &parent_predicate,
-                    &data.parent_code,
-                    obligated_types,
-                );
-            }
-            ObligationCauseCode::CompareImplMethodObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                     but not on the corresponding trait method",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::CompareImplTypeObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type \
-                     but not on the corresponding associated trait type",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
-            ObligationCauseCode::TrivialBound => {
-                err.help("see issue #48214");
-                if tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
-                }
-            }
-            ObligationCauseCode::AssocTypeBound(ref data) => {
-                err.span_label(data.original, "associated type defined here");
-                if let Some(sp) = data.impl_span {
-                    err.span_label(sp, "in this `impl` item");
-                }
-                for sp in &data.bounds {
-                    err.span_label(*sp, "restricted in this bound");
-                }
-            }
-        }
-    }
-
-    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
-        let suggested_limit = current_limit * 2;
-        err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit, self.tcx.crate_name,
-        ));
-    }
-}
-
-/// Collect all the returned expressions within the input expression.
-/// Used to point at the return spans when we want to suggest some change to them.
-#[derive(Default)]
-struct ReturnsVisitor<'v> {
-    returns: Vec<&'v hir::Expr<'v>>,
-    in_block_tail: bool,
-}
-
-impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
-    type Map = rustc::hir::map::Map<'v>;
-
-    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
-        hir::intravisit::NestedVisitorMap::None
-    }
-
-    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-        // Visit every expression to detect `return` paths, either through the function's tail
-        // expression or `return` statements. We walk all nodes to find `return` statements, but
-        // we only care about tail expressions when `in_block_tail` is `true`, which means that
-        // they're in the return path of the function body.
-        match ex.kind {
-            hir::ExprKind::Ret(Some(ex)) => {
-                self.returns.push(ex);
-            }
-            hir::ExprKind::Block(block, _) if self.in_block_tail => {
-                self.in_block_tail = false;
-                for stmt in block.stmts {
-                    hir::intravisit::walk_stmt(self, stmt);
-                }
-                self.in_block_tail = true;
-                if let Some(expr) = block.expr {
-                    self.visit_expr(expr);
-                }
-            }
-            hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
-                for arm in arms {
-                    self.visit_expr(arm.body);
-                }
-            }
-            // We need to walk to find `return`s in the entire body.
-            _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
-            _ => self.returns.push(ex),
-        }
-    }
-
-    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-        assert!(!self.in_block_tail);
-        if body.generator_kind().is_none() {
-            if let hir::ExprKind::Block(block, None) = body.value.kind {
-                if block.expr.is_some() {
-                    self.in_block_tail = true;
-                }
-            }
-        }
-        hir::intravisit::walk_body(self, body);
-    }
-}
diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs
deleted file mode 100644
index ac9ff484a02..00000000000
--- a/src/librustc_infer/traits/fulfill.rs
+++ /dev/null
@@ -1,556 +0,0 @@
-use crate::infer::{InferCtxt, ShallowResolver};
-use rustc::ty::error::ExpectedFound;
-use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable};
-use rustc_data_structures::obligation_forest::ProcessResult;
-use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
-use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
-use std::marker::PhantomData;
-
-use super::engine::{TraitEngine, TraitEngineExt};
-use super::project;
-use super::select::SelectionContext;
-use super::wf;
-use super::CodeAmbiguity;
-use super::CodeProjectionError;
-use super::CodeSelectionError;
-use super::{ConstEvalFailure, Unimplemented};
-use super::{FulfillmentError, FulfillmentErrorCode};
-use super::{ObligationCause, PredicateObligation};
-
-impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
-    /// Note that we include both the `ParamEnv` and the `Predicate`,
-    /// as the `ParamEnv` can influence whether fulfillment succeeds
-    /// or fails.
-    type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
-
-    fn as_cache_key(&self) -> Self::CacheKey {
-        self.obligation.param_env.and(self.obligation.predicate)
-    }
-}
-
-/// The fulfillment context is used to drive trait resolution. It
-/// consists of a list of obligations that must be (eventually)
-/// satisfied. The job is to track which are satisfied, which yielded
-/// errors, and which are still pending. At any point, users can call
-/// `select_where_possible`, and the fulfillment context will try to do
-/// selection, retaining only those obligations that remain
-/// ambiguous. This may be helpful in pushing type inference
-/// along. Once all type inference constraints have been generated, the
-/// method `select_all_or_error` can be used to report any remaining
-/// ambiguous cases as errors.
-pub struct FulfillmentContext<'tcx> {
-    // A list of all obligations that have been registered with this
-    // fulfillment context.
-    predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
-    // Should this fulfillment context register type-lives-for-region
-    // obligations on its parent infcx? In some cases, region
-    // obligations are either already known to hold (normalization) or
-    // hopefully verifed elsewhere (type-impls-bound), and therefore
-    // should not be checked.
-    //
-    // Note that if we are normalizing a type that we already
-    // know is well-formed, there should be no harm setting this
-    // to true - all the region variables should be determinable
-    // using the RFC 447 rules, which don't depend on
-    // type-lives-for-region constraints, and because the type
-    // is well-formed, the constraints should hold.
-    register_region_obligations: bool,
-    // Is it OK to register obligations into this infcx inside
-    // an infcx snapshot?
-    //
-    // The "primary fulfillment" in many cases in typeck lives
-    // outside of any snapshot, so any use of it inside a snapshot
-    // will lead to trouble and therefore is checked against, but
-    // other fulfillment contexts sometimes do live inside of
-    // a snapshot (they don't *straddle* a snapshot, so there
-    // is no trouble there).
-    usable_in_snapshot: bool,
-}
-
-#[derive(Clone, Debug)]
-pub struct PendingPredicateObligation<'tcx> {
-    pub obligation: PredicateObligation<'tcx>,
-    pub stalled_on: Vec<ty::InferTy>,
-}
-
-// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(target_arch = "x86_64")]
-static_assert_size!(PendingPredicateObligation<'_>, 136);
-
-impl<'a, 'tcx> FulfillmentContext<'tcx> {
-    /// Creates a new fulfillment context.
-    pub fn new() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: true,
-            usable_in_snapshot: false,
-        }
-    }
-
-    pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: true,
-            usable_in_snapshot: true,
-        }
-    }
-
-    pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
-        FulfillmentContext {
-            predicates: ObligationForest::new(),
-            register_region_obligations: false,
-            usable_in_snapshot: false,
-        }
-    }
-
-    /// Attempts to select obligations using `selcx`.
-    fn select(
-        &mut self,
-        selcx: &mut SelectionContext<'a, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        debug!("select(obligation-forest-size={})", self.predicates.len());
-
-        let mut errors = Vec::new();
-
-        loop {
-            debug!("select: starting another iteration");
-
-            // Process pending obligations.
-            let outcome = self.predicates.process_obligations(
-                &mut FulfillProcessor {
-                    selcx,
-                    register_region_obligations: self.register_region_obligations,
-                },
-                DoCompleted::No,
-            );
-            debug!("select: outcome={:#?}", outcome);
-
-            // FIXME: if we kept the original cache key, we could mark projection
-            // obligations as complete for the projection cache here.
-
-            errors.extend(outcome.errors.into_iter().map(|e| to_fulfillment_error(e)));
-
-            // If nothing new was added, no need to keep looping.
-            if outcome.stalled {
-                break;
-            }
-        }
-
-        debug!(
-            "select({} predicates remaining, {} errors) done",
-            self.predicates.len(),
-            errors.len()
-        );
-
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
-    }
-}
-
-impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
-    /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
-    /// creating a fresh type variable `$0` as well as a projection
-    /// predicate `<SomeType as SomeTrait>::X == $0`. When the
-    /// inference engine runs, it will attempt to find an impl of
-    /// `SomeTrait` or a where-clause that lets us unify `$0` with
-    /// something concrete. If this fails, we'll unify `$0` with
-    /// `projection_ty` again.
-    fn normalize_projection_type(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        projection_ty: ty::ProjectionTy<'tcx>,
-        cause: ObligationCause<'tcx>,
-    ) -> Ty<'tcx> {
-        debug!("normalize_projection_type(projection_ty={:?})", projection_ty);
-
-        debug_assert!(!projection_ty.has_escaping_bound_vars());
-
-        // FIXME(#20304) -- cache
-
-        let mut selcx = SelectionContext::new(infcx);
-        let mut obligations = vec![];
-        let normalized_ty = project::normalize_projection_type(
-            &mut selcx,
-            param_env,
-            projection_ty,
-            cause,
-            0,
-            &mut obligations,
-        );
-        self.register_predicate_obligations(infcx, obligations);
-
-        debug!("normalize_projection_type: result={:?}", normalized_ty);
-
-        normalized_ty
-    }
-
-    fn register_predicate_obligation(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        obligation: PredicateObligation<'tcx>,
-    ) {
-        // this helps to reduce duplicate errors, as well as making
-        // debug output much nicer to read and so on.
-        let obligation = infcx.resolve_vars_if_possible(&obligation);
-
-        debug!("register_predicate_obligation(obligation={:?})", obligation);
-
-        assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
-
-        self.predicates
-            .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
-    }
-
-    fn select_all_or_error(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        self.select_where_possible(infcx)?;
-
-        let errors: Vec<_> = self
-            .predicates
-            .to_errors(CodeAmbiguity)
-            .into_iter()
-            .map(|e| to_fulfillment_error(e))
-            .collect();
-        if errors.is_empty() { Ok(()) } else { Err(errors) }
-    }
-
-    fn select_where_possible(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Result<(), Vec<FulfillmentError<'tcx>>> {
-        let mut selcx = SelectionContext::new(infcx);
-        self.select(&mut selcx)
-    }
-
-    fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
-        self.predicates.map_pending_obligations(|o| o.obligation.clone())
-    }
-}
-
-struct FulfillProcessor<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    register_region_obligations: bool,
-}
-
-fn mk_pending(os: Vec<PredicateObligation<'tcx>>) -> Vec<PendingPredicateObligation<'tcx>> {
-    os.into_iter()
-        .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] })
-        .collect()
-}
-
-impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
-    type Obligation = PendingPredicateObligation<'tcx>;
-    type Error = FulfillmentErrorCode<'tcx>;
-
-    /// Processes a predicate obligation and returns either:
-    /// - `Changed(v)` if the predicate is true, presuming that `v` are also true
-    /// - `Unchanged` if we don't have enough info to be sure
-    /// - `Error(e)` if the predicate does not hold
-    ///
-    /// This is always inlined, despite its size, because it has a single
-    /// callsite and it is called *very* frequently.
-    #[inline(always)]
-    fn process_obligation(
-        &mut self,
-        pending_obligation: &mut Self::Obligation,
-    ) -> ProcessResult<Self::Obligation, Self::Error> {
-        // If we were stalled on some unresolved variables, first check whether
-        // any of them have been resolved; if not, don't bother doing more work
-        // yet.
-        let change = match pending_obligation.stalled_on.len() {
-            // Match arms are in order of frequency, which matters because this
-            // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
-            1 => {
-                let infer = pending_obligation.stalled_on[0];
-                ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
-            }
-            0 => {
-                // In this case we haven't changed, but wish to make a change.
-                true
-            }
-            _ => {
-                // This `for` loop was once a call to `all()`, but this lower-level
-                // form was a perf win. See #64545 for details.
-                (|| {
-                    for &infer in &pending_obligation.stalled_on {
-                        if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
-                            return true;
-                        }
-                    }
-                    false
-                })()
-            }
-        };
-
-        if !change {
-            debug!(
-                "process_predicate: pending obligation {:?} still stalled on {:?}",
-                self.selcx.infcx().resolve_vars_if_possible(&pending_obligation.obligation),
-                pending_obligation.stalled_on
-            );
-            return ProcessResult::Unchanged;
-        }
-
-        // This part of the code is much colder.
-
-        pending_obligation.stalled_on.truncate(0);
-
-        let obligation = &mut pending_obligation.obligation;
-
-        if obligation.predicate.has_infer_types_or_consts() {
-            obligation.predicate =
-                self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
-        }
-
-        debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
-
-        fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
-            match ty.kind {
-                ty::Infer(infer) => infer,
-                _ => panic!(),
-            }
-        }
-
-        match obligation.predicate {
-            ty::Predicate::Trait(ref data, _) => {
-                let trait_obligation = obligation.with(data.clone());
-
-                if data.is_global() {
-                    // no type variables present, can use evaluation for better caching.
-                    // FIXME: consider caching errors too.
-                    if self.selcx.infcx().predicate_must_hold_considering_regions(&obligation) {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} evaluated to holds",
-                            data, obligation.recursion_depth
-                        );
-                        return ProcessResult::Changed(vec![]);
-                    }
-                }
-
-                match self.selcx.select(&trait_obligation) {
-                    Ok(Some(vtable)) => {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} yielded Ok(Some)",
-                            data, obligation.recursion_depth
-                        );
-                        ProcessResult::Changed(mk_pending(vtable.nested_obligations()))
-                    }
-                    Ok(None) => {
-                        debug!(
-                            "selecting trait `{:?}` at depth {} yielded Ok(None)",
-                            data, obligation.recursion_depth
-                        );
-
-                        // This is a bit subtle: for the most part, the
-                        // only reason we can fail to make progress on
-                        // trait selection is because we don't have enough
-                        // information about the types in the trait.
-                        pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
-
-                        debug!(
-                            "process_predicate: pending obligation {:?} now stalled on {:?}",
-                            self.selcx.infcx().resolve_vars_if_possible(obligation),
-                            pending_obligation.stalled_on
-                        );
-
-                        ProcessResult::Unchanged
-                    }
-                    Err(selection_err) => {
-                        info!(
-                            "selecting trait `{:?}` at depth {} yielded Err",
-                            data, obligation.recursion_depth
-                        );
-
-                        ProcessResult::Error(CodeSelectionError(selection_err))
-                    }
-                }
-            }
-
-            ty::Predicate::RegionOutlives(ref binder) => {
-                match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
-                    Ok(()) => ProcessResult::Changed(vec![]),
-                    Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
-                }
-            }
-
-            ty::Predicate::TypeOutlives(ref binder) => {
-                // Check if there are higher-ranked vars.
-                match binder.no_bound_vars() {
-                    // If there are, inspect the underlying type further.
-                    None => {
-                        // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
-                        let binder = binder.map_bound_ref(|pred| pred.0);
-
-                        // Check if the type has any bound vars.
-                        match binder.no_bound_vars() {
-                            // If so, this obligation is an error (for now). Eventually we should be
-                            // able to support additional cases here, like `for<'a> &'a str: 'a`.
-                            // NOTE: this is duplicate-implemented between here and fulfillment.
-                            None => ProcessResult::Error(CodeSelectionError(Unimplemented)),
-                            // Otherwise, we have something of the form
-                            // `for<'a> T: 'a where 'a not in T`, which we can treat as
-                            // `T: 'static`.
-                            Some(t_a) => {
-                                let r_static = self.selcx.tcx().lifetimes.re_static;
-                                if self.register_region_obligations {
-                                    self.selcx.infcx().register_region_obligation_with_cause(
-                                        t_a,
-                                        r_static,
-                                        &obligation.cause,
-                                    );
-                                }
-                                ProcessResult::Changed(vec![])
-                            }
-                        }
-                    }
-                    // If there aren't, register the obligation.
-                    Some(ty::OutlivesPredicate(t_a, r_b)) => {
-                        if self.register_region_obligations {
-                            self.selcx.infcx().register_region_obligation_with_cause(
-                                t_a,
-                                r_b,
-                                &obligation.cause,
-                            );
-                        }
-                        ProcessResult::Changed(vec![])
-                    }
-                }
-            }
-
-            ty::Predicate::Projection(ref data) => {
-                let project_obligation = obligation.with(data.clone());
-                match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
-                    Ok(None) => {
-                        let tcx = self.selcx.tcx();
-                        pending_obligation.stalled_on =
-                            trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
-                        ProcessResult::Unchanged
-                    }
-                    Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)),
-                    Err(e) => ProcessResult::Error(CodeProjectionError(e)),
-                }
-            }
-
-            ty::Predicate::ObjectSafe(trait_def_id) => {
-                if !self.selcx.tcx().is_object_safe(trait_def_id) {
-                    ProcessResult::Error(CodeSelectionError(Unimplemented))
-                } else {
-                    ProcessResult::Changed(vec![])
-                }
-            }
-
-            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                match self.selcx.infcx().closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        if closure_kind.extends(kind) {
-                            ProcessResult::Changed(vec![])
-                        } else {
-                            ProcessResult::Error(CodeSelectionError(Unimplemented))
-                        }
-                    }
-                    None => ProcessResult::Unchanged,
-                }
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                match wf::obligations(
-                    self.selcx.infcx(),
-                    obligation.param_env,
-                    obligation.cause.body_id,
-                    ty,
-                    obligation.cause.span,
-                ) {
-                    None => {
-                        pending_obligation.stalled_on = vec![infer_ty(ty)];
-                        ProcessResult::Unchanged
-                    }
-                    Some(os) => ProcessResult::Changed(mk_pending(os)),
-                }
-            }
-
-            ty::Predicate::Subtype(ref subtype) => {
-                match self.selcx.infcx().subtype_predicate(
-                    &obligation.cause,
-                    obligation.param_env,
-                    subtype,
-                ) {
-                    None => {
-                        // None means that both are unresolved.
-                        pending_obligation.stalled_on = vec![
-                            infer_ty(subtype.skip_binder().a),
-                            infer_ty(subtype.skip_binder().b),
-                        ];
-                        ProcessResult::Unchanged
-                    }
-                    Some(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
-                    Some(Err(err)) => {
-                        let expected_found = ExpectedFound::new(
-                            subtype.skip_binder().a_is_expected,
-                            subtype.skip_binder().a,
-                            subtype.skip_binder().b,
-                        );
-                        ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
-                            expected_found,
-                            err,
-                        ))
-                    }
-                }
-            }
-
-            ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.selcx.infcx().const_eval_resolve(
-                    obligation.param_env,
-                    def_id,
-                    substs,
-                    None,
-                    Some(obligation.cause.span),
-                ) {
-                    Ok(_) => ProcessResult::Changed(vec![]),
-                    Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
-                }
-            }
-        }
-    }
-
-    fn process_backedge<'c, I>(
-        &mut self,
-        cycle: I,
-        _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
-    ) where
-        I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
-    {
-        if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
-            debug!("process_child_obligations: coinductive match");
-        } else {
-            let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
-            self.selcx.infcx().report_overflow_error_cycle(&cycle);
-        }
-    }
-}
-
-/// Returns the set of type variables contained in a trait ref
-fn trait_ref_type_vars<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    t: ty::PolyTraitRef<'tcx>,
-) -> Vec<ty::InferTy> {
-    t.skip_binder() // ok b/c this check doesn't care about regions
-        .input_types()
-        .map(|t| selcx.infcx().resolve_vars_if_possible(&t))
-        .filter(|t| t.has_infer_types())
-        .flat_map(|t| t.walk())
-        .filter_map(|t| match t.kind {
-            ty::Infer(infer) => Some(infer),
-            _ => None,
-        })
-        .collect()
-}
-
-fn to_fulfillment_error<'tcx>(
-    error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
-) -> FulfillmentError<'tcx> {
-    let obligation = error.backtrace.into_iter().next().unwrap().obligation;
-    FulfillmentError::new(obligation, error.error)
-}
diff --git a/src/librustc_infer/traits/misc.rs b/src/librustc_infer/traits/misc.rs
deleted file mode 100644
index 7ab918c159e..00000000000
--- a/src/librustc_infer/traits/misc.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-
-use crate::infer::TyCtxtInferExt;
-use crate::traits::{self, ObligationCause};
-
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc_hir as hir;
-
-#[derive(Clone)]
-pub enum CopyImplementationError<'tcx> {
-    InfrigingFields(Vec<&'tcx ty::FieldDef>),
-    NotAnAdt,
-    HasDestructor,
-}
-
-pub fn can_type_implement_copy(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    self_type: Ty<'tcx>,
-) -> Result<(), CopyImplementationError<'tcx>> {
-    // FIXME: (@jroesch) float this code up
-    tcx.infer_ctxt().enter(|infcx| {
-        let (adt, substs) = match self_type.kind {
-            // These types used to have a builtin impl.
-            // Now libcore provides that impl.
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::Char
-            | ty::RawPtr(..)
-            | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => return Ok(()),
-
-            ty::Adt(adt, substs) => (adt, substs),
-
-            _ => return Err(CopyImplementationError::NotAnAdt),
-        };
-
-        let mut infringing = Vec::new();
-        for variant in &adt.variants {
-            for field in &variant.fields {
-                let ty = field.ty(tcx, substs);
-                if ty.references_error() {
-                    continue;
-                }
-                let span = tcx.def_span(field.did);
-                let cause = ObligationCause { span, ..ObligationCause::dummy() };
-                let ctx = traits::FulfillmentContext::new();
-                match traits::fully_normalize(&infcx, ctx, cause, param_env, &ty) {
-                    Ok(ty) => {
-                        if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
-                            infringing.push(field);
-                        }
-                    }
-                    Err(errors) => {
-                        infcx.report_fulfillment_errors(&errors, None, false);
-                    }
-                };
-            }
-        }
-        if !infringing.is_empty() {
-            return Err(CopyImplementationError::InfrigingFields(infringing));
-        }
-        if adt.has_dtor(tcx) {
-            return Err(CopyImplementationError::HasDestructor);
-        }
-
-        Ok(())
-    })
-}
diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs
index 61702d74f1a..758a0b39d43 100644
--- a/src/librustc_infer/traits/mod.rs
+++ b/src/librustc_infer/traits/mod.rs
@@ -2,113 +2,31 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 
-#[allow(dead_code)]
-pub mod auto_trait;
-pub mod codegen;
-mod coherence;
 mod engine;
 pub mod error_reporting;
-mod fulfill;
-pub mod misc;
-mod object_safety;
-mod on_unimplemented;
 mod project;
-pub mod query;
-mod select;
-mod specialize;
 mod structural_impls;
-mod structural_match;
-mod util;
-pub mod wf;
+pub mod util;
 
-use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
-use rustc::middle::region;
-use rustc::ty::error::{ExpectedFound, TypeError};
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
-use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc::util::common::ErrorReported;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::{Span, DUMMY_SP};
-
-use std::fmt::Debug;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::{self, Ty};
+use rustc_span::Span;
 
 pub use self::FulfillmentErrorCode::*;
 pub use self::ObligationCauseCode::*;
 pub use self::SelectionError::*;
 pub use self::Vtable::*;
 
-pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
-pub use self::coherence::{OrphanCheckErr, OverlapResult};
 pub use self::engine::{TraitEngine, TraitEngineExt};
-pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
-pub use self::object_safety::astconv_object_safety_violations;
-pub use self::object_safety::is_vtable_safe_method;
-pub use self::object_safety::MethodViolationCode;
-pub use self::object_safety::ObjectSafetyViolation;
-pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{
-    normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type,
-};
-pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal};
-pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
-pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
-pub use self::specialize::find_associated_item;
-pub use self::specialize::specialization_graph::FutureCompatOverlapError;
-pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
-pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
-pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::type_marked_structural;
-pub use self::structural_match::NonStructuralMatchTy;
-pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
-pub use self::util::{expand_trait_aliases, TraitAliasExpander};
-pub use self::util::{
-    get_vtable_index_of_object_method, impl_is_default, impl_item_is_final,
-    predicate_for_trait_def, upcast_choices,
-};
-pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
+    Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
+    ProjectionCacheSnapshot, Reveal,
 };
+crate use self::util::elaborate_predicates;
 
-pub use rustc::traits::*;
-
-/// Whether to skip the leak check, as part of a future compatibility warning step.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum SkipLeakCheck {
-    Yes,
-    No,
-}
-
-impl SkipLeakCheck {
-    fn is_yes(self) -> bool {
-        self == SkipLeakCheck::Yes
-    }
-}
-
-/// The "default" for skip-leak-check corresponds to the current
-/// behavior (do not skip the leak check) -- not the behavior we are
-/// transitioning into.
-impl Default for SkipLeakCheck {
-    fn default() -> Self {
-        SkipLeakCheck::No
-    }
-}
-
-/// The mode that trait queries run in.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum TraitQueryMode {
-    // Standard/un-canonicalized queries get accurate
-    // spans etc. passed in and hence can do reasonable
-    // error reporting on their own.
-    Standard,
-    // Canonicalized queries get dummy spans and hence
-    // must generally propagate errors to
-    // pre-canonicalization callsites.
-    Canonical,
-}
+pub use rustc_middle::traits::*;
 
 /// An `Obligation` represents some trait reference (e.g., `int: Eq`) for
 /// which the vtable must be found. The process of finding a vtable is
@@ -165,418 +83,6 @@ pub enum FulfillmentErrorCode<'tcx> {
     CodeAmbiguity,
 }
 
-/// Creates predicate obligations from the generic bounds.
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> PredicateObligations<'tcx> {
-    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
-}
-
-/// Determines whether the type `ty` is known to meet `bound` and
-/// returns true if so. Returns false if `ty` either does not meet
-/// `bound` or is not known to meet bound (note that this is
-/// conservative towards *no impl*, which is the opposite of the
-/// `evaluate` methods).
-pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-    def_id: DefId,
-    span: Span,
-) -> bool {
-    debug!(
-        "type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})",
-        ty,
-        infcx.tcx.def_path_str(def_id)
-    );
-
-    let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
-    let obligation = Obligation {
-        param_env,
-        cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
-        recursion_depth: 0,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-
-    let result = infcx.predicate_must_hold_modulo_regions(&obligation);
-    debug!(
-        "type_known_to_meet_ty={:?} bound={} => {:?}",
-        ty,
-        infcx.tcx.def_path_str(def_id),
-        result
-    );
-
-    if result && ty.has_infer_types_or_consts() {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
-
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
-
-        // We can use a dummy node-id here because we won't pay any mind
-        // to region obligations that arise (there shouldn't really be any
-        // anyhow).
-        let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID);
-
-        fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
-
-        // Note: we only assume something is `Copy` if we can
-        // *definitively* show that it implements `Copy`. Otherwise,
-        // assume it is move; linear is always ok.
-        match fulfill_cx.select_all_or_error(infcx) {
-            Ok(()) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success",
-                    ty,
-                    infcx.tcx.def_path_str(def_id)
-                );
-                true
-            }
-            Err(e) => {
-                debug!(
-                    "type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}",
-                    ty,
-                    infcx.tcx.def_path_str(def_id),
-                    e
-                );
-                false
-            }
-        }
-    } else {
-        result
-    }
-}
-
-fn do_normalize_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    cause: ObligationCause<'tcx>,
-    elaborated_env: ty::ParamEnv<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> Result<Vec<ty::Predicate<'tcx>>, ErrorReported> {
-    debug!(
-        "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
-        predicates, region_context, cause,
-    );
-    let span = cause.span;
-    tcx.infer_ctxt().enter(|infcx| {
-        // FIXME. We should really... do something with these region
-        // obligations. But this call just continues the older
-        // behavior (i.e., doesn't cause any new bugs), and it would
-        // take some further refactoring to actually solve them. In
-        // particular, we would have to handle implied bounds
-        // properly, and that code is currently largely confined to
-        // regionck (though I made some efforts to extract it
-        // out). -nmatsakis
-        //
-        // @arielby: In any case, these obligations are checked
-        // by wfcheck anyway, so I'm not sure we have to check
-        // them here too, and we will remove this function when
-        // we move over to lazy normalization *anyway*.
-        let fulfill_cx = FulfillmentContext::new_ignoring_regions();
-        let predicates =
-            match fully_normalize(&infcx, fulfill_cx, cause, elaborated_env, &predicates) {
-                Ok(predicates) => predicates,
-                Err(errors) => {
-                    infcx.report_fulfillment_errors(&errors, None, false);
-                    return Err(ErrorReported);
-                }
-            };
-
-        debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
-
-        let region_scope_tree = region::ScopeTree::default();
-
-        // We can use the `elaborated_env` here; the region code only
-        // cares about declarations like `'a: 'b`.
-        let outlives_env = OutlivesEnvironment::new(elaborated_env);
-
-        infcx.resolve_regions_and_report_errors(
-            region_context,
-            &region_scope_tree,
-            &outlives_env,
-            SuppressRegionErrors::default(),
-        );
-
-        let predicates = match infcx.fully_resolve(&predicates) {
-            Ok(predicates) => predicates,
-            Err(fixup_err) => {
-                // If we encounter a fixup error, it means that some type
-                // variable wound up unconstrained. I actually don't know
-                // if this can happen, and I certainly don't expect it to
-                // happen often, but if it did happen it probably
-                // represents a legitimate failure due to some kind of
-                // unconstrained variable, and it seems better not to ICE,
-                // all things considered.
-                tcx.sess.span_err(span, &fixup_err.to_string());
-                return Err(ErrorReported);
-            }
-        };
-        if predicates.has_local_value() {
-            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
-            Err(ErrorReported)
-        } else {
-            Ok(predicates)
-        }
-    })
-}
-
-// FIXME: this is gonna need to be removed ...
-/// Normalizes the parameter environment, reporting errors if they occur.
-pub fn normalize_param_env_or_error<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    region_context: DefId,
-    unnormalized_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> ty::ParamEnv<'tcx> {
-    // I'm not wild about reporting errors here; I'd prefer to
-    // have the errors get reported at a defined place (e.g.,
-    // during typeck). Instead I have all parameter
-    // environments, in effect, going through this function
-    // and hence potentially reporting errors. This ensures of
-    // course that we never forget to normalize (the
-    // alternative seemed like it would involve a lot of
-    // manual invocations of this fn -- and then we'd have to
-    // deal with the errors at each of those sites).
-    //
-    // In any case, in practice, typeck constructs all the
-    // parameter environments once for every fn as it goes,
-    // and errors will get reported then; so after typeck we
-    // can be sure that no errors should occur.
-
-    debug!(
-        "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})",
-        region_context, unnormalized_env, cause
-    );
-
-    let mut predicates: Vec<_> =
-        util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect();
-
-    debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
-
-    let elaborated_env = ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    );
-
-    // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
-    // normalization expects its param-env to be already normalized, which means we have
-    // a circularity.
-    //
-    // The way we handle this is by normalizing the param-env inside an unnormalized version
-    // of the param-env, which means that if the param-env contains unnormalized projections,
-    // we'll have some normalization failures. This is unfortunate.
-    //
-    // Lazy normalization would basically handle this by treating just the
-    // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
-    //
-    // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
-    // types, so to make the situation less bad, we normalize all the predicates *but*
-    // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
-    // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
-    //
-    // This works fairly well because trait matching  does not actually care about param-env
-    // TypeOutlives predicates - these are normally used by regionck.
-    let outlives_predicates: Vec<_> = predicates
-        .drain_filter(|predicate| match predicate {
-            ty::Predicate::TypeOutlives(..) => true,
-            _ => false,
-        })
-        .collect();
-
-    debug!(
-        "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
-        predicates, outlives_predicates
-    );
-    let non_outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause.clone(),
-        elaborated_env,
-        predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
-            return elaborated_env;
-        }
-    };
-
-    debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
-
-    // Not sure whether it is better to include the unnormalized TypeOutlives predicates
-    // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
-    // predicates here anyway. Keeping them here anyway because it seems safer.
-    let outlives_env: Vec<_> =
-        non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
-    let outlives_env =
-        ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None);
-    let outlives_predicates = match do_normalize_predicates(
-        tcx,
-        region_context,
-        cause,
-        outlives_env,
-        outlives_predicates,
-    ) {
-        Ok(predicates) => predicates,
-        // An unnormalized env is better than nothing.
-        Err(ErrorReported) => {
-            debug!("normalize_param_env_or_error: errored resolving outlives predicates");
-            return elaborated_env;
-        }
-    };
-    debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
-
-    let mut predicates = non_outlives_predicates;
-    predicates.extend(outlives_predicates);
-    debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
-    ty::ParamEnv::new(
-        tcx.intern_predicates(&predicates),
-        unnormalized_env.reveal,
-        unnormalized_env.def_id,
-    )
-}
-
-pub fn fully_normalize<'a, 'tcx, T>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    mut fulfill_cx: FulfillmentContext<'tcx>,
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    value: &T,
-) -> Result<T, Vec<FulfillmentError<'tcx>>>
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("fully_normalize_with_fulfillcx(value={:?})", value);
-    let selcx = &mut SelectionContext::new(infcx);
-    let Normalized { value: normalized_value, obligations } =
-        project::normalize(selcx, param_env, cause, value);
-    debug!(
-        "fully_normalize: normalized_value={:?} obligations={:?}",
-        normalized_value, obligations
-    );
-    for obligation in obligations {
-        fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
-    }
-
-    debug!("fully_normalize: select_all_or_error start");
-    fulfill_cx.select_all_or_error(infcx)?;
-    debug!("fully_normalize: select_all_or_error complete");
-    let resolved_value = infcx.resolve_vars_if_possible(&normalized_value);
-    debug!("fully_normalize: resolved_value={:?}", resolved_value);
-    Ok(resolved_value)
-}
-
-/// Normalizes the predicates and checks whether they hold in an empty
-/// environment. If this returns false, then either normalize
-/// encountered an error or one of the predicates did not hold. Used
-/// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    predicates: Vec<ty::Predicate<'tcx>>,
-) -> bool {
-    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
-
-    let result = tcx.infer_ctxt().enter(|infcx| {
-        let param_env = ty::ParamEnv::reveal_all();
-        let mut selcx = SelectionContext::new(&infcx);
-        let mut fulfill_cx = FulfillmentContext::new();
-        let cause = ObligationCause::dummy();
-        let Normalized { value: predicates, obligations } =
-            normalize(&mut selcx, param_env, cause.clone(), &predicates);
-        for obligation in obligations {
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-        for predicate in predicates {
-            let obligation = Obligation::new(cause.clone(), param_env, predicate);
-            fulfill_cx.register_predicate_obligation(&infcx, obligation);
-        }
-
-        fulfill_cx.select_all_or_error(&infcx).is_ok()
-    });
-    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
-    result
-}
-
-fn substitute_normalize_and_test_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (DefId, SubstsRef<'tcx>),
-) -> bool {
-    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
-
-    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    let result = normalize_and_test_predicates(tcx, predicates);
-
-    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
-    result
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-#[inline] // FIXME(#35870): avoid closures being unexported due to `impl Trait`.
-fn vtable_methods<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
-    debug!("vtable_methods({:?})", trait_ref);
-
-    tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
-        let trait_methods = tcx
-            .associated_items(trait_ref.def_id())
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Method);
-
-        // Now list each method's DefId and InternalSubsts (for within its trait).
-        // If the method can never be called from this object, produce None.
-        trait_methods.map(move |trait_method| {
-            debug!("vtable_methods: trait_method={:?}", trait_method);
-            let def_id = trait_method.def_id;
-
-            // Some methods cannot be called on an object; skip those.
-            if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                debug!("vtable_methods: not vtable safe");
-                return None;
-            }
-
-            // The method may have some early-bound lifetimes; add regions for those.
-            let substs = trait_ref.map_bound(|trait_ref| {
-                InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                        trait_ref.substs[param.index as usize]
-                    }
-                })
-            });
-
-            // The trait type may have higher-ranked lifetimes in it;
-            // erase them if they appear, so that we get the type
-            // at some particular call site.
-            let substs =
-                tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &substs);
-
-            // It's possible that the method relies on where-clauses that
-            // do not hold for this particular set of type parameters.
-            // Note that this method could then never be called, so we
-            // do not want to try and codegen it, in that case (see #23435).
-            let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-            if !normalize_and_test_predicates(tcx, predicates.predicates) {
-                debug!("vtable_methods: predicates do not hold");
-                return None;
-            }
-
-            Some((def_id, substs))
-        })
-    }))
-}
-
 impl<'tcx, O> Obligation<'tcx, O> {
     pub fn new(
         cause: ObligationCause<'tcx>,
@@ -586,7 +92,7 @@ impl<'tcx, O> Obligation<'tcx, O> {
         Obligation { cause, param_env, recursion_depth: 0, predicate }
     }
 
-    fn with_depth(
+    pub fn with_depth(
         cause: ObligationCause<'tcx>,
         recursion_depth: usize,
         param_env: ty::ParamEnv<'tcx>,
@@ -615,28 +121,16 @@ impl<'tcx, O> Obligation<'tcx, O> {
 }
 
 impl<'tcx> FulfillmentError<'tcx> {
-    fn new(
+    pub fn new(
         obligation: PredicateObligation<'tcx>,
         code: FulfillmentErrorCode<'tcx>,
     ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false }
+        FulfillmentError { obligation, code, points_at_arg_span: false }
     }
 }
 
 impl<'tcx> TraitObligation<'tcx> {
-    fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
+    pub fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
         self.predicate.map_bound(|p| p.self_ty())
     }
 }
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    object_safety::provide(providers);
-    *providers = ty::query::Providers {
-        specialization_graph_of: specialize::specialization_graph_provider,
-        specializes: specialize::specializes,
-        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
-        vtable_methods,
-        substitute_normalize_and_test_predicates,
-        ..*providers
-    };
-}
diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs
deleted file mode 100644
index f5bab7cfac9..00000000000
--- a/src/librustc_infer/traits/object_safety.rs
+++ /dev/null
@@ -1,777 +0,0 @@
-//! "Object safety" refers to the ability for a trait to be converted
-//! to an object. In general, traits may only be converted to an
-//! object if all of their methods meet certain criteria. In particular,
-//! they must:
-//!
-//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
-//!     that doesn't contain the vtable;
-//!   - not reference the erased type `Self` except for in this receiver;
-//!   - not have generic type parameters.
-
-use super::elaborate_predicates;
-
-use crate::infer::TyCtxtInferExt;
-use crate::traits::{self, Obligation, ObligationCause};
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use smallvec::SmallVec;
-
-use std::iter;
-
-pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
-
-/// Returns the object safety violations that affect
-/// astconv -- currently, `Self` in supertraits. This is needed
-/// because `object_safety_violations` can't be used during
-/// type collection.
-pub fn astconv_object_safety_violations(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    let violations = traits::supertrait_def_ids(tcx, trait_def_id)
-        .map(|def_id| predicates_reference_self(tcx, def_id, true))
-        .filter(|spans| !spans.is_empty())
-        .map(|spans| ObjectSafetyViolation::SupertraitSelf(spans))
-        .collect();
-
-    debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}", trait_def_id, violations);
-
-    violations
-}
-
-fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    debug!("object_safety_violations: {:?}", trait_def_id);
-
-    traits::supertrait_def_ids(tcx, trait_def_id)
-        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
-        .collect()
-}
-
-/// We say a method is *vtable safe* if it can be invoked on a trait
-/// object. Note that object-safe traits can have some
-/// non-vtable-safe methods, so long as they require `Self: Sized` or
-/// otherwise ensure that they cannot be used when `Self = Trait`.
-pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
-    debug_assert!(tcx.generics_of(trait_def_id).has_self);
-    debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
-    // Any method that has a `Self: Sized` bound cannot be called.
-    if generics_require_sized_self(tcx, method.def_id) {
-        return false;
-    }
-
-    match virtual_call_violation_for_method(tcx, trait_def_id, method) {
-        None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
-        Some(_) => false,
-    }
-}
-
-fn object_safety_violations_for_trait(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
-    // Check methods for violations.
-    let mut violations: Vec<_> = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter(|item| item.kind == ty::AssocKind::Method)
-        .filter_map(|item| {
-            object_safety_violation_for_method(tcx, trait_def_id, &item)
-                .map(|(code, span)| ObjectSafetyViolation::Method(item.ident.name, code, span))
-        })
-        .filter(|violation| {
-            if let ObjectSafetyViolation::Method(
-                _,
-                MethodViolationCode::WhereClauseReferencesSelf,
-                span,
-            ) = violation
-            {
-                // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
-                // It's also hard to get a use site span, so we use the method definition span.
-                tcx.struct_span_lint_hir(
-                    WHERE_CLAUSES_OBJECT_SAFETY,
-                    hir::CRATE_HIR_ID,
-                    *span,
-                    |lint| {
-                        let mut err = lint.build(&format!(
-                            "the trait `{}` cannot be made into an object",
-                            tcx.def_path_str(trait_def_id)
-                        ));
-                        let node = tcx.hir().get_if_local(trait_def_id);
-                        let msg = if let Some(hir::Node::Item(item)) = node {
-                            err.span_label(
-                                item.ident.span,
-                                "this trait cannot be made into an object...",
-                            );
-                            format!("...because {}", violation.error_msg())
-                        } else {
-                            format!(
-                                "the trait cannot be made into an object because {}",
-                                violation.error_msg()
-                            )
-                        };
-                        err.span_label(*span, &msg);
-                        match (node, violation.solution()) {
-                            (Some(_), Some((note, None))) => {
-                                err.help(&note);
-                            }
-                            (Some(_), Some((note, Some((sugg, span))))) => {
-                                err.span_suggestion(
-                                    span,
-                                    &note,
-                                    sugg,
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                            // Only provide the help if its a local trait, otherwise it's not actionable.
-                            _ => {}
-                        }
-                        err.emit();
-                    },
-                );
-                false
-            } else {
-                true
-            }
-        })
-        .collect();
-
-    // Check the trait itself.
-    if trait_has_sized_self(tcx, trait_def_id) {
-        // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
-        let spans = get_sized_bounds(tcx, trait_def_id);
-        violations.push(ObjectSafetyViolation::SizedSelf(spans));
-    }
-    let spans = predicates_reference_self(tcx, trait_def_id, false);
-    if !spans.is_empty() {
-        violations.push(ObjectSafetyViolation::SupertraitSelf(spans));
-    }
-
-    violations.extend(
-        tcx.associated_items(trait_def_id)
-            .in_definition_order()
-            .filter(|item| item.kind == ty::AssocKind::Const)
-            .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
-    );
-
-    debug!(
-        "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
-        trait_def_id, violations
-    );
-
-    violations
-}
-
-fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    tcx.hir()
-        .get_if_local(trait_def_id)
-        .and_then(|node| match node {
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Trait(.., generics, bounds, _),
-                ..
-            }) => Some(
-                generics
-                    .where_clause
-                    .predicates
-                    .iter()
-                    .filter_map(|pred| {
-                        match pred {
-                            hir::WherePredicate::BoundPredicate(pred)
-                                if pred.bounded_ty.hir_id.owner_def_id() == trait_def_id =>
-                            {
-                                // Fetch spans for trait bounds that are Sized:
-                                // `trait T where Self: Pred`
-                                Some(pred.bounds.iter().filter_map(|b| match b {
-                                    hir::GenericBound::Trait(
-                                        trait_ref,
-                                        hir::TraitBoundModifier::None,
-                                    ) if trait_has_sized_self(
-                                        tcx,
-                                        trait_ref.trait_ref.trait_def_id(),
-                                    ) =>
-                                    {
-                                        Some(trait_ref.span)
-                                    }
-                                    _ => None,
-                                }))
-                            }
-                            _ => None,
-                        }
-                    })
-                    .flatten()
-                    .chain(bounds.iter().filter_map(|b| match b {
-                        hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
-                            if trait_has_sized_self(tcx, trait_ref.trait_ref.trait_def_id()) =>
-                        {
-                            // Fetch spans for supertraits that are `Sized`: `trait T: Super`
-                            Some(trait_ref.span)
-                        }
-                        _ => None,
-                    }))
-                    .collect::<SmallVec<[Span; 1]>>(),
-            ),
-            _ => None,
-        })
-        .unwrap_or_else(SmallVec::new)
-}
-
-fn predicates_reference_self(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-    supertraits_only: bool,
-) -> SmallVec<[Span; 1]> {
-    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
-    let predicates = if supertraits_only {
-        tcx.super_predicates_of(trait_def_id)
-    } else {
-        tcx.predicates_of(trait_def_id)
-    };
-    let self_ty = tcx.types.self_param;
-    let has_self_ty = |t: Ty<'_>| t.walk().any(|t| t == self_ty);
-    predicates
-        .predicates
-        .iter()
-        .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
-        .filter_map(|(predicate, &sp)| {
-            match predicate {
-                ty::Predicate::Trait(ref data, _) => {
-                    // In the case of a trait predicate, we can skip the "self" type.
-                    if data.skip_binder().input_types().skip(1).any(has_self_ty) {
-                        Some(sp)
-                    } else {
-                        None
-                    }
-                }
-                ty::Predicate::Projection(ref data) => {
-                    // And similarly for projections. This should be redundant with
-                    // the previous check because any projection should have a
-                    // matching `Trait` predicate with the same inputs, but we do
-                    // the check to be safe.
-                    //
-                    // Note that we *do* allow projection *outputs* to contain
-                    // `self` (i.e., `trait Foo: Bar<Output=Self::Result> { type Result; }`),
-                    // we just require the user to specify *both* outputs
-                    // in the object type (i.e., `dyn Foo<Output=(), Result=()>`).
-                    //
-                    // This is ALT2 in issue #56288, see that for discussion of the
-                    // possible alternatives.
-                    if data
-                        .skip_binder()
-                        .projection_ty
-                        .trait_ref(tcx)
-                        .input_types()
-                        .skip(1)
-                        .any(has_self_ty)
-                    {
-                        Some(sp)
-                    } else {
-                        None
-                    }
-                }
-                ty::Predicate::WellFormed(..)
-                | ty::Predicate::ObjectSafe(..)
-                | ty::Predicate::TypeOutlives(..)
-                | ty::Predicate::RegionOutlives(..)
-                | ty::Predicate::ClosureKind(..)
-                | ty::Predicate::Subtype(..)
-                | ty::Predicate::ConstEvaluatable(..) => None,
-            }
-        })
-        .collect()
-}
-
-fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    generics_require_sized_self(tcx, trait_def_id)
-}
-
-fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    let sized_def_id = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => {
-            return false; /* No Sized trait, can't require it! */
-        }
-    };
-
-    // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let predicates = tcx.predicates_of(def_id);
-    let predicates = predicates.instantiate_identity(tcx).predicates;
-    elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
-        ty::Predicate::Trait(ref trait_pred, _) => {
-            trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
-        }
-        ty::Predicate::Projection(..)
-        | ty::Predicate::Subtype(..)
-        | ty::Predicate::RegionOutlives(..)
-        | ty::Predicate::WellFormed(..)
-        | ty::Predicate::ObjectSafe(..)
-        | ty::Predicate::ClosureKind(..)
-        | ty::Predicate::TypeOutlives(..)
-        | ty::Predicate::ConstEvaluatable(..) => false,
-    })
-}
-
-/// Returns `Some(_)` if this method makes the containing trait not object safe.
-fn object_safety_violation_for_method(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-    method: &ty::AssocItem,
-) -> Option<(MethodViolationCode, Span)> {
-    debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
-    // Any method that has a `Self : Sized` requisite is otherwise
-    // exempt from the regulations.
-    if generics_require_sized_self(tcx, method.def_id) {
-        return None;
-    }
-
-    let violation = virtual_call_violation_for_method(tcx, trait_def_id, method);
-    // Get an accurate span depending on the violation.
-    violation.map(|v| {
-        let node = tcx.hir().get_if_local(method.def_id);
-        let span = match (v, node) {
-            (MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(arg + 1))
-                .map_or(method.ident.span, |arg| arg.span),
-            (MethodViolationCode::UndispatchableReceiver, Some(node)) => node
-                .fn_decl()
-                .and_then(|decl| decl.inputs.get(0))
-                .map_or(method.ident.span, |arg| arg.span),
-            (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
-                node.fn_decl().map_or(method.ident.span, |decl| decl.output.span())
-            }
-            _ => method.ident.span,
-        };
-        (v, span)
-    })
-}
-
-/// Returns `Some(_)` if this method cannot be called on a trait
-/// object; this does not necessarily imply that the enclosing trait
-/// is not object safe, because the method might have a where clause
-/// `Self:Sized`.
-fn virtual_call_violation_for_method<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    method: &ty::AssocItem,
-) -> Option<MethodViolationCode> {
-    // The method's first parameter must be named `self`
-    if !method.method_has_self_argument {
-        // We'll attempt to provide a structured suggestion for `Self: Sized`.
-        let sugg =
-            tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
-                |generics| match generics.where_clause.predicates {
-                    [] => (" where Self: Sized", generics.where_clause.span),
-                    [.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
-                },
-            );
-        return Some(MethodViolationCode::StaticMethod(sugg));
-    }
-
-    let sig = tcx.fn_sig(method.def_id);
-
-    for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
-        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
-            return Some(MethodViolationCode::ReferencesSelfInput(i));
-        }
-    }
-    if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
-        return Some(MethodViolationCode::ReferencesSelfOutput);
-    }
-
-    // We can't monomorphize things like `fn foo<A>(...)`.
-    let own_counts = tcx.generics_of(method.def_id).own_counts();
-    if own_counts.types + own_counts.consts != 0 {
-        return Some(MethodViolationCode::Generic);
-    }
-
-    if tcx
-        .predicates_of(method.def_id)
-        .predicates
-        .iter()
-        // A trait object can't claim to live more than the concrete type,
-        // so outlives predicates will always hold.
-        .cloned()
-        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
-        .collect::<Vec<_>>()
-        // Do a shallow visit so that `contains_illegal_self_type_reference`
-        // may apply it's custom visiting.
-        .visit_tys_shallow(|t| contains_illegal_self_type_reference(tcx, trait_def_id, t))
-    {
-        return Some(MethodViolationCode::WhereClauseReferencesSelf);
-    }
-
-    let receiver_ty =
-        tcx.liberate_late_bound_regions(method.def_id, &sig.map_bound(|sig| sig.inputs()[0]));
-
-    // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
-    // However, this is already considered object-safe. We allow it as a special case here.
-    // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
-    // `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
-    if receiver_ty != tcx.types.self_param {
-        if !receiver_is_dispatchable(tcx, method, receiver_ty) {
-            return Some(MethodViolationCode::UndispatchableReceiver);
-        } else {
-            // Do sanity check to make sure the receiver actually has the layout of a pointer.
-
-            use rustc::ty::layout::Abi;
-
-            let param_env = tcx.param_env(method.def_id);
-
-            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
-                match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => &layout.abi,
-                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
-                }
-            };
-
-            // e.g., `Rc<()>`
-            let unit_receiver_ty =
-                receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
-
-            match abi_of_ty(unit_receiver_ty) {
-                &Abi::Scalar(..) => (),
-                abi => {
-                    tcx.sess.delay_span_bug(
-                        tcx.def_span(method.def_id),
-                        &format!(
-                            "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
-                            abi
-                        ),
-                    );
-                }
-            }
-
-            let trait_object_ty =
-                object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
-
-            // e.g., `Rc<dyn Trait>`
-            let trait_object_receiver =
-                receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
-
-            match abi_of_ty(trait_object_receiver) {
-                &Abi::ScalarPair(..) => (),
-                abi => {
-                    tcx.sess.delay_span_bug(
-                        tcx.def_span(method.def_id),
-                        &format!(
-                            "receiver when `Self = {}` should have a ScalarPair ABI; \
-                                 found {:?}",
-                            trait_object_ty, abi
-                        ),
-                    );
-                }
-            }
-        }
-    }
-
-    None
-}
-
-/// Performs a type substitution to produce the version of `receiver_ty` when `Self = self_ty`.
-/// For example, for `receiver_ty = Rc<Self>` and `self_ty = Foo`, returns `Rc<Foo>`.
-fn receiver_for_self_ty<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    receiver_ty: Ty<'tcx>,
-    self_ty: Ty<'tcx>,
-    method_def_id: DefId,
-) -> Ty<'tcx> {
-    debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
-    let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
-        if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
-    });
-
-    let result = receiver_ty.subst(tcx, substs);
-    debug!(
-        "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
-        receiver_ty, self_ty, method_def_id, result
-    );
-    result
-}
-
-/// Creates the object type for the current trait. For example,
-/// if the current trait is `Deref`, then this will be
-/// `dyn Deref<Target = Self::Target> + 'static`.
-fn object_ty_for_trait<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    lifetime: ty::Region<'tcx>,
-) -> Ty<'tcx> {
-    debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
-
-    let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
-
-    let trait_predicate =
-        ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
-
-    let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
-        .flat_map(|super_trait_ref| {
-            tcx.associated_items(super_trait_ref.def_id())
-                .in_definition_order()
-                .map(move |item| (super_trait_ref, item))
-        })
-        .filter(|(_, item)| item.kind == ty::AssocKind::Type)
-        .collect::<Vec<_>>();
-
-    // existential predicates need to be in a specific order
-    associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id));
-
-    let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
-        // We *can* get bound lifetimes here in cases like
-        // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
-        //
-        // binder moved to (*)...
-        let super_trait_ref = super_trait_ref.skip_binder();
-        ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
-            ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
-            item_def_id: item.def_id,
-            substs: super_trait_ref.substs,
-        })
-    });
-
-    let existential_predicates =
-        tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
-
-    let object_ty = tcx.mk_dynamic(
-        // (*) ... binder re-introduced here
-        ty::Binder::bind(existential_predicates),
-        lifetime,
-    );
-
-    debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
-
-    object_ty
-}
-
-/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
-/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
-/// in the following way:
-/// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`,
-/// - require the following bound:
-///
-///   ```
-///   Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
-///   ```
-///
-///   where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
-///   (substitution notation).
-///
-/// Some examples of receiver types and their required obligation:
-/// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`,
-/// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`,
-/// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`.
-///
-/// The only case where the receiver is not dispatchable, but is still a valid receiver
-/// type (just not object-safe), is when there is more than one level of pointer indirection.
-/// E.g., `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
-/// is no way, or at least no inexpensive way, to coerce the receiver from the version where
-/// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
-/// contained by the trait object, because the object that needs to be coerced is behind
-/// a pointer.
-///
-/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
-/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
-/// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561).
-/// Instead, we fudge a little by introducing a new type parameter `U` such that
-/// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
-/// Written as a chalk-style query:
-///
-///     forall (U: Trait + ?Sized) {
-///         if (Self: Unsize<U>) {
-///             Receiver: DispatchFromDyn<Receiver[Self => U]>
-///         }
-///     }
-///
-/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
-/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
-/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
-//
-// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
-// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
-// `self: Wrapper<Self>`.
-#[allow(dead_code)]
-fn receiver_is_dispatchable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    method: &ty::AssocItem,
-    receiver_ty: Ty<'tcx>,
-) -> bool {
-    debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
-
-    let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
-    let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
-        (u, cu)
-    } else {
-        debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
-        return false;
-    };
-
-    // the type `U` in the query
-    // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
-    // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
-    // replace this with `dyn Trait`
-    let unsized_self_ty: Ty<'tcx> =
-        tcx.mk_ty_param(::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"));
-
-    // `Receiver[Self => U]`
-    let unsized_receiver_ty =
-        receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
-
-    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
-    // `U: ?Sized` is already implied here
-    let param_env = {
-        let mut param_env = tcx.param_env(method.def_id);
-
-        // Self: Unsize<U>
-        let unsize_predicate = ty::TraitRef {
-            def_id: unsize_did,
-            substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
-        }
-        .without_const()
-        .to_predicate();
-
-        // U: Trait<Arg1, ..., ArgN>
-        let trait_predicate = {
-            let substs =
-                InternalSubsts::for_item(tcx, method.container.assert_trait(), |param, _| {
-                    if param.index == 0 {
-                        unsized_self_ty.into()
-                    } else {
-                        tcx.mk_param_from_def(param)
-                    }
-                });
-
-            ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
-        };
-
-        let caller_bounds: Vec<Predicate<'tcx>> = param_env
-            .caller_bounds
-            .iter()
-            .cloned()
-            .chain(iter::once(unsize_predicate))
-            .chain(iter::once(trait_predicate))
-            .collect();
-
-        param_env.caller_bounds = tcx.intern_predicates(&caller_bounds);
-
-        param_env
-    };
-
-    // Receiver: DispatchFromDyn<Receiver[Self => U]>
-    let obligation = {
-        let predicate = ty::TraitRef {
-            def_id: dispatch_from_dyn_did,
-            substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
-        }
-        .without_const()
-        .to_predicate();
-
-        Obligation::new(ObligationCause::dummy(), param_env, predicate)
-    };
-
-    tcx.infer_ctxt().enter(|ref infcx| {
-        // the receiver is dispatchable iff the obligation holds
-        infcx.predicate_must_hold_modulo_regions(&obligation)
-    })
-}
-
-fn contains_illegal_self_type_reference<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_def_id: DefId,
-    ty: Ty<'tcx>,
-) -> bool {
-    // This is somewhat subtle. In general, we want to forbid
-    // references to `Self` in the argument and return types,
-    // since the value of `Self` is erased. However, there is one
-    // exception: it is ok to reference `Self` in order to access
-    // an associated type of the current trait, since we retain
-    // the value of those associated types in the object type
-    // itself.
-    //
-    // ```rust
-    // trait SuperTrait {
-    //     type X;
-    // }
-    //
-    // trait Trait : SuperTrait {
-    //     type Y;
-    //     fn foo(&self, x: Self) // bad
-    //     fn foo(&self) -> Self // bad
-    //     fn foo(&self) -> Option<Self> // bad
-    //     fn foo(&self) -> Self::Y // OK, desugars to next example
-    //     fn foo(&self) -> <Self as Trait>::Y // OK
-    //     fn foo(&self) -> Self::X // OK, desugars to next example
-    //     fn foo(&self) -> <Self as SuperTrait>::X // OK
-    // }
-    // ```
-    //
-    // However, it is not as simple as allowing `Self` in a projected
-    // type, because there are illegal ways to use `Self` as well:
-    //
-    // ```rust
-    // trait Trait : SuperTrait {
-    //     ...
-    //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
-    // }
-    // ```
-    //
-    // Here we will not have the type of `X` recorded in the
-    // object type, and we cannot resolve `Self as SomeOtherTrait`
-    // without knowing what `Self` is.
-
-    let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
-    let mut error = false;
-    let self_ty = tcx.types.self_param;
-    ty.maybe_walk(|ty| {
-        match ty.kind {
-            ty::Param(_) => {
-                if ty == self_ty {
-                    error = true;
-                }
-
-                false // no contained types to walk
-            }
-
-            ty::Projection(ref data) => {
-                // This is a projected type `<Foo as SomeTrait>::X`.
-
-                // Compute supertraits of current trait lazily.
-                if supertraits.is_none() {
-                    let trait_ref = ty::Binder::bind(ty::TraitRef::identity(tcx, trait_def_id));
-                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
-                }
-
-                // Determine whether the trait reference `Foo as
-                // SomeTrait` is in fact a supertrait of the
-                // current trait. In that case, this type is
-                // legal, because the type `X` will be specified
-                // in the object type.  Note that we can just use
-                // direct equality here because all of these types
-                // are part of the formal parameter listing, and
-                // hence there should be no inference variables.
-                let projection_trait_ref = ty::Binder::bind(data.trait_ref(tcx));
-                let is_supertrait_of_current_trait =
-                    supertraits.as_ref().unwrap().contains(&projection_trait_ref);
-
-                if is_supertrait_of_current_trait {
-                    false // do not walk contained types, do not report error, do collect $200
-                } else {
-                    true // DO walk contained types, POSSIBLY reporting an error
-                }
-            }
-
-            _ => true, // walk contained types, if any
-        }
-    });
-
-    error
-}
-
-pub fn provide(providers: &mut ty::query::Providers<'_>) {
-    *providers = ty::query::Providers { object_safety_violations, ..*providers };
-}
diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_infer/traits/on_unimplemented.rs
deleted file mode 100644
index 19260293ee6..00000000000
--- a/src/librustc_infer/traits/on_unimplemented.rs
+++ /dev/null
@@ -1,383 +0,0 @@
-use fmt_macros::{Parser, Piece, Position};
-
-use rustc::ty::{self, GenericParamDefKind, TyCtxt};
-use rustc::util::common::ErrorReported;
-
-use rustc_ast::ast::{MetaItem, NestedMetaItem};
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::struct_span_err;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
-
-#[derive(Clone, Debug)]
-pub struct OnUnimplementedFormatString(Symbol);
-
-#[derive(Debug)]
-pub struct OnUnimplementedDirective {
-    pub condition: Option<MetaItem>,
-    pub subcommands: Vec<OnUnimplementedDirective>,
-    pub message: Option<OnUnimplementedFormatString>,
-    pub label: Option<OnUnimplementedFormatString>,
-    pub note: Option<OnUnimplementedFormatString>,
-    pub enclosing_scope: Option<OnUnimplementedFormatString>,
-}
-
-#[derive(Default)]
-pub struct OnUnimplementedNote {
-    pub message: Option<String>,
-    pub label: Option<String>,
-    pub note: Option<String>,
-    pub enclosing_scope: Option<String>,
-}
-
-fn parse_error(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    message: &str,
-    label: &str,
-    note: Option<&str>,
-) -> ErrorReported {
-    let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
-    diag.span_label(span, label);
-    if let Some(note) = note {
-        diag.note(note);
-    }
-    diag.emit();
-    ErrorReported
-}
-
-impl<'tcx> OnUnimplementedDirective {
-    fn parse(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        items: &[NestedMetaItem],
-        span: Span,
-        is_root: bool,
-    ) -> Result<Self, ErrorReported> {
-        let mut errored = false;
-        let mut item_iter = items.iter();
-
-        let condition = if is_root {
-            None
-        } else {
-            let cond = item_iter
-                .next()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "empty `on`-clause in `#[rustc_on_unimplemented]`",
-                        "empty on-clause here",
-                        None,
-                    )
-                })?
-                .meta_item()
-                .ok_or_else(|| {
-                    parse_error(
-                        tcx,
-                        span,
-                        "invalid `on`-clause in `#[rustc_on_unimplemented]`",
-                        "invalid on-clause here",
-                        None,
-                    )
-                })?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
-            Some(cond.clone())
-        };
-
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut enclosing_scope = None;
-        let mut subcommands = vec![];
-
-        let parse_value = |value_str| {
-            OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
-        };
-
-        for item in item_iter {
-            if item.check_name(sym::message) && message.is_none() {
-                if let Some(message_) = item.value_str() {
-                    message = parse_value(message_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::label) && label.is_none() {
-                if let Some(label_) = item.value_str() {
-                    label = parse_value(label_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::note) && note.is_none() {
-                if let Some(note_) = item.value_str() {
-                    note = parse_value(note_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::enclosing_scope) && enclosing_scope.is_none() {
-                if let Some(enclosing_scope_) = item.value_str() {
-                    enclosing_scope = parse_value(enclosing_scope_)?;
-                    continue;
-                }
-            } else if item.check_name(sym::on)
-                && is_root
-                && message.is_none()
-                && label.is_none()
-                && note.is_none()
-            {
-                if let Some(items) = item.meta_item_list() {
-                    if let Ok(subcommand) =
-                        Self::parse(tcx, trait_def_id, &items, item.span(), false)
-                    {
-                        subcommands.push(subcommand);
-                    } else {
-                        errored = true;
-                    }
-                    continue;
-                }
-            }
-
-            // nothing found
-            parse_error(
-                tcx,
-                item.span(),
-                "this attribute must have a valid value",
-                "expected value here",
-                Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
-            );
-        }
-
-        if errored {
-            Err(ErrorReported)
-        } else {
-            Ok(OnUnimplementedDirective {
-                condition,
-                subcommands,
-                message,
-                label,
-                note,
-                enclosing_scope,
-            })
-        }
-    }
-
-    pub fn of_item(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        impl_def_id: DefId,
-    ) -> Result<Option<Self>, ErrorReported> {
-        let attrs = tcx.get_attrs(impl_def_id);
-
-        let attr = if let Some(item) = attr::find_by_name(&attrs, sym::rustc_on_unimplemented) {
-            item
-        } else {
-            return Ok(None);
-        };
-
-        let result = if let Some(items) = attr.meta_item_list() {
-            Self::parse(tcx, trait_def_id, &items, attr.span, true).map(Some)
-        } else if let Some(value) = attr.value_str() {
-            Ok(Some(OnUnimplementedDirective {
-                condition: None,
-                message: None,
-                subcommands: vec![],
-                label: Some(OnUnimplementedFormatString::try_parse(
-                    tcx,
-                    trait_def_id,
-                    value,
-                    attr.span,
-                )?),
-                note: None,
-                enclosing_scope: None,
-            }))
-        } else {
-            return Err(ErrorReported);
-        };
-        debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
-        result
-    }
-
-    pub fn evaluate(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &[(Symbol, Option<String>)],
-    ) -> OnUnimplementedNote {
-        let mut message = None;
-        let mut label = None;
-        let mut note = None;
-        let mut enclosing_scope = None;
-        info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
-
-        for command in self.subcommands.iter().chain(Some(self)).rev() {
-            if let Some(ref condition) = command.condition {
-                if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    c.ident().map_or(false, |ident| {
-                        options.contains(&(ident.name, c.value_str().map(|s| s.to_string())))
-                    })
-                }) {
-                    debug!("evaluate: skipping {:?} due to condition", command);
-                    continue;
-                }
-            }
-            debug!("evaluate: {:?} succeeded", command);
-            if let Some(ref message_) = command.message {
-                message = Some(message_.clone());
-            }
-
-            if let Some(ref label_) = command.label {
-                label = Some(label_.clone());
-            }
-
-            if let Some(ref note_) = command.note {
-                note = Some(note_.clone());
-            }
-
-            if let Some(ref enclosing_scope_) = command.enclosing_scope {
-                enclosing_scope = Some(enclosing_scope_.clone());
-            }
-        }
-
-        let options: FxHashMap<Symbol, String> =
-            options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
-        OnUnimplementedNote {
-            label: label.map(|l| l.format(tcx, trait_ref, &options)),
-            message: message.map(|m| m.format(tcx, trait_ref, &options)),
-            note: note.map(|n| n.format(tcx, trait_ref, &options)),
-            enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
-        }
-    }
-}
-
-impl<'tcx> OnUnimplementedFormatString {
-    fn try_parse(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        from: Symbol,
-        err_sp: Span,
-    ) -> Result<Self, ErrorReported> {
-        let result = OnUnimplementedFormatString(from);
-        result.verify(tcx, trait_def_id, err_sp)?;
-        Ok(result)
-    }
-
-    fn verify(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        span: Span,
-    ) -> Result<(), ErrorReported> {
-        let name = tcx.item_name(trait_def_id);
-        let generics = tcx.generics_of(trait_def_id);
-        let s = self.0.as_str();
-        let parser = Parser::new(&s, None, vec![], false);
-        let mut result = Ok(());
-        for token in parser {
-            match token {
-                Piece::String(_) => (), // Normal string, no need to check it
-                Piece::NextArgument(a) => match a.position {
-                    // `{Self}` is allowed
-                    Position::ArgumentNamed(s) if s == kw::SelfUpper => (),
-                    // `{ThisTraitsName}` is allowed
-                    Position::ArgumentNamed(s) if s == name => (),
-                    // `{from_method}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::from_method => (),
-                    // `{from_desugaring}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
-                    // `{ItemContext}` is allowed
-                    Position::ArgumentNamed(s) if s == sym::item_context => (),
-                    // So is `{A}` if A is a type parameter
-                    Position::ArgumentNamed(s) => {
-                        match generics.params.iter().find(|param| param.name == s) {
-                            Some(_) => (),
-                            None => {
-                                struct_span_err!(
-                                    tcx.sess,
-                                    span,
-                                    E0230,
-                                    "there is no parameter `{}` on trait `{}`",
-                                    s,
-                                    name
-                                )
-                                .emit();
-                                result = Err(ErrorReported);
-                            }
-                        }
-                    }
-                    // `{:1}` and `{}` are not to be used
-                    Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
-                        struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0231,
-                            "only named substitution parameters are allowed"
-                        )
-                        .emit();
-                        result = Err(ErrorReported);
-                    }
-                },
-            }
-        }
-
-        result
-    }
-
-    pub fn format(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        options: &FxHashMap<Symbol, String>,
-    ) -> String {
-        let name = tcx.item_name(trait_ref.def_id);
-        let trait_str = tcx.def_path_str(trait_ref.def_id);
-        let generics = tcx.generics_of(trait_ref.def_id);
-        let generic_map = generics
-            .params
-            .iter()
-            .filter_map(|param| {
-                let value = match param.kind {
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                        trait_ref.substs[param.index as usize].to_string()
-                    }
-                    GenericParamDefKind::Lifetime => return None,
-                };
-                let name = param.name;
-                Some((name, value))
-            })
-            .collect::<FxHashMap<Symbol, String>>();
-        let empty_string = String::new();
-
-        let s = self.0.as_str();
-        let parser = Parser::new(&s, None, vec![], false);
-        let item_context = (options.get(&sym::item_context)).unwrap_or(&empty_string);
-        parser
-            .map(|p| match p {
-                Piece::String(s) => s,
-                Piece::NextArgument(a) => match a.position {
-                    Position::ArgumentNamed(s) => match generic_map.get(&s) {
-                        Some(val) => val,
-                        None if s == name => &trait_str,
-                        None => {
-                            if let Some(val) = options.get(&s) {
-                                val
-                            } else if s == sym::from_desugaring || s == sym::from_method {
-                                // don't break messages using these two arguments incorrectly
-                                &empty_string
-                            } else if s == sym::item_context {
-                                &item_context
-                            } else {
-                                bug!(
-                                    "broken on_unimplemented {:?} for {:?}: \
-                                      no argument matching {:?}",
-                                    self.0,
-                                    trait_ref,
-                                    s
-                                )
-                            }
-                        }
-                    },
-                    _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0),
-                },
-            })
-            .collect()
-    }
-}
diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs
index 34889c6984b..48375a9ddf4 100644
--- a/src/librustc_infer/traits/project.rs
+++ b/src/librustc_infer/traits/project.rs
@@ -1,398 +1,18 @@
 //! Code for projecting associated types out of trait references.
 
-use super::elaborate_predicates;
-use super::specialization_graph;
-use super::translate_substs;
-use super::util;
-use super::Obligation;
-use super::ObligationCause;
 use super::PredicateObligation;
-use super::Selection;
-use super::SelectionContext;
-use super::SelectionError;
-use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData};
 
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
-use rustc_ast::ast::Ident;
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::sym;
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::{self, Ty};
 
-pub use rustc::traits::Reveal;
-
-pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
-
-pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
-
-pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
-
-/// When attempting to resolve `<T as TraitRef>::Name` ...
-#[derive(Debug)]
-pub enum ProjectionTyError<'tcx> {
-    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
-    TooManyCandidates,
-
-    /// ...an error occurred matching `T : TraitRef`
-    TraitSelectionError(SelectionError<'tcx>),
-}
+pub use rustc_middle::traits::Reveal;
 
 #[derive(Clone)]
 pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::error::TypeError<'tcx>,
 }
 
-#[derive(PartialEq, Eq, Debug)]
-enum ProjectionTyCandidate<'tcx> {
-    // from a where-clause in the env or object type
-    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
-
-    // from the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
-    TraitDef(ty::PolyProjectionPredicate<'tcx>),
-
-    // from a "impl" (or a "pseudo-impl" returned by select)
-    Select(Selection<'tcx>),
-}
-
-enum ProjectionTyCandidateSet<'tcx> {
-    None,
-    Single(ProjectionTyCandidate<'tcx>),
-    Ambiguous,
-    Error(SelectionError<'tcx>),
-}
-
-impl<'tcx> ProjectionTyCandidateSet<'tcx> {
-    fn mark_ambiguous(&mut self) {
-        *self = ProjectionTyCandidateSet::Ambiguous;
-    }
-
-    fn mark_error(&mut self, err: SelectionError<'tcx>) {
-        *self = ProjectionTyCandidateSet::Error(err);
-    }
-
-    // Returns true if the push was successful, or false if the candidate
-    // was discarded -- this could be because of ambiguity, or because
-    // a higher-priority candidate is already there.
-    fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
-        use self::ProjectionTyCandidate::*;
-        use self::ProjectionTyCandidateSet::*;
-
-        // This wacky variable is just used to try and
-        // make code readable and avoid confusing paths.
-        // It is assigned a "value" of `()` only on those
-        // paths in which we wish to convert `*self` to
-        // ambiguous (and return false, because the candidate
-        // was not used). On other paths, it is not assigned,
-        // and hence if those paths *could* reach the code that
-        // comes after the match, this fn would not compile.
-        let convert_to_ambiguous;
-
-        match self {
-            None => {
-                *self = Single(candidate);
-                return true;
-            }
-
-            Single(current) => {
-                // Duplicates can happen inside ParamEnv. In the case, we
-                // perform a lazy deduplication.
-                if current == &candidate {
-                    return false;
-                }
-
-                // Prefer where-clauses. As in select, if there are multiple
-                // candidates, we prefer where-clause candidates over impls.  This
-                // may seem a bit surprising, since impls are the source of
-                // "truth" in some sense, but in fact some of the impls that SEEM
-                // applicable are not, because of nested obligations. Where
-                // clauses are the safer choice. See the comment on
-                // `select::SelectionCandidate` and #21974 for more details.
-                match (current, candidate) {
-                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
-                    (ParamEnv(..), _) => return false,
-                    (_, ParamEnv(..)) => unreachable!(),
-                    (_, _) => convert_to_ambiguous = (),
-                }
-            }
-
-            Ambiguous | Error(..) => {
-                return false;
-            }
-        }
-
-        // We only ever get here when we moved from a single candidate
-        // to ambiguous.
-        let () = convert_to_ambiguous;
-        *self = Ambiguous;
-        false
-    }
-}
-
-/// Evaluates constraints of the form:
-///
-///     for<...> <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations. Also returns
-/// the projection cache key used to track these additional obligations.
-pub fn poly_project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &PolyProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("poly_project_and_unify_type(obligation={:?})", obligation);
-
-    let infcx = selcx.infcx();
-    infcx.commit_if_ok(|snapshot| {
-        let (placeholder_predicate, placeholder_map) =
-            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
-
-        let placeholder_obligation = obligation.with(placeholder_predicate);
-        let result = project_and_unify_type(selcx, &placeholder_obligation)?;
-        infcx
-            .leak_check(false, &placeholder_map, snapshot)
-            .map_err(|err| MismatchedProjectionTypes { err })?;
-        Ok(result)
-    })
-}
-
-/// Evaluates constraints of the form:
-///
-///     <T as Trait>::U == V
-///
-/// If successful, this may result in additional obligations.
-fn project_and_unify_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionObligation<'tcx>,
-) -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>> {
-    debug!("project_and_unify_type(obligation={:?})", obligation);
-
-    let mut obligations = vec![];
-    let normalized_ty = match opt_normalize_projection_type(
-        selcx,
-        obligation.param_env,
-        obligation.predicate.projection_ty,
-        obligation.cause.clone(),
-        obligation.recursion_depth,
-        &mut obligations,
-    ) {
-        Some(n) => n,
-        None => return Ok(None),
-    };
-
-    debug!(
-        "project_and_unify_type: normalized_ty={:?} obligations={:?}",
-        normalized_ty, obligations
-    );
-
-    let infcx = selcx.infcx();
-    match infcx
-        .at(&obligation.cause, obligation.param_env)
-        .eq(normalized_ty, obligation.predicate.ty)
-    {
-        Ok(InferOk { obligations: inferred_obligations, value: () }) => {
-            obligations.extend(inferred_obligations);
-            Ok(Some(obligations))
-        }
-        Err(err) => {
-            debug!("project_and_unify_type: equating types encountered error {:?}", err);
-            Err(MismatchedProjectionTypes { err })
-        }
-    }
-}
-
-/// Normalizes any associated type projections in `value`, replacing
-/// them with a fully resolved type where possible. The return value
-/// combines the normalized result and any additional obligations that
-/// were incurred as result.
-pub fn normalize<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
-}
-
-/// As `normalize`, but with a custom depth.
-pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-) -> Normalized<'tcx, T>
-where
-    T: TypeFoldable<'tcx>,
-{
-    let mut obligations = Vec::new();
-    let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
-    Normalized { value, obligations }
-}
-
-pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    value: &T,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> T
-where
-    T: TypeFoldable<'tcx>,
-{
-    debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
-    let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
-    let result = normalizer.fold(value);
-    debug!(
-        "normalize_with_depth: depth={} result={:?} with {} obligations",
-        depth,
-        result,
-        normalizer.obligations.len()
-    );
-    debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations);
-    result
-}
-
-struct AssocTypeNormalizer<'a, 'b, 'tcx> {
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    depth: usize,
-}
-
-impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn new(
-        selcx: &'a mut SelectionContext<'b, 'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        depth: usize,
-        obligations: &'a mut Vec<PredicateObligation<'tcx>>,
-    ) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
-        AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
-    }
-
-    fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
-        let value = self.selcx.infcx().resolve_vars_if_possible(value);
-
-        if !value.has_projections() { value } else { value.fold_with(self) }
-    }
-}
-
-impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
-        self.selcx.tcx()
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
-            return ty;
-        }
-        // We don't want to normalize associated types that occur inside of region
-        // binders, because they may contain bound regions, and we can't cope with that.
-        //
-        // Example:
-        //
-        //     for<'a> fn(<T as Foo<&'a>>::A)
-        //
-        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
-        // normalize it when we instantiate those bound regions (which
-        // should occur eventually).
-
-        let ty = ty.super_fold_with(self);
-        match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
-                // Only normalize `impl Trait` after type-checking, usually in codegen.
-                match self.param_env.reveal {
-                    Reveal::UserFacing => ty,
-
-                    Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
-                        if self.depth >= recursion_limit {
-                            let obligation = Obligation::with_depth(
-                                self.cause.clone(),
-                                recursion_limit,
-                                self.param_env,
-                                ty,
-                            );
-                            self.selcx.infcx().report_overflow_error(&obligation, true);
-                        }
-
-                        let generic_ty = self.tcx().type_of(def_id);
-                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
-                        self.depth += 1;
-                        let folded_ty = self.fold_ty(concrete_ty);
-                        self.depth -= 1;
-                        folded_ty
-                    }
-                }
-            }
-
-            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-
-                // (*) This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B : Fn(&'a int)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
-
-                let normalized_ty = normalize_projection_type(
-                    self.selcx,
-                    self.param_env,
-                    *data,
-                    self.cause.clone(),
-                    self.depth,
-                    &mut self.obligations,
-                );
-                debug!(
-                    "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \
-                     now with {} obligations",
-                    self.depth,
-                    ty,
-                    normalized_ty,
-                    self.obligations.len()
-                );
-                normalized_ty
-            }
-
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        constant.eval(self.selcx.tcx(), self.param_env)
-    }
-}
-
 #[derive(Clone, TypeFoldable)]
 pub struct Normalized<'tcx, T> {
     pub value: T,
@@ -403,1100 +23,7 @@ pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>;
 
 impl<'tcx, T> Normalized<'tcx, T> {
     pub fn with<U>(self, value: U) -> Normalized<'tcx, U> {
-        Normalized { value: value, obligations: self.obligations }
-    }
-}
-
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). If ambiguity arises, which implies that
-/// there are unresolved type variables in the projection, we will
-/// substitute a fresh type variable `$X` and generate a new
-/// obligation `<T as Trait>::Item == $X` for later.
-pub fn normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Ty<'tcx> {
-    opt_normalize_projection_type(
-        selcx,
-        param_env,
-        projection_ty,
-        cause.clone(),
-        depth,
-        obligations,
-    )
-    .unwrap_or_else(move || {
-        // if we bottom out in ambiguity, create a type variable
-        // and a deferred predicate to resolve this when more type
-        // information is available.
-
-        let tcx = selcx.infcx().tcx;
-        let def_id = projection_ty.item_def_id;
-        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
-            span: tcx.def_span(def_id),
-        });
-        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
-        let obligation =
-            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate());
-        obligations.push(obligation);
-        ty_var
-    })
-}
-
-/// The guts of `normalize`: normalize a specific projection like `<T
-/// as Trait>::Item`. The result is always a type (and possibly
-/// additional obligations). Returns `None` in the case of ambiguity,
-/// which indicates that there are unbound type variables.
-///
-/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
-/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
-/// often immediately appended to another obligations vector. So now this
-/// function takes an obligations vector and appends to it directly, which is
-/// slightly uglier but avoids the need for an extra short-lived allocation.
-fn opt_normalize_projection_type<'a, 'b, 'tcx>(
-    selcx: &'a mut SelectionContext<'b, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-    obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> Option<Ty<'tcx>> {
-    let infcx = selcx.infcx();
-
-    let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
-    let cache_key = ProjectionCacheKey { ty: projection_ty };
-
-    debug!(
-        "opt_normalize_projection_type(\
-         projection_ty={:?}, \
-         depth={})",
-        projection_ty, depth
-    );
-
-    // FIXME(#20304) For now, I am caching here, which is good, but it
-    // means we don't capture the type variables that are created in
-    // the case of ambiguity. Which means we may create a large stream
-    // of such variables. OTOH, if we move the caching up a level, we
-    // would not benefit from caching when proving `T: Trait<U=Foo>`
-    // bounds. It might be the case that we want two distinct caches,
-    // or else another kind of cache entry.
-
-    let cache_result = infcx.inner.borrow_mut().projection_cache.try_start(cache_key);
-    match cache_result {
-        Ok(()) => {}
-        Err(ProjectionCacheEntry::Ambiguous) => {
-            // If we found ambiguity the last time, that means we will continue
-            // to do so until some type in the key changes (and we know it
-            // hasn't, because we just fully resolved it).
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: ambiguous"
-            );
-            return None;
-        }
-        Err(ProjectionCacheEntry::InProgress) => {
-            // If while normalized A::B, we are asked to normalize
-            // A::B, just return A::B itself. This is a conservative
-            // answer, in the sense that A::B *is* clearly equivalent
-            // to A::B, though there may be a better value we can
-            // find.
-
-            // Under lazy normalization, this can arise when
-            // bootstrapping.  That is, imagine an environment with a
-            // where-clause like `A::B == u32`. Now, if we are asked
-            // to normalize `A::B`, we will want to check the
-            // where-clauses in scope. So we will try to unify `A::B`
-            // with `A::B`, which can trigger a recursive
-            // normalization. In that case, I think we will want this code:
-            //
-            // ```
-            // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
-            //                                    projection_ty.substs;
-            // return Some(NormalizedTy { value: v, obligations: vec![] });
-            // ```
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 found cache entry: in-progress"
-            );
-
-            // But for now, let's classify this as an overflow:
-            let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-            let obligation =
-                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
-            selcx.infcx().report_overflow_error(&obligation, false);
-        }
-        Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
-            // This is the hottest path in this function.
-            //
-            // If we find the value in the cache, then return it along
-            // with the obligations that went along with it. Note
-            // that, when using a fulfillment context, these
-            // obligations could in principle be ignored: they have
-            // already been registered when the cache entry was
-            // created (and hence the new ones will quickly be
-            // discarded as duplicated). But when doing trait
-            // evaluation this is not the case, and dropping the trait
-            // evaluations can causes ICEs (e.g., #43132).
-            debug!(
-                "opt_normalize_projection_type: \
-                 found normalized ty `{:?}`",
-                ty
-            );
-
-            // Once we have inferred everything we need to know, we
-            // can ignore the `obligations` from that point on.
-            if infcx.unresolved_type_vars(&ty.value).is_none() {
-                infcx.inner.borrow_mut().projection_cache.complete_normalized(cache_key, &ty);
-            // No need to extend `obligations`.
-            } else {
-                obligations.extend(ty.obligations);
-            }
-
-            obligations.push(get_paranoid_cache_value_obligation(
-                infcx,
-                param_env,
-                projection_ty,
-                cause,
-                depth,
-            ));
-            return Some(ty.value);
-        }
-        Err(ProjectionCacheEntry::Error) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 found error"
-            );
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            return Some(result.value);
-        }
-    }
-
-    let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
-    match project_type(selcx, &obligation) {
-        Ok(ProjectedTy::Progress(Progress {
-            ty: projected_ty,
-            obligations: mut projected_obligations,
-        })) => {
-            // if projection succeeded, then what we get out of this
-            // is also non-normalized (consider: it was derived from
-            // an impl, where-clause etc) and hence we must
-            // re-normalize it
-
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} \
-                 depth={} \
-                 projected_obligations={:?}",
-                projected_ty, depth, projected_obligations
-            );
-
-            let result = if projected_ty.has_projections() {
-                let mut normalizer = AssocTypeNormalizer::new(
-                    selcx,
-                    param_env,
-                    cause,
-                    depth + 1,
-                    &mut projected_obligations,
-                );
-                let normalized_ty = normalizer.fold(&projected_ty);
-
-                debug!(
-                    "opt_normalize_projection_type: \
-                     normalized_ty={:?} depth={}",
-                    normalized_ty, depth
-                );
-
-                Normalized { value: normalized_ty, obligations: projected_obligations }
-            } else {
-                Normalized { value: projected_ty, obligations: projected_obligations }
-            };
-
-            let cache_value = prune_cache_value_obligations(infcx, &result);
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, cache_value);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-        Ok(ProjectedTy::NoProgress(projected_ty)) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 projected_ty={:?} no progress",
-                projected_ty
-            );
-            let result = Normalized { value: projected_ty, obligations: vec![] };
-            infcx.inner.borrow_mut().projection_cache.insert_ty(cache_key, result.clone());
-            // No need to extend `obligations`.
-            Some(result.value)
-        }
-        Err(ProjectionTyError::TooManyCandidates) => {
-            debug!(
-                "opt_normalize_projection_type: \
-                 too many candidates"
-            );
-            infcx.inner.borrow_mut().projection_cache.ambiguous(cache_key);
-            None
-        }
-        Err(ProjectionTyError::TraitSelectionError(_)) => {
-            debug!("opt_normalize_projection_type: ERROR");
-            // if we got an error processing the `T as Trait` part,
-            // just return `ty::err` but add the obligation `T :
-            // Trait`, which when processed will cause the error to be
-            // reported later
-
-            infcx.inner.borrow_mut().projection_cache.error(cache_key);
-            let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
-            obligations.extend(result.obligations);
-            Some(result.value)
-        }
-    }
-}
-
-/// If there are unresolved type variables, then we need to include
-/// any subobligations that bind them, at least until those type
-/// variables are fully resolved.
-fn prune_cache_value_obligations<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    result: &NormalizedTy<'tcx>,
-) -> NormalizedTy<'tcx> {
-    if infcx.unresolved_type_vars(&result.value).is_none() {
-        return NormalizedTy { value: result.value, obligations: vec![] };
-    }
-
-    let mut obligations: Vec<_> = result
-        .obligations
-        .iter()
-        .filter(|obligation| match obligation.predicate {
-            // We found a `T: Foo<X = U>` predicate, let's check
-            // if `U` references any unresolved type
-            // variables. In principle, we only care if this
-            // projection can help resolve any of the type
-            // variables found in `result.value` -- but we just
-            // check for any type variables here, for fear of
-            // indirect obligations (e.g., we project to `?0`,
-            // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
-            // ?0>`).
-            ty::Predicate::Projection(ref data) => infcx.unresolved_type_vars(&data.ty()).is_some(),
-
-            // We are only interested in `T: Foo<X = U>` predicates, whre
-            // `U` references one of `unresolved_type_vars`. =)
-            _ => false,
-        })
-        .cloned()
-        .collect();
-
-    obligations.shrink_to_fit();
-
-    NormalizedTy { value: result.value, obligations }
-}
-
-/// Whenever we give back a cache result for a projection like `<T as
-/// Trait>::Item ==> X`, we *always* include the obligation to prove
-/// that `T: Trait` (we may also include some other obligations). This
-/// may or may not be necessary -- in principle, all the obligations
-/// that must be proven to show that `T: Trait` were also returned
-/// when the cache was first populated. But there are some vague concerns,
-/// and so we take the precautionary measure of including `T: Trait` in
-/// the result:
-///
-/// Concern #1. The current setup is fragile. Perhaps someone could
-/// have failed to prove the concerns from when the cache was
-/// populated, but also not have used a snapshot, in which case the
-/// cache could remain populated even though `T: Trait` has not been
-/// shown. In this case, the "other code" is at fault -- when you
-/// project something, you are supposed to either have a snapshot or
-/// else prove all the resulting obligations -- but it's still easy to
-/// get wrong.
-///
-/// Concern #2. Even within the snapshot, if those original
-/// obligations are not yet proven, then we are able to do projections
-/// that may yet turn out to be wrong. This *may* lead to some sort
-/// of trouble, though we don't have a concrete example of how that
-/// can occur yet. But it seems risky at best.
-fn get_paranoid_cache_value_obligation<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> PredicateObligation<'tcx> {
-    let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
-    Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
-/// hold. In various error cases, we cannot generate a valid
-/// normalized projection. Therefore, we create an inference variable
-/// return an associated obligation that, when fulfilled, will lead to
-/// an error.
-///
-/// Note that we used to return `Error` here, but that was quite
-/// dubious -- the premise was that an error would *eventually* be
-/// reported, when the obligation was processed. But in general once
-/// you see a `Error` you are supposed to be able to assume that an
-/// error *has been* reported, so that you can take whatever heuristic
-/// paths you want to take. To make things worse, it was possible for
-/// cycles to arise, where you basically had a setup like `<MyType<$0>
-/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
-/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
-/// an error for this obligation, but we legitimately should not,
-/// because it contains `[type error]`. Yuck! (See issue #29857 for
-/// one case where this arose.)
-fn normalize_to_error<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    projection_ty: ty::ProjectionTy<'tcx>,
-    cause: ObligationCause<'tcx>,
-    depth: usize,
-) -> NormalizedTy<'tcx> {
-    let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
-    let trait_obligation = Obligation {
-        cause,
-        recursion_depth: depth,
-        param_env,
-        predicate: trait_ref.without_const().to_predicate(),
-    };
-    let tcx = selcx.infcx().tcx;
-    let def_id = projection_ty.item_def_id;
-    let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
-        kind: TypeVariableOriginKind::NormalizeProjectionType,
-        span: tcx.def_span(def_id),
-    });
-    Normalized { value: new_value, obligations: vec![trait_obligation] }
-}
-
-enum ProjectedTy<'tcx> {
-    Progress(Progress<'tcx>),
-    NoProgress(Ty<'tcx>),
-}
-
-struct Progress<'tcx> {
-    ty: Ty<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-}
-
-impl<'tcx> Progress<'tcx> {
-    fn error(tcx: TyCtxt<'tcx>) -> Self {
-        Progress { ty: tcx.types.err, obligations: vec![] }
-    }
-
-    fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
-        debug!(
-            "with_addl_obligations: self.obligations.len={} obligations.len={}",
-            self.obligations.len(),
-            obligations.len()
-        );
-
-        debug!(
-            "with_addl_obligations: self.obligations={:?} obligations={:?}",
-            self.obligations, obligations
-        );
-
-        self.obligations.append(&mut obligations);
-        self
-    }
-}
-
-/// Computes the result of a projection type (if we can).
-///
-/// IMPORTANT:
-/// - `obligation` must be fully normalized
-fn project_type<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
-    debug!("project(obligation={:?})", obligation);
-
-    let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
-    if obligation.recursion_depth >= recursion_limit {
-        debug!("project: overflow!");
-        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
-    }
-
-    let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
-
-    debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
-
-    if obligation_trait_ref.references_error() {
-        return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
-    }
-
-    let mut candidates = ProjectionTyCandidateSet::None;
-
-    // Make sure that the following procedures are kept in order. ParamEnv
-    // needs to be first because it has highest priority, and Select checks
-    // the return value of push_candidate which assumes it's ran at last.
-    assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
-
-    match candidates {
-        ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress(
-            confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate),
-        )),
-        ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
-            selcx
-                .tcx()
-                .mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
-        )),
-        // Error occurred while trying to processing impls.
-        ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
-        // Inherent ambiguity that prevents us from even enumerating the
-        // candidates.
-        ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
-    }
-}
-
-/// The first thing we have to do is scan through the parameter
-/// environment to see whether there are any projection predicates
-/// there that can answer this question.
-fn assemble_candidates_from_param_env<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_param_env(..)");
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::ParamEnv,
-        obligation.param_env.caller_bounds.iter().cloned(),
-    );
-}
-
-/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
-/// that the definition of `Foo` has some clues:
-///
-/// ```
-/// trait Foo {
-///     type FooT : Bar<BarT=i32>
-/// }
-/// ```
-///
-/// Here, for example, we could conclude that the result is `i32`.
-fn assemble_candidates_from_trait_def<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    debug!("assemble_candidates_from_trait_def(..)");
-
-    let tcx = selcx.tcx();
-    // Check whether the self-type is itself a projection.
-    let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
-        ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
-        ty::Opaque(def_id, substs) => (def_id, substs),
-        ty::Infer(ty::TyVar(_)) => {
-            // If the self-type is an inference variable, then it MAY wind up
-            // being a projected type, so induce an ambiguity.
-            candidate_set.mark_ambiguous();
-            return;
-        }
-        _ => return,
-    };
-
-    // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = tcx.predicates_of(def_id);
-    let bounds = trait_predicates.instantiate(tcx, substs);
-    let bounds = elaborate_predicates(tcx, bounds.predicates);
-    assemble_candidates_from_predicates(
-        selcx,
-        obligation,
-        obligation_trait_ref,
-        candidate_set,
-        ProjectionTyCandidate::TraitDef,
-        bounds,
-    )
-}
-
-fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-    ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
-    env_predicates: I,
-) where
-    I: IntoIterator<Item = ty::Predicate<'tcx>>,
-{
-    debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
-    let infcx = selcx.infcx();
-    for predicate in env_predicates {
-        debug!("assemble_candidates_from_predicates: predicate={:?}", predicate);
-        if let ty::Predicate::Projection(data) = predicate {
-            let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
-
-            let is_match = same_def_id
-                && infcx.probe(|_| {
-                    let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx);
-                    let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-                    infcx
-                        .at(&obligation.cause, obligation.param_env)
-                        .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                        .map(|InferOk { obligations: _, value: () }| {
-                            // FIXME(#32730) -- do we need to take obligations
-                            // into account in any way? At the moment, no.
-                        })
-                        .is_ok()
-                });
-
-            debug!(
-                "assemble_candidates_from_predicates: candidate={:?} \
-                 is_match={} same_def_id={}",
-                data, is_match, same_def_id
-            );
-
-            if is_match {
-                candidate_set.push_candidate(ctor(data));
-            }
-        }
-    }
-}
-
-fn assemble_candidates_from_impls<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
-) {
-    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
-    // start out by selecting the predicate `T as TraitRef<...>`:
-    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
-    let _ = selcx.infcx().commit_if_ok(|_| {
-        let vtable = match selcx.select(&trait_obligation) {
-            Ok(Some(vtable)) => vtable,
-            Ok(None) => {
-                candidate_set.mark_ambiguous();
-                return Err(());
-            }
-            Err(e) => {
-                debug!("assemble_candidates_from_impls: selection error {:?}", e);
-                candidate_set.mark_error(e);
-                return Err(());
-            }
-        };
-
-        let eligible = match &vtable {
-            super::VtableClosure(_)
-            | super::VtableGenerator(_)
-            | super::VtableFnPointer(_)
-            | super::VtableObject(_)
-            | super::VtableTraitAlias(_) => {
-                debug!("assemble_candidates_from_impls: vtable={:?}", vtable);
-                true
-            }
-            super::VtableImpl(impl_data) => {
-                // We have to be careful when projecting out of an
-                // impl because of specialization. If we are not in
-                // codegen (i.e., projection mode is not "any"), and the
-                // impl's type is declared as default, then we disable
-                // projection (even if the trait ref is fully
-                // monomorphic). In the case where trait ref is not
-                // fully monomorphic (i.e., includes type parameters),
-                // this is because those type parameters may
-                // ultimately be bound to types from other crates that
-                // may have specialized impls we can't see. In the
-                // case where the trait ref IS fully monomorphic, this
-                // is a policy decision that we made in the RFC in
-                // order to preserve flexibility for the crate that
-                // defined the specializable impl to specialize later
-                // for existing types.
-                //
-                // In either case, we handle this by not adding a
-                // candidate for an impl if it contains a `default`
-                // type.
-                //
-                // NOTE: This should be kept in sync with the similar code in
-                // `rustc::ty::instance::resolve_associated_item()`.
-                let node_item =
-                    assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id);
-
-                let is_default = if node_item.node.is_from_trait() {
-                    // If true, the impl inherited a `type Foo = Bar`
-                    // given in the trait, which is implicitly default.
-                    // Otherwise, the impl did not specify `type` and
-                    // neither did the trait:
-                    //
-                    // ```rust
-                    // trait Foo { type T; }
-                    // impl Foo for Bar { }
-                    // ```
-                    //
-                    // This is an error, but it will be
-                    // reported in `check_impl_items_against_trait`.
-                    // We accept it here but will flag it as
-                    // an error when we confirm the candidate
-                    // (which will ultimately lead to `normalize_to_error`
-                    // being invoked).
-                    false
-                } else {
-                    // If we're looking at a trait *impl*, the item is
-                    // specializable if the impl or the item are marked
-                    // `default`.
-                    node_item.item.defaultness.is_default()
-                        || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id())
-                };
-
-                match is_default {
-                    // Non-specializable items are always projectable
-                    false => true,
-
-                    // Only reveal a specializable default if we're past type-checking
-                    // and the obligation is monomorphic, otherwise passes such as
-                    // transmute checking and polymorphic MIR optimizations could
-                    // get a result which isn't correct for all monomorphizations.
-                    true if obligation.param_env.reveal == Reveal::All => {
-                        // NOTE(eddyb) inference variables can resolve to parameters, so
-                        // assume `poly_trait_ref` isn't monomorphic, if it contains any.
-                        let poly_trait_ref =
-                            selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
-                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
-                    }
-
-                    true => {
-                        debug!(
-                            "assemble_candidates_from_impls: not eligible due to default: \
-                             assoc_ty={} predicate={}",
-                            selcx.tcx().def_path_str(node_item.item.def_id),
-                            obligation.predicate,
-                        );
-                        false
-                    }
-                }
-            }
-            super::VtableParam(..) => {
-                // This case tell us nothing about the value of an
-                // associated type. Consider:
-                //
-                // ```
-                // trait SomeTrait { type Foo; }
-                // fn foo<T:SomeTrait>(...) { }
-                // ```
-                //
-                // If the user writes `<T as SomeTrait>::Foo`, then the `T
-                // : SomeTrait` binding does not help us decide what the
-                // type `Foo` is (at least, not more specifically than
-                // what we already knew).
-                //
-                // But wait, you say! What about an example like this:
-                //
-                // ```
-                // fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
-                // ```
-                //
-                // Doesn't the `T : Sometrait<Foo=usize>` predicate help
-                // resolve `T::Foo`? And of course it does, but in fact
-                // that single predicate is desugared into two predicates
-                // in the compiler: a trait predicate (`T : SomeTrait`) and a
-                // projection. And the projection where clause is handled
-                // in `assemble_candidates_from_param_env`.
-                false
-            }
-            super::VtableAutoImpl(..) | super::VtableBuiltin(..) => {
-                // These traits have no associated types.
-                span_bug!(
-                    obligation.cause.span,
-                    "Cannot project an associated type from `{:?}`",
-                    vtable
-                );
-            }
-        };
-
-        if eligible {
-            if candidate_set.push_candidate(ProjectionTyCandidate::Select(vtable)) {
-                Ok(())
-            } else {
-                Err(())
-            }
-        } else {
-            Err(())
-        }
-    });
-}
-
-fn confirm_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    candidate: ProjectionTyCandidate<'tcx>,
-) -> Progress<'tcx> {
-    debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
-
-    match candidate {
-        ProjectionTyCandidate::ParamEnv(poly_projection)
-        | ProjectionTyCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection)
-        }
-
-        ProjectionTyCandidate::Select(vtable) => {
-            confirm_select_candidate(selcx, obligation, obligation_trait_ref, vtable)
-        }
-    }
-}
-
-fn confirm_select_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-    vtable: Selection<'tcx>,
-) -> Progress<'tcx> {
-    match vtable {
-        super::VtableImpl(data) => confirm_impl_candidate(selcx, obligation, data),
-        super::VtableGenerator(data) => confirm_generator_candidate(selcx, obligation, data),
-        super::VtableClosure(data) => confirm_closure_candidate(selcx, obligation, data),
-        super::VtableFnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
-        super::VtableObject(_) => confirm_object_candidate(selcx, obligation, obligation_trait_ref),
-        super::VtableAutoImpl(..)
-        | super::VtableParam(..)
-        | super::VtableBuiltin(..)
-        | super::VtableTraitAlias(..) =>
-        // we don't create Select candidates with this kind of resolution
-        {
-            span_bug!(
-                obligation.cause.span,
-                "Cannot project an associated type from `{:?}`",
-                vtable
-            )
-        }
-    }
-}
-
-fn confirm_object_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    obligation_trait_ref: &ty::TraitRef<'tcx>,
-) -> Progress<'tcx> {
-    let self_ty = obligation_trait_ref.self_ty();
-    let object_ty = selcx.infcx().shallow_resolve(self_ty);
-    debug!("confirm_object_candidate(object_ty={:?})", object_ty);
-    let data = match object_ty.kind {
-        ty::Dynamic(ref data, ..) => data,
-        _ => span_bug!(
-            obligation.cause.span,
-            "confirm_object_candidate called with non-object: {:?}",
-            object_ty
-        ),
-    };
-    let env_predicates = data
-        .projection_bounds()
-        .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
-        .collect();
-    let env_predicate = {
-        let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
-
-        // select only those projections that are actually projecting an
-        // item with the correct name
-        let env_predicates = env_predicates.filter_map(|p| match p {
-            ty::Predicate::Projection(data) => {
-                if data.projection_def_id() == obligation.predicate.item_def_id {
-                    Some(data)
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        });
-
-        // select those with a relevant trait-ref
-        let mut env_predicates = env_predicates.filter(|data| {
-            let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
-            let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
-            selcx.infcx().probe(|_| {
-                selcx
-                    .infcx()
-                    .at(&obligation.cause, obligation.param_env)
-                    .sup(obligation_poly_trait_ref, data_poly_trait_ref)
-                    .is_ok()
-            })
-        });
-
-        // select the first matching one; there really ought to be one or
-        // else the object type is not WF, since an object type should
-        // include all of its projections explicitly
-        match env_predicates.next() {
-            Some(env_predicate) => env_predicate,
-            None => {
-                debug!(
-                    "confirm_object_candidate: no env-predicate \
-                     found in object type `{:?}`; ill-formed",
-                    object_ty
-                );
-                return Progress::error(selcx.tcx());
-            }
-        }
-    };
-
-    confirm_param_env_candidate(selcx, obligation, env_predicate)
-}
-
-fn confirm_generator_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
-    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &gen_sig,
-    );
-
-    debug!(
-        "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}",
-        obligation, gen_sig, obligations
-    );
-
-    let tcx = selcx.tcx();
-
-    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
-
-    let predicate = super::util::generator_trait_ref_and_outputs(
-        tcx,
-        gen_def_id,
-        obligation.predicate.self_ty(),
-        gen_sig,
-    )
-    .map_bound(|(trait_ref, yield_ty, return_ty)| {
-        let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
-        let ty = if name == sym::Return {
-            return_ty
-        } else if name == sym::Yield {
-            yield_ty
-        } else {
-            bug!()
-        };
-
-        ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                substs: trait_ref.substs,
-                item_def_id: obligation.predicate.item_def_id,
-            },
-            ty: ty,
-        }
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_fn_pointer_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
-    let sig = fn_type.fn_sig(selcx.tcx());
-    let Normalized { value: sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &sig,
-    );
-
-    confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
-        .with_addl_obligations(fn_pointer_vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_closure_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-    let infcx = selcx.infcx();
-    let closure_sig_ty = vtable.substs.as_closure().sig_ty(vtable.closure_def_id, tcx);
-    let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
-    let Normalized { value: closure_sig, obligations } = normalize_with_depth(
-        selcx,
-        obligation.param_env,
-        obligation.cause.clone(),
-        obligation.recursion_depth + 1,
-        &closure_sig,
-    );
-
-    debug!(
-        "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
-        obligation, closure_sig, obligations
-    );
-
-    confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
-        .with_addl_obligations(vtable.nested)
-        .with_addl_obligations(obligations)
-}
-
-fn confirm_callable_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    fn_sig: ty::PolyFnSig<'tcx>,
-    flag: util::TupleArgumentsFlag,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig);
-
-    // the `Output` associated type is declared on `FnOnce`
-    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
-
-    let predicate = super::util::closure_trait_ref_and_return_type(
-        tcx,
-        fn_once_def_id,
-        obligation.predicate.self_ty(),
-        fn_sig,
-        flag,
-    )
-    .map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy::from_ref_and_name(
-            tcx,
-            trait_ref,
-            Ident::with_dummy_span(rustc_hir::FN_OUTPUT_NAME),
-        ),
-        ty: ret_type,
-    });
-
-    confirm_param_env_candidate(selcx, obligation, predicate)
-}
-
-fn confirm_param_env_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
-) -> Progress<'tcx> {
-    let infcx = selcx.infcx();
-    let cause = &obligation.cause;
-    let param_env = obligation.param_env;
-
-    let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
-        cause.span,
-        LateBoundRegionConversionTime::HigherRankedType,
-        &poly_cache_entry,
-    );
-
-    let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
-    let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
-    match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
-        Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations },
-        Err(e) => {
-            let msg = format!(
-                "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
-                obligation, poly_cache_entry, e,
-            );
-            debug!("confirm_param_env_candidate: {}", msg);
-            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
-            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
-        }
-    }
-}
-
-fn confirm_impl_candidate<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-
-    let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
-    let assoc_item_id = obligation.predicate.item_def_id;
-    let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
-
-    let param_env = obligation.param_env;
-    let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id);
-
-    if !assoc_ty.item.defaultness.has_value() {
-        // This means that the impl is missing a definition for the
-        // associated type. This error will be reported by the type
-        // checker method `check_impl_items_against_trait`, so here we
-        // just return Error.
-        debug!(
-            "confirm_impl_candidate: no associated type {:?} for {:?}",
-            assoc_ty.item.ident, obligation.predicate
-        );
-        return Progress { ty: tcx.types.err, obligations: nested };
-    }
-    let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
-    let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
-    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
-        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
-    } else {
-        tcx.type_of(assoc_ty.item.def_id)
-    };
-    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
-        tcx.sess
-            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
-        Progress { ty: tcx.types.err, obligations: nested }
-    } else {
-        Progress { ty: ty.subst(tcx, substs), obligations: nested }
-    }
-}
-
-/// Locate the definition of an associated type in the specialization hierarchy,
-/// starting from the given impl.
-///
-/// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_ty_def(
-    selcx: &SelectionContext<'_, '_>,
-    impl_def_id: DefId,
-    assoc_ty_def_id: DefId,
-) -> specialization_graph::NodeItem<ty::AssocItem> {
-    let tcx = selcx.tcx();
-    let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
-    let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
-    let trait_def = tcx.trait_def(trait_def_id);
-
-    // This function may be called while we are still building the
-    // specialization graph that is queried below (via TraidDef::ancestors()),
-    // so, in order to avoid unnecessary infinite recursion, we manually look
-    // for the associated item at the given impl.
-    // If there is no such item in that impl, this function will fail with a
-    // cycle error if the specialization graph is currently being built.
-    let impl_node = specialization_graph::Node::Impl(impl_def_id);
-    for item in impl_node.items(tcx) {
-        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
-            && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
-        {
-            return specialization_graph::NodeItem {
-                node: specialization_graph::Node::Impl(impl_def_id),
-                item: *item,
-            };
-        }
-    }
-
-    if let Some(assoc_item) =
-        trait_def.ancestors(tcx, impl_def_id).leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type)
-    {
-        assoc_item
-    } else {
-        // This is saying that neither the trait nor
-        // the impl contain a definition for this
-        // associated type.  Normally this situation
-        // could only arise through a compiler bug --
-        // if the user wrote a bad item name, it
-        // should have failed in astconv.
-        bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
+        Normalized { value, obligations: self.obligations }
     }
 }
 
@@ -1541,26 +68,14 @@ pub struct ProjectionCacheKey<'tcx> {
     ty: ty::ProjectionTy<'tcx>,
 }
 
-impl<'cx, 'tcx> ProjectionCacheKey<'tcx> {
-    pub fn from_poly_projection_predicate(
-        selcx: &mut SelectionContext<'cx, 'tcx>,
-        predicate: &ty::PolyProjectionPredicate<'tcx>,
-    ) -> Option<Self> {
-        let infcx = selcx.infcx();
-        // We don't do cross-snapshot caching of obligations with escaping regions,
-        // so there's no cache key to use
-        predicate.no_bound_vars().map(|predicate| ProjectionCacheKey {
-            // We don't attempt to match up with a specific type-variable state
-            // from a specific call to `opt_normalize_projection_type` - if
-            // there's no precise match, the original cache entry is "stranded"
-            // anyway.
-            ty: infcx.resolve_vars_if_possible(&predicate.projection_ty),
-        })
+impl ProjectionCacheKey<'tcx> {
+    pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self {
+        Self { ty }
     }
 }
 
 #[derive(Clone, Debug)]
-enum ProjectionCacheEntry<'tcx> {
+pub enum ProjectionCacheEntry<'tcx> {
     InProgress,
     Ambiguous,
     Error,
@@ -1596,7 +111,7 @@ impl<'tcx> ProjectionCache<'tcx> {
     /// Try to start normalize `key`; returns an error if
     /// normalization already occurred (this error corresponds to a
     /// cache hit, so it's actually a good thing).
-    fn try_start(
+    pub fn try_start(
         &mut self,
         key: ProjectionCacheKey<'tcx>,
     ) -> Result<(), ProjectionCacheEntry<'tcx>> {
@@ -1609,7 +124,7 @@ impl<'tcx> ProjectionCache<'tcx> {
     }
 
     /// Indicates that `key` was normalized to `value`.
-    fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
+    pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'tcx>) {
         debug!(
             "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
             key, value
@@ -1662,14 +177,14 @@ impl<'tcx> ProjectionCache<'tcx> {
     /// ambiguity. No point in trying it again then until we gain more
     /// type information (in which case, the "fully resolved" key will
     /// be different).
-    fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
 
     /// Indicates that trying to normalize `key` resulted in
     /// error.
-    fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
+    pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
         let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
diff --git a/src/librustc_infer/traits/query/dropck_outlives.rs b/src/librustc_infer/traits/query/dropck_outlives.rs
deleted file mode 100644
index a1d7a2836e4..00000000000
--- a/src/librustc_infer/traits/query/dropck_outlives.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-use crate::infer::at::At;
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferOk;
-
-use rustc::ty::subst::GenericArg;
-use rustc::ty::{self, Ty, TyCtxt};
-
-pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint};
-
-impl<'cx, 'tcx> At<'cx, 'tcx> {
-    /// Given a type `ty` of some value being dropped, computes a set
-    /// of "kinds" (types, regions) that must be outlive the execution
-    /// of the destructor. These basically correspond to data that the
-    /// destructor might access. This is used during regionck to
-    /// impose "outlives" constraints on any lifetimes referenced
-    /// within.
-    ///
-    /// The rules here are given by the "dropck" RFCs, notably [#1238]
-    /// and [#1327]. This is a fixed-point computation, where we
-    /// explore all the data that will be dropped (transitively) when
-    /// a value of type `ty` is dropped. For each type T that will be
-    /// dropped and which has a destructor, we must assume that all
-    /// the types/regions of T are live during the destructor, unless
-    /// they are marked with a special attribute (`#[may_dangle]`).
-    ///
-    /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
-    /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md
-    pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<GenericArg<'tcx>>> {
-        debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,);
-
-        // Quick check: there are a number of cases that we know do not require
-        // any destructor.
-        let tcx = self.infcx.tcx;
-        if trivial_dropck_outlives(tcx, ty) {
-            return InferOk { value: vec![], obligations: vec![] };
-        }
-
-        let mut orig_values = OriginalQueryValues::default();
-        let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values);
-        let span = self.cause.span;
-        debug!("c_ty = {:?}", c_ty);
-        if let Ok(result) = &tcx.dropck_outlives(c_ty) {
-            if result.is_proven() {
-                if let Ok(InferOk { value, obligations }) =
-                    self.infcx.instantiate_query_response_and_region_obligations(
-                        self.cause,
-                        self.param_env,
-                        &orig_values,
-                        result,
-                    )
-                {
-                    let ty = self.infcx.resolve_vars_if_possible(&ty);
-                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
-                    return InferOk { value: kinds, obligations };
-                }
-            }
-        }
-
-        // Errors and ambiuity in dropck occur in two cases:
-        // - unresolved inference variables at the end of typeck
-        // - non well-formed types where projections cannot be resolved
-        // Either of these should have created an error before.
-        tcx.sess.delay_span_bug(span, "dtorck encountered internal error");
-
-        InferOk { value: vec![], obligations: vec![] }
-    }
-}
-
-/// This returns true if the type `ty` is "trivial" for
-/// dropck-outlives -- that is, if it doesn't require any types to
-/// outlive. This is similar but not *quite* the same as the
-/// `needs_drop` test in the compiler already -- that is, for every
-/// type T for which this function return true, needs-drop would
-/// return `false`. But the reverse does not hold: in particular,
-/// `needs_drop` returns false for `PhantomData`, but it is not
-/// trivial for dropck-outlives.
-///
-/// Note also that `needs_drop` requires a "global" type (i.e., one
-/// with erased regions), but this function does not.
-pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.kind {
-        // None of these types have a destructor and hence they do not
-        // require anything in particular to outlive the dtor's
-        // execution.
-        ty::Infer(ty::FreshIntTy(_))
-        | ty::Infer(ty::FreshFloatTy(_))
-        | ty::Bool
-        | ty::Int(_)
-        | ty::Uint(_)
-        | ty::Float(_)
-        | ty::Never
-        | ty::FnDef(..)
-        | ty::FnPtr(_)
-        | ty::Char
-        | ty::GeneratorWitness(..)
-        | ty::RawPtr(_)
-        | ty::Ref(..)
-        | ty::Str
-        | ty::Foreign(..)
-        | ty::Error => true,
-
-        // [T; N] and [T] have same properties as T.
-        ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
-
-        // (T1..Tn) and closures have same properties as T1..Tn --
-        // check if *any* of those are trivial.
-        ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
-        ty::Closure(def_id, ref substs) => {
-            substs.as_closure().upvar_tys(def_id, tcx).all(|t| trivial_dropck_outlives(tcx, t))
-        }
-
-        ty::Adt(def, _) => {
-            if Some(def.did) == tcx.lang_items().manually_drop() {
-                // `ManuallyDrop` never has a dtor.
-                true
-            } else {
-                // Other types might. Moreover, PhantomData doesn't
-                // have a dtor, but it is considered to own its
-                // content, so it is non-trivial. Unions can have `impl Drop`,
-                // and hence are non-trivial as well.
-                false
-            }
-        }
-
-        // The following *might* require a destructor: needs deeper inspection.
-        ty::Dynamic(..)
-        | ty::Projection(..)
-        | ty::Param(_)
-        | ty::Opaque(..)
-        | ty::Placeholder(..)
-        | ty::Infer(_)
-        | ty::Bound(..)
-        | ty::Generator(..) => false,
-
-        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-    }
-}
diff --git a/src/librustc_infer/traits/query/evaluate_obligation.rs b/src/librustc_infer/traits/query/evaluate_obligation.rs
deleted file mode 100644
index b9ce3ccff27..00000000000
--- a/src/librustc_infer/traits/query/evaluate_obligation.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::{
-    EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
-};
-
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
-    /// Evaluates whether the predicate can be satisfied (by any means)
-    /// in the given `ParamEnv`.
-    pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).may_apply()
-    }
-
-    /// Evaluates whether the predicate can be satisfied in the given
-    /// `ParamEnv`, and returns `false` if not certain. However, this is
-    /// not entirely accurate if inference variables are involved.
-    ///
-    /// This version may conservatively fail when outlives obligations
-    /// are required.
-    pub fn predicate_must_hold_considering_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).must_apply_considering_regions()
-    }
-
-    /// Evaluates whether the predicate can be satisfied in the given
-    /// `ParamEnv`, and returns `false` if not certain. However, this is
-    /// not entirely accurate if inference variables are involved.
-    ///
-    /// This version ignores all outlives constraints.
-    pub fn predicate_must_hold_modulo_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions()
-    }
-
-    /// Evaluate a given predicate, capturing overflow and propagating it back.
-    pub fn evaluate_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        let mut _orig_values = OriginalQueryValues::default();
-        let c_pred = self
-            .canonicalize_query(&obligation.param_env.and(obligation.predicate), &mut _orig_values);
-        // Run canonical query. If overflow occurs, rerun from scratch but this time
-        // in standard trait query mode so that overflow is handled appropriately
-        // within `SelectionContext`.
-        self.tcx.evaluate_obligation(c_pred)
-    }
-
-    // Helper function that canonicalizes and runs the query. If an
-    // overflow results, we re-run it in the local context so we can
-    // report a nice error.
-    crate fn evaluate_obligation_no_overflow(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> EvaluationResult {
-        match self.evaluate_obligation(obligation) {
-            Ok(result) => result,
-            Err(OverflowError) => {
-                let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
-                selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| {
-                    span_bug!(
-                        obligation.cause.span,
-                        "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
-                        obligation,
-                        r,
-                    )
-                })
-            }
-        }
-    }
-}
diff --git a/src/librustc_infer/traits/query/method_autoderef.rs b/src/librustc_infer/traits/query/method_autoderef.rs
deleted file mode 100644
index 80748c5ef38..00000000000
--- a/src/librustc_infer/traits/query/method_autoderef.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use rustc::traits::query::{CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult};
diff --git a/src/librustc_infer/traits/query/mod.rs b/src/librustc_infer/traits/query/mod.rs
deleted file mode 100644
index 77b5ec669a0..00000000000
--- a/src/librustc_infer/traits/query/mod.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//! Experimental types for the trait query interface. The methods
-//! defined in this module are all based on **canonicalization**,
-//! which makes a canonical query by replacing unbound inference
-//! variables and regions, so that results can be reused more broadly.
-//! The providers for the queries defined here can be found in
-//! `librustc_traits`.
-
-pub mod dropck_outlives;
-pub mod evaluate_obligation;
-pub mod method_autoderef;
-pub mod normalize;
-pub mod outlives_bounds;
-pub mod type_op;
-
-pub use rustc::traits::query::*;
diff --git a/src/librustc_infer/traits/query/normalize.rs b/src/librustc_infer/traits/query/normalize.rs
deleted file mode 100644
index 4577e3d2e1c..00000000000
--- a/src/librustc_infer/traits/query/normalize.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-//! Code for the 'normalization' query. This consists of a wrapper
-//! which folds deeply, invoking the underlying
-//! `normalize_projection_ty` query when it encounters projections.
-
-use crate::infer::at::At;
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::project::Normalized;
-use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
-use rustc::ty::subst::Subst;
-use rustc::ty::{self, Ty, TyCtxt};
-
-use super::NoSolution;
-
-pub use rustc::traits::query::NormalizationResult;
-
-impl<'cx, 'tcx> At<'cx, 'tcx> {
-    /// Normalize `value` in the context of the inference context,
-    /// yielding a resulting type, or an error if `value` cannot be
-    /// normalized. If you don't care about regions, you should prefer
-    /// `normalize_erasing_regions`, which is more efficient.
-    ///
-    /// If the normalization succeeds and is unambiguous, returns back
-    /// the normalized value along with various outlives relations (in
-    /// the form of obligations that must be discharged).
-    ///
-    /// N.B., this will *eventually* be the main means of
-    /// normalizing, but for now should be used only when we actually
-    /// know that normalization will succeed, since error reporting
-    /// and other details are still "under development".
-    pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
-    where
-        T: TypeFoldable<'tcx>,
-    {
-        debug!(
-            "normalize::<{}>(value={:?}, param_env={:?})",
-            ::std::any::type_name::<T>(),
-            value,
-            self.param_env,
-        );
-        if !value.has_projections() {
-            return Ok(Normalized { value: value.clone(), obligations: vec![] });
-        }
-
-        let mut normalizer = QueryNormalizer {
-            infcx: self.infcx,
-            cause: self.cause,
-            param_env: self.param_env,
-            obligations: vec![],
-            error: false,
-            anon_depth: 0,
-        };
-
-        let value1 = value.fold_with(&mut normalizer);
-        if normalizer.error {
-            Err(NoSolution)
-        } else {
-            Ok(Normalized { value: value1, obligations: normalizer.obligations })
-        }
-    }
-}
-
-struct QueryNormalizer<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-    cause: &'cx ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    obligations: Vec<PredicateObligation<'tcx>>,
-    error: bool,
-    anon_depth: usize,
-}
-
-impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty.has_projections() {
-            return ty;
-        }
-
-        let ty = ty.super_fold_with(self);
-        match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
-                // Only normalize `impl Trait` after type-checking, usually in codegen.
-                match self.param_env.reveal {
-                    Reveal::UserFacing => ty,
-
-                    Reveal::All => {
-                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
-                        if self.anon_depth >= recursion_limit {
-                            let obligation = Obligation::with_depth(
-                                self.cause.clone(),
-                                recursion_limit,
-                                self.param_env,
-                                ty,
-                            );
-                            self.infcx.report_overflow_error(&obligation, true);
-                        }
-
-                        let generic_ty = self.tcx().type_of(def_id);
-                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
-                        self.anon_depth += 1;
-                        if concrete_ty == ty {
-                            bug!(
-                                "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
-                                 concrete_ty: {:#?}, ty: {:#?}",
-                                generic_ty,
-                                substs,
-                                concrete_ty,
-                                ty
-                            );
-                        }
-                        let folded_ty = self.fold_ty(concrete_ty);
-                        self.anon_depth -= 1;
-                        folded_ty
-                    }
-                }
-            }
-
-            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-                // (*) This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B : Fn(&'a int)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
-
-                let tcx = self.infcx.tcx;
-
-                let mut orig_values = OriginalQueryValues::default();
-                // HACK(matthewjasper) `'static` is special-cased in selection,
-                // so we cannot canonicalize it.
-                let c_data = self
-                    .infcx
-                    .canonicalize_hr_query_hack(&self.param_env.and(*data), &mut orig_values);
-                debug!("QueryNormalizer: c_data = {:#?}", c_data);
-                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                match tcx.normalize_projection_ty(c_data) {
-                    Ok(result) => {
-                        // We don't expect ambiguity.
-                        if result.is_ambiguous() {
-                            self.error = true;
-                            return ty;
-                        }
-
-                        match self.infcx.instantiate_query_response_and_region_obligations(
-                            self.cause,
-                            self.param_env,
-                            &orig_values,
-                            &result,
-                        ) {
-                            Ok(InferOk { value: result, obligations }) => {
-                                debug!("QueryNormalizer: result = {:#?}", result);
-                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
-                                self.obligations.extend(obligations);
-                                return result.normalized_ty;
-                            }
-
-                            Err(_) => {
-                                self.error = true;
-                                return ty;
-                            }
-                        }
-                    }
-
-                    Err(NoSolution) => {
-                        self.error = true;
-                        ty
-                    }
-                }
-            }
-
-            _ => ty,
-        }
-    }
-
-    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        constant.eval(self.infcx.tcx, self.param_env)
-    }
-}
diff --git a/src/librustc_infer/traits/query/outlives_bounds.rs b/src/librustc_infer/traits/query/outlives_bounds.rs
deleted file mode 100644
index eb32ebf5c4d..00000000000
--- a/src/librustc_infer/traits/query/outlives_bounds.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::query::NoSolution;
-use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
-use rustc::ty::{self, Ty};
-use rustc_hir as hir;
-use rustc_span::source_map::Span;
-
-pub use rustc::traits::query::OutlivesBound;
-
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
-    /// Implied bounds are region relationships that we deduce
-    /// automatically. The idea is that (e.g.) a caller must check that a
-    /// function's argument types are well-formed immediately before
-    /// calling that fn, and hence the *callee* can assume that its
-    /// argument types are well-formed. This may imply certain relationships
-    /// between generic parameters. For example:
-    ///
-    ///     fn foo<'a,T>(x: &'a T)
-    ///
-    /// can only be called with a `'a` and `T` such that `&'a T` is WF.
-    /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
-    ///
-    /// # Parameters
-    ///
-    /// - `param_env`, the where-clauses in scope
-    /// - `body_id`, the body-id to use when normalizing assoc types.
-    ///   Note that this may cause outlives obligations to be injected
-    ///   into the inference context with this body-id.
-    /// - `ty`, the type that we are supposed to assume is WF.
-    /// - `span`, a span to use when normalizing, hopefully not important,
-    ///   might be useful if a `bug!` occurs.
-    pub fn implied_outlives_bounds(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        body_id: hir::HirId,
-        ty: Ty<'tcx>,
-        span: Span,
-    ) -> Vec<OutlivesBound<'tcx>> {
-        debug!("implied_outlives_bounds(ty = {:?})", ty);
-
-        let mut orig_values = OriginalQueryValues::default();
-        let key = self.canonicalize_query(&param_env.and(ty), &mut orig_values);
-        let result = match self.tcx.implied_outlives_bounds(key) {
-            Ok(r) => r,
-            Err(NoSolution) => {
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve all obligations",
-                );
-                return vec![];
-            }
-        };
-        assert!(result.value.is_proven());
-
-        let result = self.instantiate_query_response_and_region_obligations(
-            &ObligationCause::misc(span, body_id),
-            param_env,
-            &orig_values,
-            &result,
-        );
-        debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
-        let result = match result {
-            Ok(v) => v,
-            Err(_) => {
-                self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
-                return vec![];
-            }
-        };
-
-        // Instantiation may have produced new inference variables and constraints on those
-        // variables. Process these constraints.
-        let mut fulfill_cx = FulfillmentContext::new();
-        fulfill_cx.register_predicate_obligations(self, result.obligations);
-        if fulfill_cx.select_all_or_error(self).is_err() {
-            self.tcx.sess.delay_span_bug(
-                span,
-                "implied_outlives_bounds failed to solve obligations from instantiation",
-            );
-        }
-
-        result.value
-    }
-}
-
-pub fn explicit_outlives_bounds<'tcx>(
-    param_env: ty::ParamEnv<'tcx>,
-) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
-    debug!("explicit_outlives_bounds()");
-    param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
-        ty::Predicate::Projection(..)
-        | ty::Predicate::Trait(..)
-        | ty::Predicate::Subtype(..)
-        | ty::Predicate::WellFormed(..)
-        | ty::Predicate::ObjectSafe(..)
-        | ty::Predicate::ClosureKind(..)
-        | ty::Predicate::TypeOutlives(..)
-        | ty::Predicate::ConstEvaluatable(..) => None,
-        ty::Predicate::RegionOutlives(ref data) => data
-            .no_bound_vars()
-            .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
-    })
-}
diff --git a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs b/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs
deleted file mode 100644
index b14b79f0907..00000000000
--- a/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::AscribeUserType;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        _key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_ascribe_user_type(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/custom.rs b/src/librustc_infer/traits/query/type_op/custom.rs
deleted file mode 100644
index c1c9030b888..00000000000
--- a/src/librustc_infer/traits/query/type_op/custom.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use std::fmt;
-
-use crate::infer::canonical::query_response;
-use crate::infer::canonical::QueryRegionConstraints;
-use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
-use rustc_span::source_map::DUMMY_SP;
-use std::rc::Rc;
-
-pub struct CustomTypeOp<F, G> {
-    closure: F,
-    description: G,
-}
-
-impl<F, G> CustomTypeOp<F, G> {
-    pub fn new<'tcx, R>(closure: F, description: G) -> Self
-    where
-        F: FnOnce(&InferCtxt<'_, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
-        G: Fn() -> String,
-    {
-        CustomTypeOp { closure, description }
-    }
-}
-
-impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
-where
-    F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
-    G: Fn() -> String,
-{
-    type Output = R;
-
-    /// Processes the operation and all resulting obligations,
-    /// returning the final result along with any region constraints
-    /// (they will be given over to the NLL region solver).
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-        if cfg!(debug_assertions) {
-            info!("fully_perform({:?})", self);
-        }
-
-        scrape_region_constraints(infcx, || Ok((self.closure)(infcx)?))
-    }
-}
-
-impl<F, G> fmt::Debug for CustomTypeOp<F, G>
-where
-    G: Fn() -> String,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", (self.description)())
-    }
-}
-
-/// Executes `op` and then scrapes out all the "old style" region
-/// constraints that result, creating query-region-constraints.
-fn scrape_region_constraints<'tcx, R>(
-    infcx: &InferCtxt<'_, 'tcx>,
-    op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-    let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-    let dummy_body_id = ObligationCause::dummy().body_id;
-
-    // During NLL, we expect that nobody will register region
-    // obligations **except** as part of a custom type op (and, at the
-    // end of each custom type op, we scrape out the region
-    // obligations that resulted). So this vector should be empty on
-    // entry.
-    let pre_obligations = infcx.take_registered_region_obligations();
-    assert!(
-        pre_obligations.is_empty(),
-        "scrape_region_constraints: incoming region obligations = {:#?}",
-        pre_obligations,
-    );
-
-    let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
-    debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
-    fulfill_cx.register_predicate_obligations(infcx, obligations);
-    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
-        infcx.tcx.sess.diagnostic().delay_span_bug(
-            DUMMY_SP,
-            &format!("errors selecting obligation during MIR typeck: {:?}", e),
-        );
-    }
-
-    let region_obligations = infcx.take_registered_region_obligations();
-
-    let region_constraint_data = infcx.take_and_reset_region_constraints();
-
-    let region_constraints = query_response::make_query_region_constraints(
-        infcx.tcx,
-        region_obligations
-            .iter()
-            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
-            .map(|(ty, r)| (infcx.resolve_vars_if_possible(&ty), r)),
-        &region_constraint_data,
-    );
-
-    if region_constraints.is_empty() {
-        Ok((value, None))
-    } else {
-        Ok((value, Some(Rc::new(region_constraints))))
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/eq.rs b/src/librustc_infer/traits/query/type_op/eq.rs
deleted file mode 100644
index 3b6fbc7d8dd..00000000000
--- a/src/librustc_infer/traits/query/type_op/eq.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::Eq;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Eq<'tcx>>,
-    ) -> Option<Self::QueryResponse> {
-        if key.value.a == key.value.b { Some(()) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_eq(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs
deleted file mode 100644
index 3dad546872e..00000000000
--- a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::outlives_bounds::OutlivesBound;
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
-
-#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct ImpliedOutlivesBounds<'tcx> {
-    pub ty: Ty<'tcx>,
-}
-
-impl<'tcx> ImpliedOutlivesBounds<'tcx> {
-    pub fn new(ty: Ty<'tcx>) -> Self {
-        ImpliedOutlivesBounds { ty }
-    }
-}
-
-impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
-    type QueryResponse = Vec<OutlivesBound<'tcx>>;
-
-    fn try_fast_path(
-        _tcx: TyCtxt<'tcx>,
-        _key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        // FIXME this `unchecked_map` is only necessary because the
-        // query is defined as taking a `ParamEnvAnd<Ty>`; it should
-        // take a `ImpliedOutlivesBounds` instead
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let ImpliedOutlivesBounds { ty } = value;
-            param_env.and(ty)
-        });
-
-        tcx.implied_outlives_bounds(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_infer/traits/query/type_op/mod.rs
deleted file mode 100644
index eb4c0a029e1..00000000000
--- a/src/librustc_infer/traits/query/type_op/mod.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use crate::infer::canonical::{
-    Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues, QueryRegionConstraints,
-};
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use crate::traits::ObligationCause;
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-use std::fmt;
-use std::rc::Rc;
-
-pub mod ascribe_user_type;
-pub mod custom;
-pub mod eq;
-pub mod implied_outlives_bounds;
-pub mod normalize;
-pub mod outlives;
-pub mod prove_predicate;
-use self::prove_predicate::ProvePredicate;
-pub mod subtype;
-
-pub use rustc::traits::query::type_op::*;
-
-/// "Type ops" are used in NLL to perform some particular action and
-/// extract out the resulting region constraints (or an error if it
-/// cannot be completed).
-pub trait TypeOp<'tcx>: Sized + fmt::Debug {
-    type Output;
-
-    /// Processes the operation and all resulting obligations,
-    /// returning the final result along with any region constraints
-    /// (they will be given over to the NLL region solver).
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
-}
-
-/// "Query type ops" are type ops that are implemented using a
-/// [canonical query][c]. The `Self` type here contains the kernel of
-/// information needed to do the operation -- `TypeOp` is actually
-/// implemented for `ParamEnvAnd<Self>`, since we always need to bring
-/// along a parameter environment as well. For query type-ops, we will
-/// first canonicalize the key and then invoke the query on the tcx,
-/// which produces the resulting query region constraints.
-///
-/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
-    type QueryResponse: TypeFoldable<'tcx>;
-
-    /// Give query the option for a simple fast path that never
-    /// actually hits the tcx cache lookup etc. Return `Some(r)` with
-    /// a final result or `None` to do the full path.
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse>;
-
-    /// Performs the actual query with the canonicalized key -- the
-    /// real work happens here. This method is not given an `infcx`
-    /// because it shouldn't need one -- and if it had access to one,
-    /// it might do things like invoke `sub_regions`, which would be
-    /// bad, because it would create subregion relationships that are
-    /// not captured in the return value.
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>>;
-
-    fn fully_perform_into(
-        query_key: ParamEnvAnd<'tcx, Self>,
-        infcx: &InferCtxt<'_, 'tcx>,
-        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<Self::QueryResponse> {
-        if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
-            return Ok(result);
-        }
-
-        // FIXME(#33684) -- We need to use
-        // `canonicalize_hr_query_hack` here because of things
-        // like the subtype query, which go awry around
-        // `'static` otherwise.
-        let mut canonical_var_values = OriginalQueryValues::default();
-        let canonical_self =
-            infcx.canonicalize_hr_query_hack(&query_key, &mut canonical_var_values);
-        let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
-
-        let param_env = query_key.param_env;
-
-        let InferOk { value, obligations } = infcx
-            .instantiate_nll_query_response_and_region_obligations(
-                &ObligationCause::dummy(),
-                param_env,
-                &canonical_var_values,
-                canonical_result,
-                output_query_region_constraints,
-            )?;
-
-        // Typically, instantiating NLL query results does not
-        // create obligations. However, in some cases there
-        // are unresolved type variables, and unify them *can*
-        // create obligations. In that case, we have to go
-        // fulfill them. We do this via a (recursive) query.
-        for obligation in obligations {
-            let () = ProvePredicate::fully_perform_into(
-                obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
-                infcx,
-                output_query_region_constraints,
-            )?;
-        }
-
-        Ok(value)
-    }
-}
-
-impl<'tcx, Q> TypeOp<'tcx> for ParamEnvAnd<'tcx, Q>
-where
-    Q: QueryTypeOp<'tcx>,
-{
-    type Output = Q::QueryResponse;
-
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
-        let mut region_constraints = QueryRegionConstraints::default();
-        let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
-
-        // Promote the final query-region-constraints into a
-        // (optional) ref-counted vector:
-        let opt_qrc =
-            if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) };
-
-        Ok((r, opt_qrc))
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/normalize.rs b/src/librustc_infer/traits/query/type_op/normalize.rs
deleted file mode 100644
index d2eec53bf80..00000000000
--- a/src/librustc_infer/traits/query/type_op/normalize.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
-use std::fmt;
-
-pub use rustc::traits::query::type_op::Normalize;
-
-impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
-where
-    T: Normalizable<'tcx> + 'tcx,
-{
-    type QueryResponse = T;
-
-    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
-        if !key.value.value.has_projections() { Some(key.value.value) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        T::type_op_method(tcx, canonicalized)
-    }
-}
-
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>>;
-}
-
-impl Normalizable<'tcx> for Ty<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_ty(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::Predicate<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_predicate(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_poly_fn_sig(canonicalized)
-    }
-}
-
-impl Normalizable<'tcx> for ty::FnSig<'tcx> {
-    fn type_op_method(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self>> {
-        tcx.type_op_normalize_fn_sig(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/outlives.rs b/src/librustc_infer/traits/query/type_op/outlives.rs
deleted file mode 100644
index b94948cffd6..00000000000
--- a/src/librustc_infer/traits/query/type_op/outlives.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
-
-#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)]
-pub struct DropckOutlives<'tcx> {
-    dropped_ty: Ty<'tcx>,
-}
-
-impl<'tcx> DropckOutlives<'tcx> {
-    pub fn new(dropped_ty: Ty<'tcx>) -> Self {
-        DropckOutlives { dropped_ty }
-    }
-}
-
-impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
-    type QueryResponse = DropckOutlivesResult<'tcx>;
-
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
-            Some(DropckOutlivesResult::default())
-        } else {
-            None
-        }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
-        // Subtle: note that we are not invoking
-        // `infcx.at(...).dropck_outlives(...)` here, but rather the
-        // underlying `dropck_outlives` query. This same underlying
-        // query is also used by the
-        // `infcx.at(...).dropck_outlives(...)` fn. Avoiding the
-        // wrapper means we don't need an infcx in this code, which is
-        // good because the interface doesn't give us one (so that we
-        // know we are not registering any subregion relations or
-        // other things).
-
-        // FIXME convert to the type expected by the `dropck_outlives`
-        // query. This should eventually be fixed by changing the
-        // *underlying query*.
-        let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
-            let DropckOutlives { dropped_ty } = value;
-            param_env.and(dropped_ty)
-        });
-
-        tcx.dropck_outlives(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/prove_predicate.rs b/src/librustc_infer/traits/query/type_op/prove_predicate.rs
deleted file mode 100644
index 8c68f7db9e5..00000000000
--- a/src/librustc_infer/traits/query/type_op/prove_predicate.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, Predicate, TyCtxt};
-
-pub use rustc::traits::query::type_op::ProvePredicate;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(
-        tcx: TyCtxt<'tcx>,
-        key: &ParamEnvAnd<'tcx, Self>,
-    ) -> Option<Self::QueryResponse> {
-        // Proving Sized, very often on "obviously sized" types like
-        // `&T`, accounts for about 60% percentage of the predicates
-        // we have to prove. No need to canonicalize and all that for
-        // such cases.
-        if let Predicate::Trait(trait_ref, _) = key.value.predicate {
-            if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
-                if trait_ref.def_id() == sized_def_id {
-                    if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
-                        return Some(());
-                    }
-                }
-            }
-        }
-
-        None
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_prove_predicate(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/query/type_op/subtype.rs b/src/librustc_infer/traits/query/type_op/subtype.rs
deleted file mode 100644
index 053411b0cac..00000000000
--- a/src/librustc_infer/traits/query/type_op/subtype.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
-use crate::traits::query::Fallible;
-use rustc::ty::{ParamEnvAnd, TyCtxt};
-
-pub use rustc::traits::query::type_op::Subtype;
-
-impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
-    type QueryResponse = ();
-
-    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<()> {
-        if key.value.sub == key.value.sup { Some(()) } else { None }
-    }
-
-    fn perform_query(
-        tcx: TyCtxt<'tcx>,
-        canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
-    ) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
-        tcx.type_op_subtype(canonicalized)
-    }
-}
diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs
deleted file mode 100644
index 4c312c9fce2..00000000000
--- a/src/librustc_infer/traits/select.rs
+++ /dev/null
@@ -1,3823 +0,0 @@
-// ignore-tidy-filelength
-
-//! Candidate selection. See the [rustc guide] for more information on how this works.
-//!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
-
-use self::EvaluationResult::*;
-use self::SelectionCandidate::*;
-
-use super::coherence::{self, Conflict};
-use super::project;
-use super::project::{
-    normalize_with_depth, normalize_with_depth_to, Normalized, ProjectionCacheKey,
-};
-use super::util;
-use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
-use super::wf;
-use super::DerivedObligationCause;
-use super::Selection;
-use super::SelectionResult;
-use super::TraitNotObjectSafe;
-use super::TraitQueryMode;
-use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
-use super::{ObjectCastObligation, Obligation};
-use super::{ObligationCause, PredicateObligation, TraitObligation};
-use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
-use super::{
-    VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
-    VtableObject, VtableParam, VtableTraitAlias,
-};
-use super::{
-    VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
-    VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
-};
-
-use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
-use rustc::dep_graph::{DepKind, DepNodeIndex};
-use rustc::middle::lang_items;
-use rustc::ty::fast_reject;
-use rustc::ty::relate::TypeRelation;
-use rustc::ty::subst::{Subst, SubstsRef};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_ast::attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::GrowableBitSet;
-use rustc_span::symbol::sym;
-use rustc_target::spec::abi::Abi;
-
-use std::cell::{Cell, RefCell};
-use std::cmp;
-use std::fmt::{self, Display};
-use std::iter;
-use std::rc::Rc;
-
-pub use rustc::traits::select::*;
-
-pub struct SelectionContext<'cx, 'tcx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
-
-    /// Freshener used specifically for entries on the obligation
-    /// stack. This ensures that all entries on the stack at one time
-    /// will have the same set of placeholder entries, which is
-    /// important for checking for trait bounds that recursively
-    /// require themselves.
-    freshener: TypeFreshener<'cx, 'tcx>,
-
-    /// If `true`, indicates that the evaluation should be conservative
-    /// and consider the possibility of types outside this crate.
-    /// This comes up primarily when resolving ambiguity. Imagine
-    /// there is some trait reference `$0: Bar` where `$0` is an
-    /// inference variable. If `intercrate` is true, then we can never
-    /// say for sure that this reference is not implemented, even if
-    /// there are *no impls at all for `Bar`*, because `$0` could be
-    /// bound to some type that in a downstream crate that implements
-    /// `Bar`. This is the suitable mode for coherence. Elsewhere,
-    /// though, we set this to false, because we are only interested
-    /// in types that the user could actually have written --- in
-    /// other words, we consider `$0: Bar` to be unimplemented if
-    /// there is no type that the user could *actually name* that
-    /// would satisfy it. This avoids crippling inference, basically.
-    intercrate: bool,
-
-    intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
-
-    /// Controls whether or not to filter out negative impls when selecting.
-    /// This is used in librustdoc to distinguish between the lack of an impl
-    /// and a negative impl
-    allow_negative_impls: bool,
-
-    /// The mode that trait queries run in, which informs our error handling
-    /// policy. In essence, canonicalized queries need their errors propagated
-    /// rather than immediately reported because we do not have accurate spans.
-    query_mode: TraitQueryMode,
-}
-
-#[derive(Clone, Debug)]
-pub enum IntercrateAmbiguityCause {
-    DownstreamCrate { trait_desc: String, self_desc: Option<String> },
-    UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
-    ReservationImpl { message: String },
-}
-
-impl IntercrateAmbiguityCause {
-    /// Emits notes when the overlap is caused by complex intercrate ambiguities.
-    /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) {
-        err.note(&self.intercrate_ambiguity_hint());
-    }
-
-    pub fn intercrate_ambiguity_hint(&self) -> String {
-        match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
-            }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
-                    format!(" for type `{}`", ty)
-                } else {
-                    String::new()
-                };
-                format!(
-                    "upstream crates may add a new impl of trait `{}`{} \
-                     in future versions",
-                    trait_desc, self_desc
-                )
-            }
-            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
-        }
-    }
-}
-
-// A stack that walks back up the stack frame.
-struct TraitObligationStack<'prev, 'tcx> {
-    obligation: &'prev TraitObligation<'tcx>,
-
-    /// The trait ref from `obligation` but "freshened" with the
-    /// selection-context's freshener. Used to check for recursion.
-    fresh_trait_ref: ty::PolyTraitRef<'tcx>,
-
-    /// Starts out equal to `depth` -- if, during evaluation, we
-    /// encounter a cycle, then we will set this flag to the minimum
-    /// depth of that cycle for all participants in the cycle. These
-    /// participants will then forego caching their results. This is
-    /// not the most efficient solution, but it addresses #60010. The
-    /// problem we are trying to prevent:
-    ///
-    /// - If you have `A: AutoTrait` requires `B: AutoTrait` and `C: NonAutoTrait`
-    /// - `B: AutoTrait` requires `A: AutoTrait` (coinductive cycle, ok)
-    /// - `C: NonAutoTrait` requires `A: AutoTrait` (non-coinductive cycle, not ok)
-    ///
-    /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
-    /// is `EvaluatedToOk`; this is because they were only considered
-    /// ok on the premise that if `A: AutoTrait` held, but we indeed
-    /// encountered a problem (later on) with `A: AutoTrait. So we
-    /// currently set a flag on the stack node for `B: AutoTrait` (as
-    /// well as the second instance of `A: AutoTrait`) to suppress
-    /// caching.
-    ///
-    /// This is a simple, targeted fix. A more-performant fix requires
-    /// deeper changes, but would permit more caching: we could
-    /// basically defer caching until we have fully evaluated the
-    /// tree, and then cache the entire tree at once. In any case, the
-    /// performance impact here shouldn't be so horrible: every time
-    /// this is hit, we do cache at least one trait, so we only
-    /// evaluate each member of a cycle up to N times, where N is the
-    /// length of the cycle. This means the performance impact is
-    /// bounded and we shouldn't have any terrible worst-cases.
-    reached_depth: Cell<usize>,
-
-    previous: TraitObligationStackList<'prev, 'tcx>,
-
-    /// The number of parent frames plus one (thus, the topmost frame has depth 1).
-    depth: usize,
-
-    /// The depth-first number of this node in the search graph -- a
-    /// pre-order index. Basically, a freshly incremented counter.
-    dfn: usize,
-}
-
-struct SelectionCandidateSet<'tcx> {
-    // A list of candidates that definitely apply to the current
-    // obligation (meaning: types unify).
-    vec: Vec<SelectionCandidate<'tcx>>,
-
-    // If `true`, then there were candidates that might or might
-    // not have applied, but we couldn't tell. This occurs when some
-    // of the input types are type variables, in which case there are
-    // various "builtin" rules that might or might not trigger.
-    ambiguous: bool,
-}
-
-#[derive(PartialEq, Eq, Debug, Clone)]
-struct EvaluatedCandidate<'tcx> {
-    candidate: SelectionCandidate<'tcx>,
-    evaluation: EvaluationResult,
-}
-
-/// When does the builtin impl for `T: Trait` apply?
-enum BuiltinImplConditions<'tcx> {
-    /// The impl is conditional on `T1, T2, ...: Trait`.
-    Where(ty::Binder<Vec<Ty<'tcx>>>),
-    /// There is no built-in impl. There may be some other
-    /// candidate (a where-clause or user-defined impl).
-    None,
-    /// It is unknown whether there is an impl.
-    Ambiguous,
-}
-
-impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: true,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn with_negative(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        allow_negative_impls: bool,
-    ) -> SelectionContext<'cx, 'tcx> {
-        debug!("with_negative({:?})", allow_negative_impls);
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn with_query_mode(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        query_mode: TraitQueryMode,
-    ) -> SelectionContext<'cx, 'tcx> {
-        debug!("with_query_mode({:?})", query_mode);
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode,
-        }
-    }
-
-    /// Enables tracking of intercrate ambiguity causes. These are
-    /// used in coherence to give improved diagnostics. We don't do
-    /// this until we detect a coherence error because it can lead to
-    /// false overflow results (#47139) and because it costs
-    /// computation time.
-    pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
-        assert!(self.intercrate);
-        assert!(self.intercrate_ambiguity_causes.is_none());
-        self.intercrate_ambiguity_causes = Some(vec![]);
-        debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
-    }
-
-    /// Gets the intercrate ambiguity causes collected since tracking
-    /// was enabled and disables tracking at the same time. If
-    /// tracking is not enabled, just returns an empty vector.
-    pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
-        assert!(self.intercrate);
-        self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
-    }
-
-    pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
-        self.infcx
-    }
-
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
-        self.infcx
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Selection
-    //
-    // The selection phase tries to identify *how* an obligation will
-    // be resolved. For example, it will identify which impl or
-    // parameter bound is to be used. The process can be inconclusive
-    // if the self type in the obligation is not fully inferred. Selection
-    // can result in an error in one of two ways:
-    //
-    // 1. If no applicable impl or parameter bound can be found.
-    // 2. If the output type parameters in the obligation do not match
-    //    those specified by the impl/bound. For example, if the obligation
-    //    is `Vec<Foo>: Iterable<Bar>`, but the impl specifies
-    //    `impl<T> Iterable<T> for Vec<T>`, than an error would result.
-
-    /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
-    /// type environment by performing unification.
-    pub fn select(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> SelectionResult<'tcx, Selection<'tcx>> {
-        debug!("select({:?})", obligation);
-        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
-
-        let pec = &ProvisionalEvaluationCache::default();
-        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);
-
-        let candidate = match self.candidate_from_obligation(&stack) {
-            Err(SelectionError::Overflow) => {
-                // In standard mode, overflow must have been caught and reported
-                // earlier.
-                assert!(self.query_mode == TraitQueryMode::Canonical);
-                return Err(SelectionError::Overflow);
-            }
-            Err(e) => {
-                return Err(e);
-            }
-            Ok(None) => {
-                return Ok(None);
-            }
-            Ok(Some(candidate)) => candidate,
-        };
-
-        match self.confirm_candidate(obligation, candidate) {
-            Err(SelectionError::Overflow) => {
-                assert!(self.query_mode == TraitQueryMode::Canonical);
-                Err(SelectionError::Overflow)
-            }
-            Err(e) => Err(e),
-            Ok(candidate) => Ok(Some(candidate)),
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // EVALUATION
-    //
-    // Tests whether an obligation can be selected or whether an impl
-    // can be applied to particular types. It skips the "confirmation"
-    // step and hence completely ignores output type parameters.
-    //
-    // The result is "true" if the obligation *may* hold and "false" if
-    // we can be sure it does not.
-
-    /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
-    pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
-        debug!("predicate_may_hold_fatal({:?})", obligation);
-
-        // This fatal query is a stopgap that should only be used in standard mode,
-        // where we do not expect overflow to be propagated.
-        assert!(self.query_mode == TraitQueryMode::Standard);
-
-        self.evaluate_root_obligation(obligation)
-            .expect("Overflow should be caught earlier in standard query mode")
-            .may_apply()
-    }
-
-    /// Evaluates whether the obligation `obligation` can be satisfied
-    /// and returns an `EvaluationResult`. This is meant for the
-    /// *initial* call.
-    pub fn evaluate_root_obligation(
-        &mut self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.evaluation_probe(|this| {
-            this.evaluate_predicate_recursively(
-                TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
-                obligation.clone(),
-            )
-        })
-    }
-
-    fn evaluation_probe(
-        &mut self,
-        op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
-            let result = op(self)?;
-            match self.infcx.region_constraints_added_in_snapshot(snapshot) {
-                None => Ok(result),
-                Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
-            }
-        })
-    }
-
-    /// Evaluates the predicates in `predicates` recursively. Note that
-    /// this applies projections in the predicates, and therefore
-    /// is run within an inference probe.
-    fn evaluate_predicates_recursively<'o, I>(
-        &mut self,
-        stack: TraitObligationStackList<'o, 'tcx>,
-        predicates: I,
-    ) -> Result<EvaluationResult, OverflowError>
-    where
-        I: IntoIterator<Item = PredicateObligation<'tcx>>,
-    {
-        let mut result = EvaluatedToOk;
-        for obligation in predicates {
-            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
-            debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
-            if let EvaluatedToErr = eval {
-                // fast-path - EvaluatedToErr is the top of the lattice,
-                // so we don't need to look on the other predicates.
-                return Ok(EvaluatedToErr);
-            } else {
-                result = cmp::max(result, eval);
-            }
-        }
-        Ok(result)
-    }
-
-    fn evaluate_predicate_recursively<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!(
-            "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
-            previous_stack.head(),
-            obligation
-        );
-
-        // `previous_stack` stores a `TraitObligatiom`, while `obligation` is
-        // a `PredicateObligation`. These are distinct types, so we can't
-        // use any `Option` combinator method that would force them to be
-        // the same.
-        match previous_stack.head() {
-            Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
-            None => self.check_recursion_limit(&obligation, &obligation)?,
-        }
-
-        match obligation.predicate {
-            ty::Predicate::Trait(ref t, _) => {
-                debug_assert!(!t.has_escaping_bound_vars());
-                let obligation = obligation.with(t.clone());
-                self.evaluate_trait_predicate_recursively(previous_stack, obligation)
-            }
-
-            ty::Predicate::Subtype(ref p) => {
-                // Does this code ever run?
-                match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
-                    Some(Ok(InferOk { mut obligations, .. })) => {
-                        self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
-                        self.evaluate_predicates_recursively(
-                            previous_stack,
-                            obligations.into_iter(),
-                        )
-                    }
-                    Some(Err(_)) => Ok(EvaluatedToErr),
-                    None => Ok(EvaluatedToAmbig),
-                }
-            }
-
-            ty::Predicate::WellFormed(ty) => match wf::obligations(
-                self.infcx,
-                obligation.param_env,
-                obligation.cause.body_id,
-                ty,
-                obligation.cause.span,
-            ) {
-                Some(mut obligations) => {
-                    self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
-                    self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
-                }
-                None => Ok(EvaluatedToAmbig),
-            },
-
-            ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
-                // We do not consider region relationships when evaluating trait matches.
-                Ok(EvaluatedToOkModuloRegions)
-            }
-
-            ty::Predicate::ObjectSafe(trait_def_id) => {
-                if self.tcx().is_object_safe(trait_def_id) {
-                    Ok(EvaluatedToOk)
-                } else {
-                    Ok(EvaluatedToErr)
-                }
-            }
-
-            ty::Predicate::Projection(ref data) => {
-                let project_obligation = obligation.with(data.clone());
-                match project::poly_project_and_unify_type(self, &project_obligation) {
-                    Ok(Some(mut subobligations)) => {
-                        self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
-                        let result = self.evaluate_predicates_recursively(
-                            previous_stack,
-                            subobligations.into_iter(),
-                        );
-                        if let Some(key) =
-                            ProjectionCacheKey::from_poly_projection_predicate(self, data)
-                        {
-                            self.infcx.inner.borrow_mut().projection_cache.complete(key);
-                        }
-                        result
-                    }
-                    Ok(None) => Ok(EvaluatedToAmbig),
-                    Err(_) => Ok(EvaluatedToErr),
-                }
-            }
-
-            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                match self.infcx.closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        if closure_kind.extends(kind) {
-                            Ok(EvaluatedToOk)
-                        } else {
-                            Ok(EvaluatedToErr)
-                        }
-                    }
-                    None => Ok(EvaluatedToAmbig),
-                }
-            }
-
-            ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.tcx().const_eval_resolve(
-                    obligation.param_env,
-                    def_id,
-                    substs,
-                    None,
-                    None,
-                ) {
-                    Ok(_) => Ok(EvaluatedToOk),
-                    Err(_) => Ok(EvaluatedToErr),
-                }
-            }
-        }
-    }
-
-    fn evaluate_trait_predicate_recursively<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        mut obligation: TraitObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!("evaluate_trait_predicate_recursively({:?})", obligation);
-
-        if !self.intercrate
-            && obligation.is_global()
-            && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst())
-        {
-            // If a param env has no global bounds, global obligations do not
-            // depend on its particular value in order to work, so we can clear
-            // out the param env and get better caching.
-            debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation);
-            obligation.param_env = obligation.param_env.without_caller_bounds();
-        }
-
-        let stack = self.push_stack(previous_stack, &obligation);
-        let fresh_trait_ref = stack.fresh_trait_ref;
-        if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) {
-            debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
-            return Ok(result);
-        }
-
-        if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) {
-            debug!("PROVISIONAL CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
-            stack.update_reached_depth(stack.cache().current_reached_depth());
-            return Ok(result);
-        }
-
-        // Check if this is a match for something already on the
-        // stack. If so, we don't want to insert the result into the
-        // main cache (it is cycle dependent) nor the provisional
-        // cache (which is meant for things that have completed but
-        // for a "backedge" -- this result *is* the backedge).
-        if let Some(cycle_result) = self.check_evaluation_cycle(&stack) {
-            return Ok(cycle_result);
-        }
-
-        let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
-        let result = result?;
-
-        if !result.must_apply_modulo_regions() {
-            stack.cache().on_failure(stack.dfn);
-        }
-
-        let reached_depth = stack.reached_depth.get();
-        if reached_depth >= stack.depth {
-            debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result);
-            self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
-
-            stack.cache().on_completion(stack.depth, |fresh_trait_ref, provisional_result| {
-                self.insert_evaluation_cache(
-                    obligation.param_env,
-                    fresh_trait_ref,
-                    dep_node,
-                    provisional_result.max(result),
-                );
-            });
-        } else {
-            debug!("PROVISIONAL: {:?}={:?}", fresh_trait_ref, result);
-            debug!(
-                "evaluate_trait_predicate_recursively: caching provisionally because {:?} \
-                 is a cycle participant (at depth {}, reached depth {})",
-                fresh_trait_ref, stack.depth, reached_depth,
-            );
-
-            stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result);
-        }
-
-        Ok(result)
-    }
-
-    /// If there is any previous entry on the stack that precisely
-    /// matches this obligation, then we can assume that the
-    /// obligation is satisfied for now (still all other conditions
-    /// must be met of course). One obvious case this comes up is
-    /// marker traits like `Send`. Think of a linked list:
-    ///
-    ///    struct List<T> { data: T, next: Option<Box<List<T>>> }
-    ///
-    /// `Box<List<T>>` will be `Send` if `T` is `Send` and
-    /// `Option<Box<List<T>>>` is `Send`, and in turn
-    /// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` is
-    /// `Send`.
-    ///
-    /// Note that we do this comparison using the `fresh_trait_ref`
-    /// fields. Because these have all been freshened using
-    /// `self.freshener`, we can be sure that (a) this will not
-    /// affect the inferencer state and (b) that if we see two
-    /// fresh regions with the same index, they refer to the same
-    /// unbound type variable.
-    fn check_evaluation_cycle(
-        &mut self,
-        stack: &TraitObligationStack<'_, 'tcx>,
-    ) -> Option<EvaluationResult> {
-        if let Some(cycle_depth) = stack
-            .iter()
-            .skip(1) // Skip top-most frame.
-            .find(|prev| {
-                stack.obligation.param_env == prev.obligation.param_env
-                    && stack.fresh_trait_ref == prev.fresh_trait_ref
-            })
-            .map(|stack| stack.depth)
-        {
-            debug!(
-                "evaluate_stack({:?}) --> recursive at depth {}",
-                stack.fresh_trait_ref, cycle_depth,
-            );
-
-            // If we have a stack like `A B C D E A`, where the top of
-            // the stack is the final `A`, then this will iterate over
-            // `A, E, D, C, B` -- i.e., all the participants apart
-            // from the cycle head. We mark them as participating in a
-            // cycle. This suppresses caching for those nodes. See
-            // `in_cycle` field for more details.
-            stack.update_reached_depth(cycle_depth);
-
-            // Subtle: when checking for a coinductive cycle, we do
-            // not compare using the "freshened trait refs" (which
-            // have erased regions) but rather the fully explicit
-            // trait refs. This is important because it's only a cycle
-            // if the regions match exactly.
-            let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
-            let cycle = cycle.map(|stack| {
-                ty::Predicate::Trait(stack.obligation.predicate, hir::Constness::NotConst)
-            });
-            if self.coinductive_match(cycle) {
-                debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
-                Some(EvaluatedToOk)
-            } else {
-                debug!("evaluate_stack({:?}) --> recursive, inductive", stack.fresh_trait_ref);
-                Some(EvaluatedToRecur)
-            }
-        } else {
-            None
-        }
-    }
-
-    fn evaluate_stack<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        // In intercrate mode, whenever any of the types are unbound,
-        // there can always be an impl. Even if there are no impls in
-        // this crate, perhaps the type would be unified with
-        // something from another crate that does provide an impl.
-        //
-        // In intra mode, we must still be conservative. The reason is
-        // that we want to avoid cycles. Imagine an impl like:
-        //
-        //     impl<T:Eq> Eq for Vec<T>
-        //
-        // and a trait reference like `$0 : Eq` where `$0` is an
-        // unbound variable. When we evaluate this trait-reference, we
-        // will unify `$0` with `Vec<$1>` (for some fresh variable
-        // `$1`), on the condition that `$1 : Eq`. We will then wind
-        // up with many candidates (since that are other `Eq` impls
-        // that apply) and try to winnow things down. This results in
-        // a recursive evaluation that `$1 : Eq` -- as you can
-        // imagine, this is just where we started. To avoid that, we
-        // check for unbound variables and return an ambiguous (hence possible)
-        // match if we've seen this trait before.
-        //
-        // This suffices to allow chains like `FnMut` implemented in
-        // terms of `Fn` etc, but we could probably make this more
-        // precise still.
-        let unbound_input_types =
-            stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh());
-        // This check was an imperfect workaround for a bug in the old
-        // intercrate mode; it should be removed when that goes away.
-        if unbound_input_types && self.intercrate {
-            debug!(
-                "evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
-                stack.fresh_trait_ref
-            );
-            // Heuristics: show the diagnostics when there are no candidates in crate.
-            if self.intercrate_ambiguity_causes.is_some() {
-                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                    if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
-                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                        let self_ty = trait_ref.self_ty();
-                        let cause = IntercrateAmbiguityCause::DownstreamCrate {
-                            trait_desc: trait_ref.print_only_trait_path().to_string(),
-                            self_desc: if self_ty.has_concrete_skeleton() {
-                                Some(self_ty.to_string())
-                            } else {
-                                None
-                            },
-                        };
-                        debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
-                    }
-                }
-            }
-            return Ok(EvaluatedToAmbig);
-        }
-        if unbound_input_types
-            && stack.iter().skip(1).any(|prev| {
-                stack.obligation.param_env == prev.obligation.param_env
-                    && self.match_fresh_trait_refs(
-                        &stack.fresh_trait_ref,
-                        &prev.fresh_trait_ref,
-                        prev.obligation.param_env,
-                    )
-            })
-        {
-            debug!(
-                "evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
-                stack.fresh_trait_ref
-            );
-            return Ok(EvaluatedToUnknown);
-        }
-
-        match self.candidate_from_obligation(stack) {
-            Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Ok(None) => Ok(EvaluatedToAmbig),
-            Err(Overflow) => Err(OverflowError),
-            Err(..) => Ok(EvaluatedToErr),
-        }
-    }
-
-    /// For defaulted traits, we use a co-inductive strategy to solve, so
-    /// that recursion is ok. This routine returns `true` if the top of the
-    /// stack (`cycle[0]`):
-    ///
-    /// - is a defaulted trait,
-    /// - it also appears in the backtrace at some position `X`,
-    /// - all the predicates at positions `X..` between `X` and the top are
-    ///   also defaulted traits.
-    pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
-    where
-        I: Iterator<Item = ty::Predicate<'tcx>>,
-    {
-        let mut cycle = cycle;
-        cycle.all(|predicate| self.coinductive_predicate(predicate))
-    }
-
-    fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
-        let result = match predicate {
-            ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
-            _ => false,
-        };
-        debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
-        result
-    }
-
-    /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
-    /// obligations are met. Returns whether `candidate` remains viable after this further
-    /// scrutiny.
-    fn evaluate_candidate<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        candidate: &SelectionCandidate<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        debug!(
-            "evaluate_candidate: depth={} candidate={:?}",
-            stack.obligation.recursion_depth, candidate
-        );
-        let result = self.evaluation_probe(|this| {
-            let candidate = (*candidate).clone();
-            match this.confirm_candidate(stack.obligation, candidate) {
-                Ok(selection) => this.evaluate_predicates_recursively(
-                    stack.list(),
-                    selection.nested_obligations().into_iter(),
-                ),
-                Err(..) => Ok(EvaluatedToErr),
-            }
-        })?;
-        debug!(
-            "evaluate_candidate: depth={} result={:?}",
-            stack.obligation.recursion_depth, result
-        );
-        Ok(result)
-    }
-
-    fn check_evaluation_cache(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Option<EvaluationResult> {
-        let tcx = self.tcx();
-        if self.can_use_global_caches(param_env) {
-            let cache = tcx.evaluation_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&param_env.and(trait_ref)) {
-                return Some(cached.get(tcx));
-            }
-        }
-        self.infcx
-            .evaluation_cache
-            .hashmap
-            .borrow()
-            .get(&param_env.and(trait_ref))
-            .map(|v| v.get(tcx))
-    }
-
-    fn insert_evaluation_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        dep_node: DepNodeIndex,
-        result: EvaluationResult,
-    ) {
-        // Avoid caching results that depend on more than just the trait-ref
-        // - the stack can create recursion.
-        if result.is_stack_dependent() {
-            return;
-        }
-
-        if self.can_use_global_caches(param_env) {
-            if !trait_ref.has_local_value() {
-                debug!(
-                    "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
-                    trait_ref, result,
-                );
-                // This may overwrite the cache with the same value
-                // FIXME: Due to #50507 this overwrites the different values
-                // This should be changed to use HashMapExt::insert_same
-                // when that is fixed
-                self.tcx()
-                    .evaluation_cache
-                    .hashmap
-                    .borrow_mut()
-                    .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
-                return;
-            }
-        }
-
-        debug!("insert_evaluation_cache(trait_ref={:?}, candidate={:?})", trait_ref, result,);
-        self.infcx
-            .evaluation_cache
-            .hashmap
-            .borrow_mut()
-            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, result));
-    }
-
-    /// For various reasons, it's possible for a subobligation
-    /// to have a *lower* recursion_depth than the obligation used to create it.
-    /// Projection sub-obligations may be returned from the projection cache,
-    /// which results in obligations with an 'old' `recursion_depth`.
-    /// Additionally, methods like `wf::obligations` and
-    /// `InferCtxt.subtype_predicate` produce subobligations without
-    /// taking in a 'parent' depth, causing the generated subobligations
-    /// to have a `recursion_depth` of `0`.
-    ///
-    /// To ensure that obligation_depth never decreasees, we force all subobligations
-    /// to have at least the depth of the original obligation.
-    fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(
-        &self,
-        it: I,
-        min_depth: usize,
-    ) {
-        it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
-    }
-
-    /// Checks that the recursion limit has not been exceeded.
-    ///
-    /// The weird return type of this function allows it to be used with the `try` (`?`)
-    /// operator within certain functions.
-    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        error_obligation: &Obligation<'tcx, V>,
-    ) -> Result<(), OverflowError> {
-        let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
-        if obligation.recursion_depth >= recursion_limit {
-            match self.query_mode {
-                TraitQueryMode::Standard => {
-                    self.infcx().report_overflow_error(error_obligation, true);
-                }
-                TraitQueryMode::Canonical => {
-                    return Err(OverflowError);
-                }
-            }
-        }
-        Ok(())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // CANDIDATE ASSEMBLY
-    //
-    // The selection process begins by examining all in-scope impls,
-    // caller obligations, and so forth and assembling a list of
-    // candidates. See the [rustc guide] for more details.
-    //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly
-
-    fn candidate_from_obligation<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        // Watch out for overflow. This intentionally bypasses (and does
-        // not update) the cache.
-        self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
-
-        // Check the cache. Note that we freshen the trait-ref
-        // separately rather than using `stack.fresh_trait_ref` --
-        // this is because we want the unbound variables to be
-        // replaced with fresh types starting from index 0.
-        let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone());
-        debug!(
-            "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
-            cache_fresh_trait_pred, stack
-        );
-        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
-
-        if let Some(c) =
-            self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
-        {
-            debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c);
-            return c;
-        }
-
-        // If no match, compute result and insert into cache.
-        //
-        // FIXME(nikomatsakis) -- this cache is not taking into
-        // account cycles that may have occurred in forming the
-        // candidate. I don't know of any specific problems that
-        // result but it seems awfully suspicious.
-        let (candidate, dep_node) =
-            self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
-
-        debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate);
-        self.insert_candidate_cache(
-            stack.obligation.param_env,
-            cache_fresh_trait_pred,
-            dep_node,
-            candidate.clone(),
-        );
-        candidate
-    }
-
-    fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
-    where
-        OP: FnOnce(&mut Self) -> R,
-    {
-        let (result, dep_node) =
-            self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self));
-        self.tcx().dep_graph.read_index(dep_node);
-        (result, dep_node)
-    }
-
-    // Treat negative impls as unimplemented, and reservation impls as ambiguity.
-    fn filter_negative_and_reservation_impls(
-        &mut self,
-        candidate: SelectionCandidate<'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        if let ImplCandidate(def_id) = candidate {
-            let tcx = self.tcx();
-            match tcx.impl_polarity(def_id) {
-                ty::ImplPolarity::Negative if !self.allow_negative_impls => {
-                    return Err(Unimplemented);
-                }
-                ty::ImplPolarity::Reservation => {
-                    if let Some(intercrate_ambiguity_clauses) =
-                        &mut self.intercrate_ambiguity_causes
-                    {
-                        let attrs = tcx.get_attrs(def_id);
-                        let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
-                        let value = attr.and_then(|a| a.value_str());
-                        if let Some(value) = value {
-                            debug!(
-                                "filter_negative_and_reservation_impls: \
-                                 reservation impl ambiguity on {:?}",
-                                def_id
-                            );
-                            intercrate_ambiguity_clauses.push(
-                                IntercrateAmbiguityCause::ReservationImpl {
-                                    message: value.to_string(),
-                                },
-                            );
-                        }
-                    }
-                    return Ok(None);
-                }
-                _ => {}
-            };
-        }
-        Ok(Some(candidate))
-    }
-
-    fn candidate_from_obligation_no_cache<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        if stack.obligation.predicate.references_error() {
-            // If we encounter a `Error`, we generally prefer the
-            // most "optimistic" result in response -- that is, the
-            // one least likely to report downstream errors. But
-            // because this routine is shared by coherence and by
-            // trait selection, there isn't an obvious "right" choice
-            // here in that respect, so we opt to just return
-            // ambiguity and let the upstream clients sort it out.
-            return Ok(None);
-        }
-
-        if let Some(conflict) = self.is_knowable(stack) {
-            debug!("coherence stage: not knowable");
-            if self.intercrate_ambiguity_causes.is_some() {
-                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
-                // Heuristics: show the diagnostics when there are no candidates in crate.
-                if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                    let mut no_candidates_apply = true;
-                    {
-                        let evaluated_candidates =
-                            candidate_set.vec.iter().map(|c| self.evaluate_candidate(stack, &c));
-
-                        for ec in evaluated_candidates {
-                            match ec {
-                                Ok(c) => {
-                                    if c.may_apply() {
-                                        no_candidates_apply = false;
-                                        break;
-                                    }
-                                }
-                                Err(e) => return Err(e.into()),
-                            }
-                        }
-                    }
-
-                    if !candidate_set.ambiguous && no_candidates_apply {
-                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                        let self_ty = trait_ref.self_ty();
-                        let trait_desc = trait_ref.print_only_trait_path().to_string();
-                        let self_desc = if self_ty.has_concrete_skeleton() {
-                            Some(self_ty.to_string())
-                        } else {
-                            None
-                        };
-                        let cause = if let Conflict::Upstream = conflict {
-                            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
-                        } else {
-                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
-                        };
-                        debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
-                    }
-                }
-            }
-            return Ok(None);
-        }
-
-        let candidate_set = self.assemble_candidates(stack)?;
-
-        if candidate_set.ambiguous {
-            debug!("candidate set contains ambig");
-            return Ok(None);
-        }
-
-        let mut candidates = candidate_set.vec;
-
-        debug!("assembled {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
-
-        // At this point, we know that each of the entries in the
-        // candidate set is *individually* applicable. Now we have to
-        // figure out if they contain mutual incompatibilities. This
-        // frequently arises if we have an unconstrained input type --
-        // for example, we are looking for `$0: Eq` where `$0` is some
-        // unconstrained type variable. In that case, we'll get a
-        // candidate which assumes $0 == int, one that assumes `$0 ==
-        // usize`, etc. This spells an ambiguity.
-
-        // If there is more than one candidate, first winnow them down
-        // by considering extra conditions (nested obligations and so
-        // forth). We don't winnow if there is exactly one
-        // candidate. This is a relatively minor distinction but it
-        // can lead to better inference and error-reporting. An
-        // example would be if there was an impl:
-        //
-        //     impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
-        //
-        // and we were to see some code `foo.push_clone()` where `boo`
-        // is a `Vec<Bar>` and `Bar` does not implement `Clone`.  If
-        // we were to winnow, we'd wind up with zero candidates.
-        // Instead, we select the right impl now but report "`Bar` does
-        // not implement `Clone`".
-        if candidates.len() == 1 {
-            return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
-        }
-
-        // Winnow, but record the exact outcome of evaluation, which
-        // is needed for specialization. Propagate overflow if it occurs.
-        let mut candidates = candidates
-            .into_iter()
-            .map(|c| match self.evaluate_candidate(stack, &c) {
-                Ok(eval) if eval.may_apply() => {
-                    Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))
-                }
-                Ok(_) => Ok(None),
-                Err(OverflowError) => Err(Overflow),
-            })
-            .flat_map(Result::transpose)
-            .collect::<Result<Vec<_>, _>>()?;
-
-        debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
-
-        let needs_infer = stack.obligation.predicate.needs_infer();
-
-        // If there are STILL multiple candidates, we can further
-        // reduce the list by dropping duplicates -- including
-        // resolving specializations.
-        if candidates.len() > 1 {
-            let mut i = 0;
-            while i < candidates.len() {
-                let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
-                    self.candidate_should_be_dropped_in_favor_of(
-                        &candidates[i],
-                        &candidates[j],
-                        needs_infer,
-                    )
-                });
-                if is_dup {
-                    debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
-                    candidates.swap_remove(i);
-                } else {
-                    debug!("Retaining candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
-                    i += 1;
-
-                    // If there are *STILL* multiple candidates, give up
-                    // and report ambiguity.
-                    if i > 1 {
-                        debug!("multiple matches, ambig");
-                        return Ok(None);
-                    }
-                }
-            }
-        }
-
-        // If there are *NO* candidates, then there are no impls --
-        // that we know of, anyway. Note that in the case where there
-        // are unbound type variables within the obligation, it might
-        // be the case that you could still satisfy the obligation
-        // from another crate by instantiating the type variables with
-        // a type from another crate that does have an impl. This case
-        // is checked for in `evaluate_stack` (and hence users
-        // who might care about this case, like coherence, should use
-        // that function).
-        if candidates.is_empty() {
-            return Err(Unimplemented);
-        }
-
-        // Just one candidate left.
-        self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
-    }
-
-    fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
-        debug!("is_knowable(intercrate={:?})", self.intercrate);
-
-        if !self.intercrate {
-            return None;
-        }
-
-        let obligation = &stack.obligation;
-        let predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
-
-        // Okay to skip binder because of the nature of the
-        // trait-ref-is-knowable check, which does not care about
-        // bound regions.
-        let trait_ref = predicate.skip_binder().trait_ref;
-
-        coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
-    }
-
-    /// Returns `true` if the global caches can be used.
-    /// Do note that if the type itself is not in the
-    /// global tcx, the local caches will be used.
-    fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
-        // If there are any e.g. inference variables in the `ParamEnv`, then we
-        // always use a cache local to this particular scope. Otherwise, we
-        // switch to a global cache.
-        if param_env.has_local_value() {
-            return false;
-        }
-
-        // Avoid using the master cache during coherence and just rely
-        // on the local cache. This effectively disables caching
-        // during coherence. It is really just a simplification to
-        // avoid us having to fear that coherence results "pollute"
-        // the master cache. Since coherence executes pretty quickly,
-        // it's not worth going to more trouble to increase the
-        // hit-rate, I don't think.
-        if self.intercrate {
-            return false;
-        }
-
-        // Otherwise, we can use the global cache.
-        true
-    }
-
-    fn check_candidate_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>,
-    ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
-        let tcx = self.tcx();
-        let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
-        if self.can_use_global_caches(param_env) {
-            let cache = tcx.selection_cache.hashmap.borrow();
-            if let Some(cached) = cache.get(&param_env.and(*trait_ref)) {
-                return Some(cached.get(tcx));
-            }
-        }
-        self.infcx
-            .selection_cache
-            .hashmap
-            .borrow()
-            .get(&param_env.and(*trait_ref))
-            .map(|v| v.get(tcx))
-    }
-
-    /// Determines whether can we safely cache the result
-    /// of selecting an obligation. This is almost always `true`,
-    /// except when dealing with certain `ParamCandidate`s.
-    ///
-    /// Ordinarily, a `ParamCandidate` will contain no inference variables,
-    /// since it was usually produced directly from a `DefId`. However,
-    /// certain cases (currently only librustdoc's blanket impl finder),
-    /// a `ParamEnv` may be explicitly constructed with inference types.
-    /// When this is the case, we do *not* want to cache the resulting selection
-    /// candidate. This is due to the fact that it might not always be possible
-    /// to equate the obligation's trait ref and the candidate's trait ref,
-    /// if more constraints end up getting added to an inference variable.
-    ///
-    /// Because of this, we always want to re-run the full selection
-    /// process for our obligation the next time we see it, since
-    /// we might end up picking a different `SelectionCandidate` (or none at all).
-    fn can_cache_candidate(
-        &self,
-        result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
-    ) -> bool {
-        match result {
-            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => {
-                !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer()))
-            }
-            _ => true,
-        }
-    }
-
-    fn insert_candidate_cache(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
-        dep_node: DepNodeIndex,
-        candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
-    ) {
-        let tcx = self.tcx();
-        let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
-
-        if !self.can_cache_candidate(&candidate) {
-            debug!(
-                "insert_candidate_cache(trait_ref={:?}, candidate={:?} -\
-                 candidate is not cacheable",
-                trait_ref, candidate
-            );
-            return;
-        }
-
-        if self.can_use_global_caches(param_env) {
-            if let Err(Overflow) = candidate {
-                // Don't cache overflow globally; we only produce this in certain modes.
-            } else if !trait_ref.has_local_value() {
-                if !candidate.has_local_value() {
-                    debug!(
-                        "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
-                        trait_ref, candidate,
-                    );
-                    // This may overwrite the cache with the same value.
-                    tcx.selection_cache
-                        .hashmap
-                        .borrow_mut()
-                        .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
-                    return;
-                }
-            }
-        }
-
-        debug!(
-            "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
-            trait_ref, candidate,
-        );
-        self.infcx
-            .selection_cache
-            .hashmap
-            .borrow_mut()
-            .insert(param_env.and(trait_ref), WithDepNode::new(dep_node, candidate));
-    }
-
-    fn assemble_candidates<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-    ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
-        let TraitObligationStack { obligation, .. } = *stack;
-        let ref obligation = Obligation {
-            param_env: obligation.param_env,
-            cause: obligation.cause.clone(),
-            recursion_depth: obligation.recursion_depth,
-            predicate: self.infcx().resolve_vars_if_possible(&obligation.predicate),
-        };
-
-        if obligation.predicate.skip_binder().self_ty().is_ty_var() {
-            // Self is a type variable (e.g., `_: AsRef<str>`).
-            //
-            // This is somewhat problematic, as the current scheme can't really
-            // handle it turning to be a projection. This does end up as truly
-            // ambiguous in most cases anyway.
-            //
-            // Take the fast path out - this also improves
-            // performance by preventing assemble_candidates_from_impls from
-            // matching every impl for this trait.
-            return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
-        }
-
-        let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
-
-        self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
-
-        // Other bounds. Consider both in-scope bounds from fn decl
-        // and applicable impls. There is a certain set of precedence rules here.
-        let def_id = obligation.predicate.def_id();
-        let lang_items = self.tcx().lang_items();
-
-        if lang_items.copy_trait() == Some(def_id) {
-            debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty());
-
-            // User-defined copy impls are permitted, but only for
-            // structs and enums.
-            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-
-            // For other types, we'll use the builtin rules.
-            let copy_conditions = self.copy_clone_conditions(obligation);
-            self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
-        } else if lang_items.sized_trait() == Some(def_id) {
-            // Sized is never implementable by end-users, it is
-            // always automatically computed.
-            let sized_conditions = self.sized_conditions(obligation);
-            self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?;
-        } else if lang_items.unsize_trait() == Some(def_id) {
-            self.assemble_candidates_for_unsizing(obligation, &mut candidates);
-        } else {
-            if lang_items.clone_trait() == Some(def_id) {
-                // Same builtin conditions as `Copy`, i.e., every type which has builtin support
-                // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
-                // types have builtin support for `Clone`.
-                let clone_conditions = self.copy_clone_conditions(obligation);
-                self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
-            }
-
-            self.assemble_generator_candidates(obligation, &mut candidates)?;
-            self.assemble_closure_candidates(obligation, &mut candidates)?;
-            self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
-            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-            self.assemble_candidates_from_object_ty(obligation, &mut candidates);
-        }
-
-        self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
-        self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-        // Auto implementations have lower priority, so we only
-        // consider triggering a default if there is no other impl that can apply.
-        if candidates.vec.is_empty() {
-            self.assemble_candidates_from_auto_impls(obligation, &mut candidates)?;
-        }
-        debug!("candidate list size: {}", candidates.vec.len());
-        Ok(candidates)
-    }
-
-    fn assemble_candidates_from_projected_tys(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        debug!("assemble_candidates_for_projected_tys({:?})", obligation);
-
-        // Before we go into the whole placeholder thing, just
-        // quickly check if the self-type is a projection at all.
-        match obligation.predicate.skip_binder().trait_ref.self_ty().kind {
-            ty::Projection(_) | ty::Opaque(..) => {}
-            ty::Infer(ty::TyVar(_)) => {
-                span_bug!(
-                    obligation.cause.span,
-                    "Self=_ should have been handled by assemble_candidates"
-                );
-            }
-            _ => return,
-        }
-
-        let result = self.infcx.probe(|snapshot| {
-            self.match_projection_obligation_against_definition_bounds(obligation, snapshot)
-        });
-
-        if result {
-            candidates.vec.push(ProjectionCandidate);
-        }
-    }
-
-    fn match_projection_obligation_against_definition_bounds(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> bool {
-        let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
-        let (placeholder_trait_predicate, placeholder_map) =
-            self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             placeholder_trait_predicate={:?}",
-            placeholder_trait_predicate,
-        );
-
-        let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
-            ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
-            ty::Opaque(def_id, substs) => (def_id, substs),
-            _ => {
-                span_bug!(
-                    obligation.cause.span,
-                    "match_projection_obligation_against_definition_bounds() called \
-                     but self-ty is not a projection: {:?}",
-                    placeholder_trait_predicate.trait_ref.self_ty()
-                );
-            }
-        };
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             def_id={:?}, substs={:?}",
-            def_id, substs
-        );
-
-        let predicates_of = self.tcx().predicates_of(def_id);
-        let bounds = predicates_of.instantiate(self.tcx(), substs);
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             bounds={:?}",
-            bounds
-        );
-
-        let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates);
-        let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
-            self.infcx.probe(|_| {
-                self.match_projection(
-                    obligation,
-                    bound.clone(),
-                    placeholder_trait_predicate.trait_ref.clone(),
-                    &placeholder_map,
-                    snapshot,
-                )
-            })
-        });
-
-        debug!(
-            "match_projection_obligation_against_definition_bounds: \
-             matching_bound={:?}",
-            matching_bound
-        );
-        match matching_bound {
-            None => false,
-            Some(bound) => {
-                // Repeat the successful match, if any, this time outside of a probe.
-                let result = self.match_projection(
-                    obligation,
-                    bound,
-                    placeholder_trait_predicate.trait_ref.clone(),
-                    &placeholder_map,
-                    snapshot,
-                );
-
-                assert!(result);
-                true
-            }
-        }
-    }
-
-    fn match_projection(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_bound: ty::PolyTraitRef<'tcx>,
-        placeholder_trait_ref: ty::TraitRef<'tcx>,
-        placeholder_map: &PlaceholderMap<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> bool {
-        debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
-        self.infcx
-            .at(&obligation.cause, obligation.param_env)
-            .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
-            .is_ok()
-            && self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
-    }
-
-    /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
-    /// supplied to find out whether it is listed among them.
-    ///
-    /// Never affects the inference environment.
-    fn assemble_candidates_from_caller_bounds<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        debug!("assemble_candidates_from_caller_bounds({:?})", stack.obligation);
-
-        let all_bounds = stack
-            .obligation
-            .param_env
-            .caller_bounds
-            .iter()
-            .filter_map(|o| o.to_opt_poly_trait_ref());
-
-        // Micro-optimization: filter out predicates relating to different traits.
-        let matching_bounds =
-            all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
-
-        // Keep only those bounds which may apply, and propagate overflow if it occurs.
-        let mut param_candidates = vec![];
-        for bound in matching_bounds {
-            let wc = self.evaluate_where_clause(stack, bound.clone())?;
-            if wc.may_apply() {
-                param_candidates.push(ParamCandidate(bound));
-            }
-        }
-
-        candidates.vec.extend(param_candidates);
-
-        Ok(())
-    }
-
-    fn evaluate_where_clause<'o>(
-        &mut self,
-        stack: &TraitObligationStack<'o, 'tcx>,
-        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError> {
-        self.evaluation_probe(|this| {
-            match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
-                Ok(obligations) => {
-                    this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
-                }
-                Err(()) => Ok(EvaluatedToErr),
-            }
-        })
-    }
-
-    fn assemble_generator_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
-            return Ok(());
-        }
-
-        // Okay to skip binder because the substs on generator types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = *obligation.self_ty().skip_binder();
-        match self_ty.kind {
-            ty::Generator(..) => {
-                debug!(
-                    "assemble_generator_candidates: self_ty={:?} obligation={:?}",
-                    self_ty, obligation
-                );
-
-                candidates.vec.push(GeneratorCandidate);
-            }
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_generator_candidates: ambiguous self-type");
-                candidates.ambiguous = true;
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Checks for the artificial impl that the compiler will create for an obligation like `X :
-    /// FnMut<..>` where `X` is a closure type.
-    ///
-    /// Note: the type parameters on a closure candidate are modeled as *output* type
-    /// parameters and hence do not affect whether this trait is a match or not. They will be
-    /// unified during the confirmation step.
-    fn assemble_closure_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        let kind = match self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()) {
-            Some(k) => k,
-            None => {
-                return Ok(());
-            }
-        };
-
-        // Okay to skip binder because the substs on closure types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters
-        match obligation.self_ty().skip_binder().kind {
-            ty::Closure(closure_def_id, closure_substs) => {
-                debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation);
-                match self.infcx.closure_kind(closure_def_id, closure_substs) {
-                    Some(closure_kind) => {
-                        debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
-                        if closure_kind.extends(kind) {
-                            candidates.vec.push(ClosureCandidate);
-                        }
-                    }
-                    None => {
-                        debug!("assemble_unboxed_candidates: closure_kind not yet known");
-                        candidates.vec.push(ClosureCandidate);
-                    }
-                }
-            }
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
-                candidates.ambiguous = true;
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Implements one of the `Fn()` family for a fn pointer.
-    fn assemble_fn_pointer_candidates(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // We provide impl of all fn traits for fn pointers.
-        if self.tcx().fn_trait_kind_from_lang_item(obligation.predicate.def_id()).is_none() {
-            return Ok(());
-        }
-
-        // Okay to skip binder because what we are inspecting doesn't involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        match self_ty.kind {
-            ty::Infer(ty::TyVar(_)) => {
-                debug!("assemble_fn_pointer_candidates: ambiguous self-type");
-                candidates.ambiguous = true; // Could wind up being a fn() type.
-            }
-            // Provide an impl, but only for suitable `fn` pointers.
-            ty::FnDef(..) | ty::FnPtr(_) => {
-                if let ty::FnSig {
-                    unsafety: hir::Unsafety::Normal,
-                    abi: Abi::Rust,
-                    c_variadic: false,
-                    ..
-                } = self_ty.fn_sig(self.tcx()).skip_binder()
-                {
-                    candidates.vec.push(FnPointerCandidate);
-                }
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    /// Searches for impls that might apply to `obligation`.
-    fn assemble_candidates_from_impls(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
-
-        self.tcx().for_each_relevant_impl(
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().trait_ref.self_ty(),
-            |impl_def_id| {
-                self.infcx.probe(|snapshot| {
-                    if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) {
-                        candidates.vec.push(ImplCandidate(impl_def_id));
-                    }
-                });
-            },
-        );
-
-        Ok(())
-    }
-
-    fn assemble_candidates_from_auto_impls(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
-
-        let def_id = obligation.predicate.def_id();
-
-        if self.tcx().trait_is_auto(def_id) {
-            match self_ty.kind {
-                ty::Dynamic(..) => {
-                    // For object types, we don't know what the closed
-                    // over types are. This means we conservatively
-                    // say nothing; a candidate may be added by
-                    // `assemble_candidates_from_object_ty`.
-                }
-                ty::Foreign(..) => {
-                    // Since the contents of foreign types is unknown,
-                    // we don't add any `..` impl. Default traits could
-                    // still be provided by a manual implementation for
-                    // this trait and type.
-                }
-                ty::Param(..) | ty::Projection(..) => {
-                    // In these cases, we don't know what the actual
-                    // type is.  Therefore, we cannot break it down
-                    // into its constituent types. So we don't
-                    // consider the `..` impl but instead just add no
-                    // candidates: this means that typeck will only
-                    // succeed if there is another reason to believe
-                    // that this obligation holds. That could be a
-                    // where-clause or, in the case of an object type,
-                    // it could be that the object type lists the
-                    // trait (e.g., `Foo+Send : Send`). See
-                    // `compile-fail/typeck-default-trait-impl-send-param.rs`
-                    // for an example of a test case that exercises
-                    // this path.
-                }
-                ty::Infer(ty::TyVar(_)) => {
-                    // The auto impl might apply; we don't know.
-                    candidates.ambiguous = true;
-                }
-                ty::Generator(_, _, movability)
-                    if self.tcx().lang_items().unpin_trait() == Some(def_id) =>
-                {
-                    match movability {
-                        hir::Movability::Static => {
-                            // Immovable generators are never `Unpin`, so
-                            // suppress the normal auto-impl candidate for it.
-                        }
-                        hir::Movability::Movable => {
-                            // Movable generators are always `Unpin`, so add an
-                            // unconditional builtin candidate.
-                            candidates.vec.push(BuiltinCandidate { has_nested: false });
-                        }
-                    }
-                }
-
-                _ => candidates.vec.push(AutoImplCandidate(def_id)),
-            }
-        }
-
-        Ok(())
-    }
-
-    /// Searches for impls that might apply to `obligation`.
-    fn assemble_candidates_from_object_ty(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        debug!(
-            "assemble_candidates_from_object_ty(self_ty={:?})",
-            obligation.self_ty().skip_binder()
-        );
-
-        self.infcx.probe(|_snapshot| {
-            // The code below doesn't care about regions, and the
-            // self-ty here doesn't escape this probe, so just erase
-            // any LBR.
-            let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty());
-            let poly_trait_ref = match self_ty.kind {
-                ty::Dynamic(ref data, ..) => {
-                    if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
-                        debug!(
-                            "assemble_candidates_from_object_ty: matched builtin bound, \
-                             pushing candidate"
-                        );
-                        candidates.vec.push(BuiltinObjectCandidate);
-                        return;
-                    }
-
-                    if let Some(principal) = data.principal() {
-                        if !self.infcx.tcx.features().object_safe_for_dispatch {
-                            principal.with_self_ty(self.tcx(), self_ty)
-                        } else if self.tcx().is_object_safe(principal.def_id()) {
-                            principal.with_self_ty(self.tcx(), self_ty)
-                        } else {
-                            return;
-                        }
-                    } else {
-                        // Only auto trait bounds exist.
-                        return;
-                    }
-                }
-                ty::Infer(ty::TyVar(_)) => {
-                    debug!("assemble_candidates_from_object_ty: ambiguous");
-                    candidates.ambiguous = true; // could wind up being an object type
-                    return;
-                }
-                _ => return,
-            };
-
-            debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", poly_trait_ref);
-
-            // Count only those upcast versions that match the trait-ref
-            // we are looking for. Specifically, do not only check for the
-            // correct trait, but also the correct type parameters.
-            // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
-            // but `Foo` is declared as `trait Foo: Bar<u32>`.
-            let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref)
-                .filter(|upcast_trait_ref| {
-                    self.infcx
-                        .probe(|_| self.match_poly_trait_ref(obligation, *upcast_trait_ref).is_ok())
-                })
-                .count();
-
-            if upcast_trait_refs > 1 {
-                // Can be upcast in many ways; need more type information.
-                candidates.ambiguous = true;
-            } else if upcast_trait_refs == 1 {
-                candidates.vec.push(ObjectCandidate);
-            }
-        })
-    }
-
-    /// Searches for unsizing that might apply to `obligation`.
-    fn assemble_candidates_for_unsizing(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) {
-        // We currently never consider higher-ranked obligations e.g.
-        // `for<'a> &'a T: Unsize<Trait+'a>` to be implemented. This is not
-        // because they are a priori invalid, and we could potentially add support
-        // for them later, it's just that there isn't really a strong need for it.
-        // A `T: Unsize<U>` obligation is always used as part of a `T: CoerceUnsize<U>`
-        // impl, and those are generally applied to concrete types.
-        //
-        // That said, one might try to write a fn with a where clause like
-        //     for<'a> Foo<'a, T>: Unsize<Foo<'a, Trait>>
-        // where the `'a` is kind of orthogonal to the relevant part of the `Unsize`.
-        // Still, you'd be more likely to write that where clause as
-        //     T: Trait
-        // so it seems ok if we (conservatively) fail to accept that `Unsize`
-        // obligation above. Should be possible to extend this in the future.
-        let source = match obligation.self_ty().no_bound_vars() {
-            Some(t) => t,
-            None => {
-                // Don't add any candidates if there are bound regions.
-                return;
-            }
-        };
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
-
-        debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target);
-
-        let may_apply = match (&source.kind, &target.kind) {
-            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
-                // Upcasts permit two things:
-                //
-                // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
-                // 2. Tightening the region bound, e.g., `Foo + 'a` to `Foo + 'b` if `'a: 'b`
-                //
-                // Note that neither of these changes requires any
-                // change at runtime. Eventually this will be
-                // generalized.
-                //
-                // We always upcast when we can because of reason
-                // #2 (region bounds).
-                data_a.principal_def_id() == data_b.principal_def_id()
-                    && data_b
-                        .auto_traits()
-                        // All of a's auto traits need to be in b's auto traits.
-                        .all(|b| data_a.auto_traits().any(|a| a == b))
-            }
-
-            // `T` -> `Trait`
-            (_, &ty::Dynamic(..)) => true,
-
-            // Ambiguous handling is below `T` -> `Trait`, because inference
-            // variables can still implement `Unsize<Trait>` and nested
-            // obligations will have the final say (likely deferred).
-            (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
-                debug!("assemble_candidates_for_unsizing: ambiguous");
-                candidates.ambiguous = true;
-                false
-            }
-
-            // `[T; n]` -> `[T]`
-            (&ty::Array(..), &ty::Slice(_)) => true,
-
-            // `Struct<T>` -> `Struct<U>`
-            (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
-                def_id_a == def_id_b
-            }
-
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(),
-
-            _ => false,
-        };
-
-        if may_apply {
-            candidates.vec.push(BuiltinUnsizeCandidate);
-        }
-    }
-
-    fn assemble_candidates_for_trait_alias(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        // Okay to skip binder here because the tests we do below do not involve bound regions.
-        let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
-
-        let def_id = obligation.predicate.def_id();
-
-        if self.tcx().is_trait_alias(def_id) {
-            candidates.vec.push(TraitAliasCandidate(def_id));
-        }
-
-        Ok(())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // WINNOW
-    //
-    // Winnowing is the process of attempting to resolve ambiguity by
-    // probing further. During the winnowing process, we unify all
-    // type variables and then we also attempt to evaluate recursive
-    // bounds to see if they are satisfied.
-
-    /// Returns `true` if `victim` should be dropped in favor of
-    /// `other`. Generally speaking we will drop duplicate
-    /// candidates and prefer where-clause candidates.
-    ///
-    /// See the comment for "SelectionCandidate" for more details.
-    fn candidate_should_be_dropped_in_favor_of(
-        &mut self,
-        victim: &EvaluatedCandidate<'tcx>,
-        other: &EvaluatedCandidate<'tcx>,
-        needs_infer: bool,
-    ) -> bool {
-        if victim.candidate == other.candidate {
-            return true;
-        }
-
-        // Check if a bound would previously have been removed when normalizing
-        // the param_env so that it can be given the lowest priority. See
-        // #50825 for the motivation for this.
-        let is_global =
-            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
-
-        match other.candidate {
-            // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-            // This is a fix for #53123 and prevents winnowing from accidentally extending the
-            // lifetime of a variable.
-            BuiltinCandidate { has_nested: false } => true,
-            ParamCandidate(ref cand) => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-                // This is a fix for #53123 and prevents winnowing from accidentally extending the
-                // lifetime of a variable.
-                BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..)
-                | ClosureCandidate
-                | GeneratorCandidate
-                | FnPointerCandidate
-                | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..) => {
-                    // Global bounds from the where clause should be ignored
-                    // here (see issue #50825). Otherwise, we have a where
-                    // clause so don't go around looking for impls.
-                    !is_global(cand)
-                }
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    !is_global(cand)
-                }
-                ParamCandidate(..) => false,
-            },
-            ObjectCandidate | ProjectionCandidate => match victim.candidate {
-                AutoImplCandidate(..) => {
-                    bug!(
-                        "default implementations shouldn't be recorded \
-                         when there are other valid candidates"
-                    );
-                }
-                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
-                // This is a fix for #53123 and prevents winnowing from accidentally extending the
-                // lifetime of a variable.
-                BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..)
-                | ClosureCandidate
-                | GeneratorCandidate
-                | FnPointerCandidate
-                | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
-                | BuiltinCandidate { .. }
-                | TraitAliasCandidate(..) => true,
-                ObjectCandidate | ProjectionCandidate => {
-                    // Arbitrarily give param candidates priority
-                    // over projection and object candidates.
-                    true
-                }
-                ParamCandidate(ref cand) => is_global(cand),
-            },
-            ImplCandidate(other_def) => {
-                // See if we can toss out `victim` based on specialization.
-                // This requires us to know *for sure* that the `other` impl applies
-                // i.e., `EvaluatedToOk`.
-                if other.evaluation.must_apply_modulo_regions() {
-                    match victim.candidate {
-                        ImplCandidate(victim_def) => {
-                            let tcx = self.tcx();
-                            if tcx.specializes((other_def, victim_def)) {
-                                return true;
-                            }
-                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
-                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
-                                    // Subtle: If the predicate we are evaluating has inference
-                                    // variables, do *not* allow discarding candidates due to
-                                    // marker trait impls.
-                                    //
-                                    // Without this restriction, we could end up accidentally
-                                    // constrainting inference variables based on an arbitrarily
-                                    // chosen trait impl.
-                                    //
-                                    // Imagine we have the following code:
-                                    //
-                                    // ```rust
-                                    // #[marker] trait MyTrait {}
-                                    // impl MyTrait for u8 {}
-                                    // impl MyTrait for bool {}
-                                    // ```
-                                    //
-                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
-                                    //
-                                    // During selection, we will end up with one candidate for each
-                                    // impl of `MyTrait`. If we were to discard one impl in favor
-                                    // of the other, we would be left with one candidate, causing
-                                    // us to "successfully" select the predicate, unifying
-                                    // _#0t with (for example) `u8`.
-                                    //
-                                    // However, we have no reason to believe that this unification
-                                    // is correct - we've essentially just picked an arbitrary
-                                    // *possibility* for _#0t, and required that this be the *only*
-                                    // possibility.
-                                    //
-                                    // Eventually, we will either:
-                                    // 1) Unify all inference variables in the predicate through
-                                    // some other means (e.g. type-checking of a function). We will
-                                    // then be in a position to drop marker trait candidates
-                                    // without constraining inference variables (since there are
-                                    // none left to constrin)
-                                    // 2) Be left with some unconstrained inference variables. We
-                                    // will then correctly report an inference error, since the
-                                    // existence of multiple marker trait impls tells us nothing
-                                    // about which one should actually apply.
-                                    !needs_infer
-                                }
-                                Some(_) => true,
-                                None => false,
-                            };
-                        }
-                        ParamCandidate(ref cand) => {
-                            // Prefer the impl to a global where clause candidate.
-                            return is_global(cand);
-                        }
-                        _ => (),
-                    }
-                }
-
-                false
-            }
-            ClosureCandidate
-            | GeneratorCandidate
-            | FnPointerCandidate
-            | BuiltinObjectCandidate
-            | BuiltinUnsizeCandidate
-            | BuiltinCandidate { has_nested: true } => {
-                match victim.candidate {
-                    ParamCandidate(ref cand) => {
-                        // Prefer these to a global where-clause bound
-                        // (see issue #50825).
-                        is_global(cand) && other.evaluation.must_apply_modulo_regions()
-                    }
-                    _ => false,
-                }
-            }
-            _ => false,
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // BUILTIN BOUNDS
-    //
-    // These cover the traits that are built-in to the language
-    // itself: `Copy`, `Clone` and `Sized`.
-
-    fn assemble_builtin_bound_candidates(
-        &mut self,
-        conditions: BuiltinImplConditions<'tcx>,
-        candidates: &mut SelectionCandidateSet<'tcx>,
-    ) -> Result<(), SelectionError<'tcx>> {
-        match conditions {
-            BuiltinImplConditions::Where(nested) => {
-                debug!("builtin_bound: nested={:?}", nested);
-                candidates
-                    .vec
-                    .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() });
-            }
-            BuiltinImplConditions::None => {}
-            BuiltinImplConditions::Ambiguous => {
-                debug!("assemble_builtin_bound_candidates: ambiguous builtin");
-                candidates.ambiguous = true;
-            }
-        }
-
-        Ok(())
-    }
-
-    fn sized_conditions(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> BuiltinImplConditions<'tcx> {
-        use self::BuiltinImplConditions::{Ambiguous, None, Where};
-
-        // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
-
-        match self_ty.kind {
-            ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::RawPtr(..)
-            | ty::Char
-            | ty::Ref(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
-            | ty::Array(..)
-            | ty::Closure(..)
-            | ty::Never
-            | ty::Error => {
-                // safe for everything
-                Where(ty::Binder::dummy(Vec::new()))
-            }
-
-            ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
-
-            ty::Tuple(tys) => {
-                Where(ty::Binder::bind(tys.last().into_iter().map(|k| k.expect_ty()).collect()))
-            }
-
-            ty::Adt(def, substs) => {
-                let sized_crit = def.sized_constraint(self.tcx());
-                // (*) binder moved here
-                Where(ty::Binder::bind(
-                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect(),
-                ))
-            }
-
-            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
-            ty::Infer(ty::TyVar(_)) => Ambiguous,
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
-            }
-        }
-    }
-
-    fn copy_clone_conditions(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> BuiltinImplConditions<'tcx> {
-        // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
-
-        use self::BuiltinImplConditions::{Ambiguous, None, Where};
-
-        match self_ty.kind {
-            ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Error => Where(ty::Binder::dummy(Vec::new())),
-
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::Char
-            | ty::RawPtr(..)
-            | ty::Never
-            | ty::Ref(_, _, hir::Mutability::Not) => {
-                // Implementations provided in libcore
-                None
-            }
-
-            ty::Dynamic(..)
-            | ty::Str
-            | ty::Slice(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
-            | ty::Foreign(..)
-            | ty::Ref(_, _, hir::Mutability::Mut) => None,
-
-            ty::Array(element_ty, _) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(vec![element_ty]))
-            }
-
-            ty::Tuple(tys) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
-            }
-
-            ty::Closure(def_id, substs) => {
-                // (*) binder moved here
-                Where(ty::Binder::bind(substs.as_closure().upvar_tys(def_id, self.tcx()).collect()))
-            }
-
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
-                // Fallback to whatever user-defined impls exist in this case.
-                None
-            }
-
-            ty::Infer(ty::TyVar(_)) => {
-                // Unbound type variable. Might or might not have
-                // applicable impls and so forth, depending on what
-                // those type variables wind up being bound to.
-                Ambiguous
-            }
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
-            }
-        }
-    }
-
-    /// For default impls, we need to break apart a type into its
-    /// "constituent types" -- meaning, the types that it contains.
-    ///
-    /// Here are some (simple) examples:
-    ///
-    /// ```
-    /// (i32, u32) -> [i32, u32]
-    /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
-    /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
-    /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
-    /// ```
-    fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
-        match t.kind {
-            ty::Uint(_)
-            | ty::Int(_)
-            | ty::Bool
-            | ty::Float(_)
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Str
-            | ty::Error
-            | ty::Infer(ty::IntVar(_))
-            | ty::Infer(ty::FloatVar(_))
-            | ty::Never
-            | ty::Char => Vec::new(),
-
-            ty::UnnormalizedProjection(..)
-            | ty::Placeholder(..)
-            | ty::Dynamic(..)
-            | ty::Param(..)
-            | ty::Foreign(..)
-            | ty::Projection(..)
-            | ty::Bound(..)
-            | ty::Infer(ty::TyVar(_))
-            | ty::Infer(ty::FreshTy(_))
-            | ty::Infer(ty::FreshIntTy(_))
-            | ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble constituent types of unexpected type: {:?}", t);
-            }
-
-            ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
-                vec![element_ty]
-            }
-
-            ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty],
-
-            ty::Tuple(ref tys) => {
-                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-                tys.iter().map(|k| k.expect_ty()).collect()
-            }
-
-            ty::Closure(def_id, ref substs) => {
-                substs.as_closure().upvar_tys(def_id, self.tcx()).collect()
-            }
-
-            ty::Generator(def_id, ref substs, _) => {
-                let witness = substs.as_generator().witness(def_id, self.tcx());
-                substs
-                    .as_generator()
-                    .upvar_tys(def_id, self.tcx())
-                    .chain(iter::once(witness))
-                    .collect()
-            }
-
-            ty::GeneratorWitness(types) => {
-                // This is sound because no regions in the witness can refer to
-                // the binder outside the witness. So we'll effectivly reuse
-                // the implicit binder around the witness.
-                types.skip_binder().to_vec()
-            }
-
-            // For `PhantomData<T>`, we pass `T`.
-            ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
-
-            ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
-
-            ty::Opaque(def_id, substs) => {
-                // We can resolve the `impl Trait` to its concrete type,
-                // which enforces a DAG between the functions requiring
-                // the auto trait bounds in question.
-                vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)]
-            }
-        }
-    }
-
-    fn collect_predicates_for_types(
-        &mut self,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        trait_def_id: DefId,
-        types: ty::Binder<Vec<Ty<'tcx>>>,
-    ) -> Vec<PredicateObligation<'tcx>> {
-        // Because the types were potentially derived from
-        // higher-ranked obligations they may reference late-bound
-        // regions. For example, `for<'a> Foo<&'a int> : Copy` would
-        // yield a type like `for<'a> &'a int`. In general, we
-        // maintain the invariant that we never manipulate bound
-        // regions, so we have to process these bound regions somehow.
-        //
-        // The strategy is to:
-        //
-        // 1. Instantiate those regions to placeholder regions (e.g.,
-        //    `for<'a> &'a int` becomes `&0 int`.
-        // 2. Produce something like `&'0 int : Copy`
-        // 3. Re-bind the regions back to `for<'a> &'a int : Copy`
-
-        types
-            .skip_binder()
-            .iter()
-            .flat_map(|ty| {
-                // binder moved -\
-                let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
-
-                self.infcx.commit_unconditionally(|_| {
-                    let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty);
-                    let Normalized { value: normalized_ty, mut obligations } =
-                        project::normalize_with_depth(
-                            self,
-                            param_env,
-                            cause.clone(),
-                            recursion_depth,
-                            &skol_ty,
-                        );
-                    let skol_obligation = predicate_for_trait_def(
-                        self.tcx(),
-                        param_env,
-                        cause.clone(),
-                        trait_def_id,
-                        recursion_depth,
-                        normalized_ty,
-                        &[],
-                    );
-                    obligations.push(skol_obligation);
-                    obligations
-                })
-            })
-            .collect()
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // CONFIRMATION
-    //
-    // Confirmation unifies the output type parameters of the trait
-    // with the values found in the obligation, possibly yielding a
-    // type error.  See the [rustc guide] for more details.
-    //
-    // [rustc guide]:
-    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation
-
-    fn confirm_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        candidate: SelectionCandidate<'tcx>,
-    ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
-        debug!("confirm_candidate({:?}, {:?})", obligation, candidate);
-
-        match candidate {
-            BuiltinCandidate { has_nested } => {
-                let data = self.confirm_builtin_candidate(obligation, has_nested);
-                Ok(VtableBuiltin(data))
-            }
-
-            ParamCandidate(param) => {
-                let obligations = self.confirm_param_candidate(obligation, param);
-                Ok(VtableParam(obligations))
-            }
-
-            ImplCandidate(impl_def_id) => {
-                Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
-            }
-
-            AutoImplCandidate(trait_def_id) => {
-                let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
-                Ok(VtableAutoImpl(data))
-            }
-
-            ProjectionCandidate => {
-                self.confirm_projection_candidate(obligation);
-                Ok(VtableParam(Vec::new()))
-            }
-
-            ClosureCandidate => {
-                let vtable_closure = self.confirm_closure_candidate(obligation)?;
-                Ok(VtableClosure(vtable_closure))
-            }
-
-            GeneratorCandidate => {
-                let vtable_generator = self.confirm_generator_candidate(obligation)?;
-                Ok(VtableGenerator(vtable_generator))
-            }
-
-            FnPointerCandidate => {
-                let data = self.confirm_fn_pointer_candidate(obligation)?;
-                Ok(VtableFnPointer(data))
-            }
-
-            TraitAliasCandidate(alias_def_id) => {
-                let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
-                Ok(VtableTraitAlias(data))
-            }
-
-            ObjectCandidate => {
-                let data = self.confirm_object_candidate(obligation);
-                Ok(VtableObject(data))
-            }
-
-            BuiltinObjectCandidate => {
-                // This indicates something like `Trait + Send: Send`. In this case, we know that
-                // this holds because that's what the object type is telling us, and there's really
-                // no additional obligations to prove and no types in particular to unify, etc.
-                Ok(VtableParam(Vec::new()))
-            }
-
-            BuiltinUnsizeCandidate => {
-                let data = self.confirm_builtin_unsize_candidate(obligation)?;
-                Ok(VtableBuiltin(data))
-            }
-        }
-    }
-
-    fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
-        self.infcx.commit_unconditionally(|snapshot| {
-            let result =
-                self.match_projection_obligation_against_definition_bounds(obligation, snapshot);
-            assert!(result);
-        })
-    }
-
-    fn confirm_param_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        param: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<PredicateObligation<'tcx>> {
-        debug!("confirm_param_candidate({:?},{:?})", obligation, param);
-
-        // During evaluation, we already checked that this
-        // where-clause trait-ref could be unified with the obligation
-        // trait-ref. Repeat that unification now without any
-        // transactional boundary; it should not fail.
-        match self.match_where_clause_trait_ref(obligation, param.clone()) {
-            Ok(obligations) => obligations,
-            Err(()) => {
-                bug!(
-                    "Where clause `{:?}` was applicable to `{:?}` but now is not",
-                    param,
-                    obligation
-                );
-            }
-        }
-    }
-
-    fn confirm_builtin_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        has_nested: bool,
-    ) -> VtableBuiltinData<PredicateObligation<'tcx>> {
-        debug!("confirm_builtin_candidate({:?}, {:?})", obligation, has_nested);
-
-        let lang_items = self.tcx().lang_items();
-        let obligations = if has_nested {
-            let trait_def = obligation.predicate.def_id();
-            let conditions = if Some(trait_def) == lang_items.sized_trait() {
-                self.sized_conditions(obligation)
-            } else if Some(trait_def) == lang_items.copy_trait() {
-                self.copy_clone_conditions(obligation)
-            } else if Some(trait_def) == lang_items.clone_trait() {
-                self.copy_clone_conditions(obligation)
-            } else {
-                bug!("unexpected builtin trait {:?}", trait_def)
-            };
-            let nested = match conditions {
-                BuiltinImplConditions::Where(nested) => nested,
-                _ => bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation),
-            };
-
-            let cause = obligation.derived_cause(BuiltinDerivedObligation);
-            self.collect_predicates_for_types(
-                obligation.param_env,
-                cause,
-                obligation.recursion_depth + 1,
-                trait_def,
-                nested,
-            )
-        } else {
-            vec![]
-        };
-
-        debug!("confirm_builtin_candidate: obligations={:?}", obligations);
-
-        VtableBuiltinData { nested: obligations }
-    }
-
-    /// This handles the case where a `auto trait Foo` impl is being used.
-    /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
-    ///
-    /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
-    /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
-    fn confirm_auto_impl_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_def_id: DefId,
-    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
-        debug!("confirm_auto_impl_candidate({:?}, {:?})", obligation, trait_def_id);
-
-        let types = obligation.predicate.map_bound(|inner| {
-            let self_ty = self.infcx.shallow_resolve(inner.self_ty());
-            self.constituent_types_for_ty(self_ty)
-        });
-        self.vtable_auto_impl(obligation, trait_def_id, types)
-    }
-
-    /// See `confirm_auto_impl_candidate`.
-    fn vtable_auto_impl(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        trait_def_id: DefId,
-        nested: ty::Binder<Vec<Ty<'tcx>>>,
-    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
-        debug!("vtable_auto_impl: nested={:?}", nested);
-
-        let cause = obligation.derived_cause(BuiltinDerivedObligation);
-        let mut obligations = self.collect_predicates_for_types(
-            obligation.param_env,
-            cause,
-            obligation.recursion_depth + 1,
-            trait_def_id,
-            nested,
-        );
-
-        let trait_obligations: Vec<PredicateObligation<'_>> =
-            self.infcx.commit_unconditionally(|_| {
-                let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
-                let (trait_ref, _) =
-                    self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref);
-                let cause = obligation.derived_cause(ImplDerivedObligation);
-                self.impl_or_trait_obligations(
-                    cause,
-                    obligation.recursion_depth + 1,
-                    obligation.param_env,
-                    trait_def_id,
-                    &trait_ref.substs,
-                )
-            });
-
-        // Adds the predicates from the trait.  Note that this contains a `Self: Trait`
-        // predicate as usual.  It won't have any effect since auto traits are coinductive.
-        obligations.extend(trait_obligations);
-
-        debug!("vtable_auto_impl: obligations={:?}", obligations);
-
-        VtableAutoImplData { trait_def_id, nested: obligations }
-    }
-
-    fn confirm_impl_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        impl_def_id: DefId,
-    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id);
-
-        // First, create the substitutions by matching the impl again,
-        // this time not in a probe.
-        self.infcx.commit_unconditionally(|snapshot| {
-            let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
-            debug!("confirm_impl_candidate: substs={:?}", substs);
-            let cause = obligation.derived_cause(ImplDerivedObligation);
-            self.vtable_impl(
-                impl_def_id,
-                substs,
-                cause,
-                obligation.recursion_depth + 1,
-                obligation.param_env,
-            )
-        })
-    }
-
-    fn vtable_impl(
-        &mut self,
-        impl_def_id: DefId,
-        mut substs: Normalized<'tcx, SubstsRef<'tcx>>,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
-        debug!(
-            "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})",
-            impl_def_id, substs, recursion_depth,
-        );
-
-        let mut impl_obligations = self.impl_or_trait_obligations(
-            cause,
-            recursion_depth,
-            param_env,
-            impl_def_id,
-            &substs.value,
-        );
-
-        debug!(
-            "vtable_impl: impl_def_id={:?} impl_obligations={:?}",
-            impl_def_id, impl_obligations
-        );
-
-        // Because of RFC447, the impl-trait-ref and obligations
-        // are sufficient to determine the impl substs, without
-        // relying on projections in the impl-trait-ref.
-        //
-        // e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
-        impl_obligations.append(&mut substs.obligations);
-
-        VtableImplData { impl_def_id, substs: substs.value, nested: impl_obligations }
-    }
-
-    fn confirm_object_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_object_candidate({:?})", obligation);
-
-        // FIXME(nmatsakis) skipping binder here seems wrong -- we should
-        // probably flatten the binder from the obligation and the binder
-        // from the object. Have to try to make a broken test case that
-        // results.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let poly_trait_ref = match self_ty.kind {
-            ty::Dynamic(ref data, ..) => data
-                .principal()
-                .unwrap_or_else(|| {
-                    span_bug!(obligation.cause.span, "object candidate with no principal")
-                })
-                .with_self_ty(self.tcx(), self_ty),
-            _ => span_bug!(obligation.cause.span, "object candidate with non-object"),
-        };
-
-        let mut upcast_trait_ref = None;
-        let mut nested = vec![];
-        let vtable_base;
-
-        {
-            let tcx = self.tcx();
-
-            // We want to find the first supertrait in the list of
-            // supertraits that we can unify with, and do that
-            // unification. We know that there is exactly one in the list
-            // where we can unify, because otherwise select would have
-            // reported an ambiguity. (When we do find a match, also
-            // record it for later.)
-            let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| {
-                match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) {
-                    Ok(obligations) => {
-                        upcast_trait_ref = Some(t);
-                        nested.extend(obligations);
-                        false
-                    }
-                    Err(_) => true,
-                }
-            });
-
-            // Additionally, for each of the non-matching predicates that
-            // we pass over, we sum up the set of number of vtable
-            // entries, so that we can compute the offset for the selected
-            // trait.
-            vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum();
-        }
-
-        VtableObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested }
-    }
-
-    fn confirm_fn_pointer_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        debug!("confirm_fn_pointer_candidate({:?})", obligation);
-
-        // Okay to skip binder; it is reintroduced below.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let sig = self_ty.fn_sig(self.tcx());
-        let trait_ref = closure_trait_ref_and_return_type(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            self_ty,
-            sig,
-            util::TupleArgumentsFlag::Yes,
-        )
-        .map_bound(|(trait_ref, _)| trait_ref);
-
-        let Normalized { value: trait_ref, obligations } = project::normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?;
-        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
-    }
-
-    fn confirm_trait_alias_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        alias_def_id: DefId,
-    ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
-        debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id);
-
-        self.infcx.commit_unconditionally(|_| {
-            let (predicate, _) =
-                self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
-            let trait_ref = predicate.trait_ref;
-            let trait_def_id = trait_ref.def_id;
-            let substs = trait_ref.substs;
-
-            let trait_obligations = self.impl_or_trait_obligations(
-                obligation.cause.clone(),
-                obligation.recursion_depth,
-                obligation.param_env,
-                trait_def_id,
-                &substs,
-            );
-
-            debug!(
-                "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
-                trait_def_id, trait_obligations
-            );
-
-            VtableTraitAliasData { alias_def_id, substs: substs, nested: trait_obligations }
-        })
-    }
-
-    fn confirm_generator_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        // Okay to skip binder because the substs on generator types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let (generator_def_id, substs) = match self_ty.kind {
-            ty::Generator(id, substs, _) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation),
-        };
-
-        debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs);
-
-        let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
-        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        debug!(
-            "confirm_generator_candidate(generator_def_id={:?}, \
-             trait_ref={:?}, obligations={:?})",
-            generator_def_id, trait_ref, obligations
-        );
-
-        obligations.extend(self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?);
-
-        Ok(VtableGeneratorData { generator_def_id, substs, nested: obligations })
-    }
-
-    fn confirm_closure_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        debug!("confirm_closure_candidate({:?})", obligation);
-
-        let kind = self
-            .tcx()
-            .fn_trait_kind_from_lang_item(obligation.predicate.def_id())
-            .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
-
-        // Okay to skip binder because the substs on closure types never
-        // touch bound regions, they just capture the in-scope
-        // type/region parameters.
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let (closure_def_id, substs) = match self_ty.kind {
-            ty::Closure(id, substs) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation),
-        };
-
-        let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
-        let Normalized { value: trait_ref, mut obligations } = normalize_with_depth(
-            self,
-            obligation.param_env,
-            obligation.cause.clone(),
-            obligation.recursion_depth + 1,
-            &trait_ref,
-        );
-
-        debug!(
-            "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
-            closure_def_id, trait_ref, obligations
-        );
-
-        obligations.extend(self.confirm_poly_trait_refs(
-            obligation.cause.clone(),
-            obligation.param_env,
-            obligation.predicate.to_poly_trait_ref(),
-            trait_ref,
-        )?);
-
-        obligations.push(Obligation::new(
-            obligation.cause.clone(),
-            obligation.param_env,
-            ty::Predicate::ClosureKind(closure_def_id, substs, kind),
-        ));
-
-        Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations })
-    }
-
-    /// In the case of closure types and fn pointers,
-    /// we currently treat the input type parameters on the trait as
-    /// outputs. This means that when we have a match we have only
-    /// considered the self type, so we have to go back and make sure
-    /// to relate the argument types too. This is kind of wrong, but
-    /// since we control the full set of impls, also not that wrong,
-    /// and it DOES yield better error messages (since we don't report
-    /// errors as if there is no applicable impl, but rather report
-    /// errors are about mismatched argument types.
-    ///
-    /// Here is an example. Imagine we have a closure expression
-    /// and we desugared it so that the type of the expression is
-    /// `Closure`, and `Closure` expects an int as argument. Then it
-    /// is "as if" the compiler generated this impl:
-    ///
-    ///     impl Fn(int) for Closure { ... }
-    ///
-    /// Now imagine our obligation is `Fn(usize) for Closure`. So far
-    /// we have matched the self type `Closure`. At this point we'll
-    /// compare the `int` to `usize` and generate an error.
-    ///
-    /// Note that this checking occurs *after* the impl has selected,
-    /// because these output type parameters should not affect the
-    /// selection of the impl. Therefore, if there is a mismatch, we
-    /// report an error to the user.
-    fn confirm_poly_trait_refs(
-        &mut self,
-        obligation_cause: ObligationCause<'tcx>,
-        obligation_param_env: ty::ParamEnv<'tcx>,
-        obligation_trait_ref: ty::PolyTraitRef<'tcx>,
-        expected_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        self.infcx
-            .at(&obligation_cause, obligation_param_env)
-            .sup(obligation_trait_ref, expected_trait_ref)
-            .map(|InferOk { obligations, .. }| obligations)
-            .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
-    }
-
-    fn confirm_builtin_unsize_candidate(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-    ) -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-        let tcx = self.tcx();
-
-        // `assemble_candidates_for_unsizing` should ensure there are no late-bound
-        // regions here. See the comment there for more details.
-        let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
-        let target = self.infcx.shallow_resolve(target);
-
-        debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target);
-
-        let mut nested = vec![];
-        match (&source.kind, &target.kind) {
-            // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
-                // See `assemble_candidates_for_unsizing` for more info.
-                let existential_predicates = data_a.map_bound(|data_a| {
-                    let iter = data_a
-                        .principal()
-                        .map(|x| ty::ExistentialPredicate::Trait(x))
-                        .into_iter()
-                        .chain(
-                            data_a
-                                .projection_bounds()
-                                .map(|x| ty::ExistentialPredicate::Projection(x)),
-                        )
-                        .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
-                    tcx.mk_existential_predicates(iter)
-                });
-                let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
-
-                // Require that the traits involved in this upcast are **equal**;
-                // only the **lifetime bound** is changed.
-                //
-                // FIXME: This condition is arguably too strong -- it would
-                // suffice for the source trait to be a *subtype* of the target
-                // trait. In particular, changing from something like
-                // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
-                // permitted. And, indeed, in the in commit
-                // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
-                // condition was loosened. However, when the leak check was
-                // added back, using subtype here actually guides the coercion
-                // code in such a way that it accepts `old-lub-glb-object.rs`.
-                // This is probably a good thing, but I've modified this to `.eq`
-                // because I want to continue rejecting that test (as we have
-                // done for quite some time) before we are firmly comfortable
-                // with what our behavior should be there. -nikomatsakis
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, source_trait) // FIXME -- see below
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Register one obligation for 'a: 'b.
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(target),
-                );
-                let outlives = ty::OutlivesPredicate(r_a, r_b);
-                nested.push(Obligation::with_depth(
-                    cause,
-                    obligation.recursion_depth + 1,
-                    obligation.param_env,
-                    ty::Binder::bind(outlives).to_predicate(),
-                ));
-            }
-
-            // `T` -> `Trait`
-            (_, &ty::Dynamic(ref data, r)) => {
-                let mut object_dids = data.auto_traits().chain(data.principal_def_id());
-                if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
-                    return Err(TraitNotObjectSafe(did));
-                }
-
-                let cause = ObligationCause::new(
-                    obligation.cause.span,
-                    obligation.cause.body_id,
-                    ObjectCastObligation(target),
-                );
-
-                let predicate_to_obligation = |predicate| {
-                    Obligation::with_depth(
-                        cause.clone(),
-                        obligation.recursion_depth + 1,
-                        obligation.param_env,
-                        predicate,
-                    )
-                };
-
-                // Create obligations:
-                //  - Casting `T` to `Trait`
-                //  - For all the various builtin bounds attached to the object cast. (In other
-                //  words, if the object type is `Foo + Send`, this would create an obligation for
-                //  the `Send` check.)
-                //  - Projection predicates
-                nested.extend(
-                    data.iter().map(|predicate| {
-                        predicate_to_obligation(predicate.with_self_ty(tcx, source))
-                    }),
-                );
-
-                // We can only make objects from sized types.
-                let tr = ty::TraitRef::new(
-                    tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
-                    tcx.mk_substs_trait(source, &[]),
-                );
-                nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
-
-                // If the type is `Foo + 'a`, ensure that the type
-                // being cast to `Foo + 'a` outlives `'a`:
-                let outlives = ty::OutlivesPredicate(source, r);
-                nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate()));
-            }
-
-            // `[T; n]` -> `[T]`
-            (&ty::Array(a, _), &ty::Slice(b)) => {
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(b, a)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-            }
-
-            // `Struct<T>` -> `Struct<U>`
-            (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
-                let fields =
-                    def.all_fields().map(|field| tcx.type_of(field.did)).collect::<Vec<_>>();
-
-                // The last field of the structure has to exist and contain type parameters.
-                let field = if let Some(&field) = fields.last() {
-                    field
-                } else {
-                    return Err(Unimplemented);
-                };
-                let mut ty_params = GrowableBitSet::new_empty();
-                let mut found = false;
-                for ty in field.walk() {
-                    if let ty::Param(p) = ty.kind {
-                        ty_params.insert(p.index as usize);
-                        found = true;
-                    }
-                }
-                if !found {
-                    return Err(Unimplemented);
-                }
-
-                // Replace type parameters used in unsizing with
-                // Error and ensure they do not affect any other fields.
-                // This could be checked after type collection for any struct
-                // with a potentially unsized trailing field.
-                let params = substs_a
-                    .iter()
-                    .enumerate()
-                    .map(|(i, &k)| if ty_params.contains(i) { tcx.types.err.into() } else { k });
-                let substs = tcx.mk_substs(params);
-                for &ty in fields.split_last().unwrap().1 {
-                    if ty.subst(tcx, substs).references_error() {
-                        return Err(Unimplemented);
-                    }
-                }
-
-                // Extract `Field<T>` and `Field<U>` from `Struct<T>` and `Struct<U>`.
-                let inner_source = field.subst(tcx, substs_a);
-                let inner_target = field.subst(tcx, substs_b);
-
-                // Check that the source struct with the target's
-                // unsized parameters is equal to the target.
-                let params = substs_a.iter().enumerate().map(|(i, &k)| {
-                    if ty_params.contains(i) { substs_b.type_at(i).into() } else { k }
-                });
-                let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, new_struct)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Construct the nested `Field<T>: Unsize<Field<U>>` predicate.
-                nested.push(predicate_for_trait_def(
-                    tcx,
-                    obligation.param_env,
-                    obligation.cause.clone(),
-                    obligation.predicate.def_id(),
-                    obligation.recursion_depth + 1,
-                    inner_source,
-                    &[inner_target.into()],
-                ));
-            }
-
-            // `(.., T)` -> `(.., U)`
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-                assert_eq!(tys_a.len(), tys_b.len());
-
-                // The last field of the tuple has to exist.
-                let (&a_last, a_mid) = if let Some(x) = tys_a.split_last() {
-                    x
-                } else {
-                    return Err(Unimplemented);
-                };
-                let &b_last = tys_b.last().unwrap();
-
-                // Check that the source tuple with the target's
-                // last element is equal to the target.
-                let new_tuple = tcx.mk_tup(
-                    a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())),
-                );
-                let InferOk { obligations, .. } = self
-                    .infcx
-                    .at(&obligation.cause, obligation.param_env)
-                    .eq(target, new_tuple)
-                    .map_err(|_| Unimplemented)?;
-                nested.extend(obligations);
-
-                // Construct the nested `T: Unsize<U>` predicate.
-                nested.push(predicate_for_trait_def(
-                    tcx,
-                    obligation.param_env,
-                    obligation.cause.clone(),
-                    obligation.predicate.def_id(),
-                    obligation.recursion_depth + 1,
-                    a_last.expect_ty(),
-                    &[b_last],
-                ));
-            }
-
-            _ => bug!(),
-        };
-
-        Ok(VtableBuiltinData { nested })
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Matching
-    //
-    // Matching is a common path used for both evaluation and
-    // confirmation.  It basically unifies types that appear in impls
-    // and traits. This does affect the surrounding environment;
-    // therefore, when used during evaluation, match routines must be
-    // run inside of a `probe()` so that their side-effects are
-    // contained.
-
-    fn rematch_impl(
-        &mut self,
-        impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> Normalized<'tcx, SubstsRef<'tcx>> {
-        match self.match_impl(impl_def_id, obligation, snapshot) {
-            Ok(substs) => substs,
-            Err(()) => {
-                bug!(
-                    "Impl {:?} was matchable against {:?} but now is not",
-                    impl_def_id,
-                    obligation
-                );
-            }
-        }
-    }
-
-    fn match_impl(
-        &mut self,
-        impl_def_id: DefId,
-        obligation: &TraitObligation<'tcx>,
-        snapshot: &CombinedSnapshot<'_, 'tcx>,
-    ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
-        let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
-
-        // Before we create the substitutions and everything, first
-        // consider a "quick reject". This avoids creating more types
-        // and so forth that we need to.
-        if self.fast_reject_trait_refs(obligation, &impl_trait_ref) {
-            return Err(());
-        }
-
-        let (skol_obligation, placeholder_map) =
-            self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
-        let skol_obligation_trait_ref = skol_obligation.trait_ref;
-
-        let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
-
-        let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
-
-        let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
-            project::normalize_with_depth(
-                self,
-                obligation.param_env,
-                obligation.cause.clone(),
-                obligation.recursion_depth + 1,
-                &impl_trait_ref,
-            );
-
-        debug!(
-            "match_impl(impl_def_id={:?}, obligation={:?}, \
-             impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
-            impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
-        );
-
-        let InferOk { obligations, .. } = self
-            .infcx
-            .at(&obligation.cause, obligation.param_env)
-            .eq(skol_obligation_trait_ref, impl_trait_ref)
-            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
-        nested_obligations.extend(obligations);
-
-        if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
-            debug!("match_impl: failed leak check due to `{}`", e);
-            return Err(());
-        }
-
-        if !self.intercrate
-            && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
-        {
-            debug!("match_impl: reservation impls only apply in intercrate mode");
-            return Err(());
-        }
-
-        debug!("match_impl: success impl_substs={:?}", impl_substs);
-        Ok(Normalized { value: impl_substs, obligations: nested_obligations })
-    }
-
-    fn fast_reject_trait_refs(
-        &mut self,
-        obligation: &TraitObligation<'_>,
-        impl_trait_ref: &ty::TraitRef<'_>,
-    ) -> bool {
-        // We can avoid creating type variables and doing the full
-        // substitution if we find that any of the input types, when
-        // simplified, do not match.
-
-        obligation.predicate.skip_binder().input_types().zip(impl_trait_ref.input_types()).any(
-            |(obligation_ty, impl_ty)| {
-                let simplified_obligation_ty =
-                    fast_reject::simplify_type(self.tcx(), obligation_ty, true);
-                let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false);
-
-                simplified_obligation_ty.is_some()
-                    && simplified_impl_ty.is_some()
-                    && simplified_obligation_ty != simplified_impl_ty
-            },
-        )
-    }
-
-    /// Normalize `where_clause_trait_ref` and try to match it against
-    /// `obligation`. If successful, return any predicates that
-    /// result from the normalization. Normalization is necessary
-    /// because where-clauses are stored in the parameter environment
-    /// unnormalized.
-    fn match_where_clause_trait_ref(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
-        self.match_poly_trait_ref(obligation, where_clause_trait_ref)
-    }
-
-    /// Returns `Ok` if `poly_trait_ref` being true implies that the
-    /// obligation is satisfied.
-    fn match_poly_trait_ref(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        poly_trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
-        debug!(
-            "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
-            obligation, poly_trait_ref
-        );
-
-        self.infcx
-            .at(&obligation.cause, obligation.param_env)
-            .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
-            .map(|InferOk { obligations, .. }| obligations)
-            .map_err(|_| ())
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // Miscellany
-
-    fn match_fresh_trait_refs(
-        &self,
-        previous: &ty::PolyTraitRef<'tcx>,
-        current: &ty::PolyTraitRef<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> bool {
-        let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
-        matcher.relate(previous, current).is_ok()
-    }
-
-    fn push_stack<'o>(
-        &mut self,
-        previous_stack: TraitObligationStackList<'o, 'tcx>,
-        obligation: &'o TraitObligation<'tcx>,
-    ) -> TraitObligationStack<'o, 'tcx> {
-        let fresh_trait_ref =
-            obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
-
-        let dfn = previous_stack.cache.next_dfn();
-        let depth = previous_stack.depth() + 1;
-        TraitObligationStack {
-            obligation,
-            fresh_trait_ref,
-            reached_depth: Cell::new(depth),
-            previous: previous_stack,
-            dfn,
-            depth,
-        }
-    }
-
-    fn closure_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        closure_def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        debug!(
-            "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
-            obligation, closure_def_id, substs,
-        );
-        let closure_type = self.infcx.closure_sig(closure_def_id, substs);
-
-        debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type);
-
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an unboxed closure type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-        closure_trait_ref_and_return_type(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            closure_type,
-            util::TupleArgumentsFlag::No,
-        )
-        .map_bound(|(trait_ref, _)| trait_ref)
-    }
-
-    fn generator_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        closure_def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx());
-
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an generator type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-
-        super::util::generator_trait_ref_and_outputs(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            gen_sig,
-        )
-        .map_bound(|(trait_ref, ..)| trait_ref)
-    }
-
-    /// Returns the obligations that are implied by instantiating an
-    /// impl or trait. The obligations are substituted and fully
-    /// normalized. This is used when confirming an impl or default
-    /// impl.
-    fn impl_or_trait_obligations(
-        &mut self,
-        cause: ObligationCause<'tcx>,
-        recursion_depth: usize,
-        param_env: ty::ParamEnv<'tcx>,
-        def_id: DefId,           // of impl or trait
-        substs: SubstsRef<'tcx>, // for impl or trait
-    ) -> Vec<PredicateObligation<'tcx>> {
-        debug!("impl_or_trait_obligations(def_id={:?})", def_id);
-        let tcx = self.tcx();
-
-        // To allow for one-pass evaluation of the nested obligation,
-        // each predicate must be preceded by the obligations required
-        // to normalize it.
-        // for example, if we have:
-        //    impl<U: Iterator<Item: Copy>, V: Iterator<Item = U>> Foo for V
-        // the impl will have the following predicates:
-        //    <V as Iterator>::Item = U,
-        //    U: Iterator, U: Sized,
-        //    V: Iterator, V: Sized,
-        //    <U as Iterator>::Item: Copy
-        // When we substitute, say, `V => IntoIter<u32>, U => $0`, the last
-        // obligation will normalize to `<$0 as Iterator>::Item = $1` and
-        // `$1: Copy`, so we must ensure the obligations are emitted in
-        // that order.
-        let predicates = tcx.predicates_of(def_id);
-        assert_eq!(predicates.parent, None);
-        let mut obligations = Vec::with_capacity(predicates.predicates.len());
-        for (predicate, _) in predicates.predicates {
-            let predicate = normalize_with_depth_to(
-                self,
-                param_env,
-                cause.clone(),
-                recursion_depth,
-                &predicate.subst(tcx, substs),
-                &mut obligations,
-            );
-            obligations.push(Obligation {
-                cause: cause.clone(),
-                recursion_depth,
-                param_env,
-                predicate,
-            });
-        }
-
-        // We are performing deduplication here to avoid exponential blowups
-        // (#38528) from happening, but the real cause of the duplication is
-        // unknown. What we know is that the deduplication avoids exponential
-        // amount of predicates being propagated when processing deeply nested
-        // types.
-        //
-        // This code is hot enough that it's worth avoiding the allocation
-        // required for the FxHashSet when possible. Special-casing lengths 0,
-        // 1 and 2 covers roughly 75-80% of the cases.
-        if obligations.len() <= 1 {
-            // No possibility of duplicates.
-        } else if obligations.len() == 2 {
-            // Only two elements. Drop the second if they are equal.
-            if obligations[0] == obligations[1] {
-                obligations.truncate(1);
-            }
-        } else {
-            // Three or more elements. Use a general deduplication process.
-            let mut seen = FxHashSet::default();
-            obligations.retain(|i| seen.insert(i.clone()));
-        }
-
-        obligations
-    }
-}
-
-impl<'tcx> TraitObligation<'tcx> {
-    #[allow(unused_comparisons)]
-    pub fn derived_cause(
-        &self,
-        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
-    ) -> ObligationCause<'tcx> {
-        /*!
-         * Creates a cause for obligations that are derived from
-         * `obligation` by a recursive search (e.g., for a builtin
-         * bound, or eventually a `auto trait Foo`). If `obligation`
-         * is itself a derived obligation, this is just a clone, but
-         * otherwise we create a "derived obligation" cause so as to
-         * keep track of the original root obligation for error
-         * reporting.
-         */
-
-        let obligation = self;
-
-        // NOTE(flaper87): As of now, it keeps track of the whole error
-        // chain. Ideally, we should have a way to configure this either
-        // by using -Z verbose or just a CLI argument.
-        let derived_cause = DerivedObligationCause {
-            parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-            parent_code: Rc::new(obligation.cause.code.clone()),
-        };
-        let derived_code = variant(derived_cause);
-        ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
-    }
-}
-
-impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
-    fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList::with(self)
-    }
-
-    fn cache(&self) -> &'o ProvisionalEvaluationCache<'tcx> {
-        self.previous.cache
-    }
-
-    fn iter(&'o self) -> TraitObligationStackList<'o, 'tcx> {
-        self.list()
-    }
-
-    /// Indicates that attempting to evaluate this stack entry
-    /// required accessing something from the stack at depth `reached_depth`.
-    fn update_reached_depth(&self, reached_depth: usize) {
-        assert!(
-            self.depth > reached_depth,
-            "invoked `update_reached_depth` with something under this stack: \
-             self.depth={} reached_depth={}",
-            self.depth,
-            reached_depth,
-        );
-        debug!("update_reached_depth(reached_depth={})", reached_depth);
-        let mut p = self;
-        while reached_depth < p.depth {
-            debug!("update_reached_depth: marking {:?} as cycle participant", p.fresh_trait_ref);
-            p.reached_depth.set(p.reached_depth.get().min(reached_depth));
-            p = p.previous.head.unwrap();
-        }
-    }
-}
-
-/// The "provisional evaluation cache" is used to store intermediate cache results
-/// when solving auto traits. Auto traits are unusual in that they can support
-/// cycles. So, for example, a "proof tree" like this would be ok:
-///
-/// - `Foo<T>: Send` :-
-///   - `Bar<T>: Send` :-
-///     - `Foo<T>: Send` -- cycle, but ok
-///   - `Baz<T>: Send`
-///
-/// Here, to prove `Foo<T>: Send`, we have to prove `Bar<T>: Send` and
-/// `Baz<T>: Send`. Proving `Bar<T>: Send` in turn required `Foo<T>: Send`.
-/// For non-auto traits, this cycle would be an error, but for auto traits (because
-/// they are coinductive) it is considered ok.
-///
-/// However, there is a complication: at the point where we have
-/// "proven" `Bar<T>: Send`, we have in fact only proven it
-/// *provisionally*. In particular, we proved that `Bar<T>: Send`
-/// *under the assumption* that `Foo<T>: Send`. But what if we later
-/// find out this assumption is wrong?  Specifically, we could
-/// encounter some kind of error proving `Baz<T>: Send`. In that case,
-/// `Bar<T>: Send` didn't turn out to be true.
-///
-/// In Issue #60010, we found a bug in rustc where it would cache
-/// these intermediate results. This was fixed in #60444 by disabling
-/// *all* caching for things involved in a cycle -- in our example,
-/// that would mean we don't cache that `Bar<T>: Send`.  But this led
-/// to large slowdowns.
-///
-/// Specifically, imagine this scenario, where proving `Baz<T>: Send`
-/// first requires proving `Bar<T>: Send` (which is true:
-///
-/// - `Foo<T>: Send` :-
-///   - `Bar<T>: Send` :-
-///     - `Foo<T>: Send` -- cycle, but ok
-///   - `Baz<T>: Send`
-///     - `Bar<T>: Send` -- would be nice for this to be a cache hit!
-///     - `*const T: Send` -- but what if we later encounter an error?
-///
-/// The *provisional evaluation cache* resolves this issue. It stores
-/// cache results that we've proven but which were involved in a cycle
-/// in some way. We track the minimal stack depth (i.e., the
-/// farthest from the top of the stack) that we are dependent on.
-/// The idea is that the cache results within are all valid -- so long as
-/// none of the nodes in between the current node and the node at that minimum
-/// depth result in an error (in which case the cached results are just thrown away).
-///
-/// During evaluation, we consult this provisional cache and rely on
-/// it. Accessing a cached value is considered equivalent to accessing
-/// a result at `reached_depth`, so it marks the *current* solution as
-/// provisional as well. If an error is encountered, we toss out any
-/// provisional results added from the subtree that encountered the
-/// error.  When we pop the node at `reached_depth` from the stack, we
-/// can commit all the things that remain in the provisional cache.
-struct ProvisionalEvaluationCache<'tcx> {
-    /// next "depth first number" to issue -- just a counter
-    dfn: Cell<usize>,
-
-    /// Stores the "coldest" depth (bottom of stack) reached by any of
-    /// the evaluation entries. The idea here is that all things in the provisional
-    /// cache are always dependent on *something* that is colder in the stack:
-    /// therefore, if we add a new entry that is dependent on something *colder still*,
-    /// we have to modify the depth for all entries at once.
-    ///
-    /// Example:
-    ///
-    /// Imagine we have a stack `A B C D E` (with `E` being the top of
-    /// the stack).  We cache something with depth 2, which means that
-    /// it was dependent on C.  Then we pop E but go on and process a
-    /// new node F: A B C D F.  Now F adds something to the cache with
-    /// depth 1, meaning it is dependent on B.  Our original cache
-    /// entry is also dependent on B, because there is a path from E
-    /// to C and then from C to F and from F to B.
-    reached_depth: Cell<usize>,
-
-    /// Map from cache key to the provisionally evaluated thing.
-    /// The cache entries contain the result but also the DFN in which they
-    /// were added. The DFN is used to clear out values on failure.
-    ///
-    /// Imagine we have a stack like:
-    ///
-    /// - `A B C` and we add a cache for the result of C (DFN 2)
-    /// - Then we have a stack `A B D` where `D` has DFN 3
-    /// - We try to solve D by evaluating E: `A B D E` (DFN 4)
-    /// - `E` generates various cache entries which have cyclic dependices on `B`
-    ///   - `A B D E F` and so forth
-    ///   - the DFN of `F` for example would be 5
-    /// - then we determine that `E` is in error -- we will then clear
-    ///   all cache values whose DFN is >= 4 -- in this case, that
-    ///   means the cached value for `F`.
-    map: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ProvisionalEvaluation>>,
-}
-
-/// A cache value for the provisional cache: contains the depth-first
-/// number (DFN) and result.
-#[derive(Copy, Clone, Debug)]
-struct ProvisionalEvaluation {
-    from_dfn: usize,
-    result: EvaluationResult,
-}
-
-impl<'tcx> Default for ProvisionalEvaluationCache<'tcx> {
-    fn default() -> Self {
-        Self {
-            dfn: Cell::new(0),
-            reached_depth: Cell::new(std::usize::MAX),
-            map: Default::default(),
-        }
-    }
-}
-
-impl<'tcx> ProvisionalEvaluationCache<'tcx> {
-    /// Get the next DFN in sequence (basically a counter).
-    fn next_dfn(&self) -> usize {
-        let result = self.dfn.get();
-        self.dfn.set(result + 1);
-        result
-    }
-
-    /// Check the provisional cache for any result for
-    /// `fresh_trait_ref`. If there is a hit, then you must consider
-    /// it an access to the stack slots at depth
-    /// `self.current_reached_depth()` and above.
-    fn get_provisional(&self, fresh_trait_ref: ty::PolyTraitRef<'tcx>) -> Option<EvaluationResult> {
-        debug!(
-            "get_provisional(fresh_trait_ref={:?}) = {:#?} with reached-depth {}",
-            fresh_trait_ref,
-            self.map.borrow().get(&fresh_trait_ref),
-            self.reached_depth.get(),
-        );
-        Some(self.map.borrow().get(&fresh_trait_ref)?.result)
-    }
-
-    /// Current value of the `reached_depth` counter -- all the
-    /// provisional cache entries are dependent on the item at this
-    /// depth.
-    fn current_reached_depth(&self) -> usize {
-        self.reached_depth.get()
-    }
-
-    /// Insert a provisional result into the cache. The result came
-    /// from the node with the given DFN. It accessed a minimum depth
-    /// of `reached_depth` to compute. It evaluated `fresh_trait_ref`
-    /// and resulted in `result`.
-    fn insert_provisional(
-        &self,
-        from_dfn: usize,
-        reached_depth: usize,
-        fresh_trait_ref: ty::PolyTraitRef<'tcx>,
-        result: EvaluationResult,
-    ) {
-        debug!(
-            "insert_provisional(from_dfn={}, reached_depth={}, fresh_trait_ref={:?}, result={:?})",
-            from_dfn, reached_depth, fresh_trait_ref, result,
-        );
-        let r_d = self.reached_depth.get();
-        self.reached_depth.set(r_d.min(reached_depth));
-
-        debug!("insert_provisional: reached_depth={:?}", self.reached_depth.get());
-
-        self.map.borrow_mut().insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, result });
-    }
-
-    /// Invoked when the node with dfn `dfn` does not get a successful
-    /// result.  This will clear out any provisional cache entries
-    /// that were added since `dfn` was created. This is because the
-    /// provisional entries are things which must assume that the
-    /// things on the stack at the time of their creation succeeded --
-    /// since the failing node is presently at the top of the stack,
-    /// these provisional entries must either depend on it or some
-    /// ancestor of it.
-    fn on_failure(&self, dfn: usize) {
-        debug!("on_failure(dfn={:?})", dfn,);
-        self.map.borrow_mut().retain(|key, eval| {
-            if !eval.from_dfn >= dfn {
-                debug!("on_failure: removing {:?}", key);
-                false
-            } else {
-                true
-            }
-        });
-    }
-
-    /// Invoked when the node at depth `depth` completed without
-    /// depending on anything higher in the stack (if that completion
-    /// was a failure, then `on_failure` should have been invoked
-    /// already). The callback `op` will be invoked for each
-    /// provisional entry that we can now confirm.
-    fn on_completion(
-        &self,
-        depth: usize,
-        mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult),
-    ) {
-        debug!("on_completion(depth={}, reached_depth={})", depth, self.reached_depth.get(),);
-
-        if self.reached_depth.get() < depth {
-            debug!("on_completion: did not yet reach depth to complete");
-            return;
-        }
-
-        for (fresh_trait_ref, eval) in self.map.borrow_mut().drain() {
-            debug!("on_completion: fresh_trait_ref={:?} eval={:?}", fresh_trait_ref, eval,);
-
-            op(fresh_trait_ref, eval.result);
-        }
-
-        self.reached_depth.set(std::usize::MAX);
-    }
-}
-
-#[derive(Copy, Clone)]
-struct TraitObligationStackList<'o, 'tcx> {
-    cache: &'o ProvisionalEvaluationCache<'tcx>,
-    head: Option<&'o TraitObligationStack<'o, 'tcx>>,
-}
-
-impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
-    fn empty(cache: &'o ProvisionalEvaluationCache<'tcx>) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList { cache, head: None }
-    }
-
-    fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
-        TraitObligationStackList { cache: r.cache(), head: Some(r) }
-    }
-
-    fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        self.head
-    }
-
-    fn depth(&self) -> usize {
-        if let Some(head) = self.head { head.depth } else { 0 }
-    }
-}
-
-impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
-    type Item = &'o TraitObligationStack<'o, 'tcx>;
-
-    fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        match self.head {
-            Some(o) => {
-                *self = o.previous;
-                Some(o)
-            }
-            None => None,
-        }
-    }
-}
-
-impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "TraitObligationStack({:?})", self.obligation)
-    }
-}
diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs
deleted file mode 100644
index ee1c737c208..00000000000
--- a/src/librustc_infer/traits/specialize/mod.rs
+++ /dev/null
@@ -1,472 +0,0 @@
-//! Logic and data structures related to impl specialization, explained in
-//! greater detail below.
-//!
-//! At the moment, this implementation support only the simple "chain" rule:
-//! If any two impls overlap, one must be a strict subset of the other.
-//!
-//! See the [rustc guide] for a bit more detail on how specialization
-//! fits together with the rest of the trait machinery.
-//!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
-
-pub mod specialization_graph;
-use specialization_graph::GraphExt;
-
-use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
-use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
-use rustc::lint::LintDiagnosticBuilder;
-use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
-use rustc_hir::def_id::DefId;
-use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
-use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::DUMMY_SP;
-
-use super::util::impl_trait_ref_and_oblig;
-use super::{FulfillmentContext, SelectionContext};
-
-/// Information pertinent to an overlapping impl error.
-#[derive(Debug)]
-pub struct OverlapError {
-    pub with_impl: DefId,
-    pub trait_desc: String,
-    pub self_desc: Option<String>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
-    pub involves_placeholder: bool,
-}
-
-/// Given a subst for the requested impl, translate it to a subst
-/// appropriate for the actual item definition (whether it be in that impl,
-/// a parent impl, or the trait).
-///
-/// When we have selected one impl, but are actually using item definitions from
-/// a parent impl providing a default, we need a way to translate between the
-/// type parameters of the two impls. Here the `source_impl` is the one we've
-/// selected, and `source_substs` is a substitution of its generics.
-/// And `target_node` is the impl/trait we're actually going to get the
-/// definition from. The resulting substitution will map from `target_node`'s
-/// generics to `source_impl`'s generics as instantiated by `source_subst`.
-///
-/// For example, consider the following scenario:
-///
-/// ```rust
-/// trait Foo { ... }
-/// impl<T, U> Foo for (T, U) { ... }  // target impl
-/// impl<V> Foo for (V, V) { ... }     // source impl
-/// ```
-///
-/// Suppose we have selected "source impl" with `V` instantiated with `u32`.
-/// This function will produce a substitution with `T` and `U` both mapping to `u32`.
-///
-/// where-clauses add some trickiness here, because they can be used to "define"
-/// an argument indirectly:
-///
-/// ```rust
-/// impl<'a, I, T: 'a> Iterator for Cloned<I>
-///    where I: Iterator<Item = &'a T>, T: Clone
-/// ```
-///
-/// In a case like this, the substitution for `T` is determined indirectly,
-/// through associated type projection. We deal with such cases by using
-/// *fulfillment* to relate the two impls, requiring that all projections are
-/// resolved.
-pub fn translate_substs<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    source_impl: DefId,
-    source_substs: SubstsRef<'tcx>,
-    target_node: specialization_graph::Node,
-) -> SubstsRef<'tcx> {
-    debug!(
-        "translate_substs({:?}, {:?}, {:?}, {:?})",
-        param_env, source_impl, source_substs, target_node
-    );
-    let source_trait_ref =
-        infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs);
-
-    // translate the Self and Param parts of the substitution, since those
-    // vary across impls
-    let target_substs = match target_node {
-        specialization_graph::Node::Impl(target_impl) => {
-            // no need to translate if we're targeting the impl we started with
-            if source_impl == target_impl {
-                return source_substs;
-            }
-
-            fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
-                |_| {
-                    bug!(
-                        "When translating substitutions for specialization, the expected \
-                         specialization failed to hold"
-                    )
-                },
-            )
-        }
-        specialization_graph::Node::Trait(..) => source_trait_ref.substs,
-    };
-
-    // directly inherent the method generics, since those do not vary across impls
-    source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
-}
-
-/// Given a selected impl described by `impl_data`, returns the
-/// definition and substitutions for the method with the name `name`
-/// the kind `kind`, and trait method substitutions `substs`, in
-/// that impl, a less specialized impl, or the trait default,
-/// whichever applies.
-pub fn find_associated_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    item: &ty::AssocItem,
-    substs: SubstsRef<'tcx>,
-    impl_data: &super::VtableImplData<'tcx, ()>,
-) -> (DefId, SubstsRef<'tcx>) {
-    debug!("find_associated_item({:?}, {:?}, {:?}, {:?})", param_env, item, substs, impl_data);
-    assert!(!substs.needs_infer());
-
-    let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap();
-    let trait_def = tcx.trait_def(trait_def_id);
-
-    let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
-    match ancestors.leaf_def(tcx, item.ident, item.kind) {
-        Some(node_item) => {
-            let substs = tcx.infer_ctxt().enter(|infcx| {
-                let param_env = param_env.with_reveal_all();
-                let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
-                let substs = translate_substs(
-                    &infcx,
-                    param_env,
-                    impl_data.impl_def_id,
-                    substs,
-                    node_item.node,
-                );
-                infcx.tcx.erase_regions(&substs)
-            });
-            (node_item.item.def_id, substs)
-        }
-        None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id),
-    }
-}
-
-/// Is `impl1` a specialization of `impl2`?
-///
-/// Specialization is determined by the sets of types to which the impls apply;
-/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
-/// to.
-pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
-    debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
-
-    // The feature gate should prevent introducing new specializations, but not
-    // taking advantage of upstream ones.
-    if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
-        return false;
-    }
-
-    // We determine whether there's a subset relationship by:
-    //
-    // - skolemizing impl1,
-    // - assuming the where clauses for impl1,
-    // - instantiating impl2 with fresh inference variables,
-    // - unifying,
-    // - attempting to prove the where clauses for impl2
-    //
-    // The last three steps are encapsulated in `fulfill_implication`.
-    //
-    // See RFC 1210 for more details and justification.
-
-    // Currently we do not allow e.g., a negative impl to specialize a positive one
-    if tcx.impl_polarity(impl1_def_id) != tcx.impl_polarity(impl2_def_id) {
-        return false;
-    }
-
-    // create a parameter environment corresponding to a (placeholder) instantiation of impl1
-    let penv = tcx.param_env(impl1_def_id);
-    let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
-
-    // Create a infcx, taking the predicates of impl1 as assumptions:
-    tcx.infer_ctxt().enter(|infcx| {
-        // Normalize the trait reference. The WF rules ought to ensure
-        // that this always succeeds.
-        let impl1_trait_ref = match traits::fully_normalize(
-            &infcx,
-            FulfillmentContext::new(),
-            ObligationCause::dummy(),
-            penv,
-            &impl1_trait_ref,
-        ) {
-            Ok(impl1_trait_ref) => impl1_trait_ref,
-            Err(err) => {
-                bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
-            }
-        };
-
-        // Attempt to prove that impl2 applies, given all of the above.
-        fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
-    })
-}
-
-/// Attempt to fulfill all obligations of `target_impl` after unification with
-/// `source_trait_ref`. If successful, returns a substitution for *all* the
-/// generics of `target_impl`, including both those needed to unify with
-/// `source_trait_ref` and those whose identity is determined via a where
-/// clause in the impl.
-fn fulfill_implication<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    source_trait_ref: ty::TraitRef<'tcx>,
-    target_impl: DefId,
-) -> Result<SubstsRef<'tcx>, ()> {
-    debug!(
-        "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
-        param_env, source_trait_ref, target_impl
-    );
-
-    let selcx = &mut SelectionContext::new(&infcx);
-    let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
-    let (target_trait_ref, mut obligations) =
-        impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
-    debug!(
-        "fulfill_implication: target_trait_ref={:?}, obligations={:?}",
-        target_trait_ref, obligations
-    );
-
-    // do the impls unify? If not, no specialization.
-    match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
-        Ok(InferOk { obligations: o, .. }) => {
-            obligations.extend(o);
-        }
-        Err(_) => {
-            debug!(
-                "fulfill_implication: {:?} does not unify with {:?}",
-                source_trait_ref, target_trait_ref
-            );
-            return Err(());
-        }
-    }
-
-    // attempt to prove all of the predicates for impl2 given those for impl1
-    // (which are packed up in penv)
-
-    infcx.save_and_restore_in_snapshot_flag(|infcx| {
-        // If we came from `translate_substs`, we already know that the
-        // predicates for our impl hold (after all, we know that a more
-        // specialized impl holds, so our impl must hold too), and
-        // we only want to process the projections to determine the
-        // the types in our substs using RFC 447, so we can safely
-        // ignore region obligations, which allows us to avoid threading
-        // a node-id to assign them with.
-        //
-        // If we came from specialization graph construction, then
-        // we already make a mockery out of the region system, so
-        // why not ignore them a bit earlier?
-        let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
-        for oblig in obligations.into_iter() {
-            fulfill_cx.register_predicate_obligation(&infcx, oblig);
-        }
-        match fulfill_cx.select_all_or_error(infcx) {
-            Err(errors) => {
-                // no dice!
-                debug!(
-                    "fulfill_implication: for impls on {:?} and {:?}, \
-                     could not fulfill: {:?} given {:?}",
-                    source_trait_ref, target_trait_ref, errors, param_env.caller_bounds
-                );
-                Err(())
-            }
-
-            Ok(()) => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait_ref, target_trait_ref
-                );
-
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(&target_substs))
-            }
-        }
-    })
-}
-
-// Query provider for `specialization_graph_of`.
-pub(super) fn specialization_graph_provider(
-    tcx: TyCtxt<'_>,
-    trait_id: DefId,
-) -> &specialization_graph::Graph {
-    let mut sg = specialization_graph::Graph::new();
-
-    let mut trait_impls = tcx.all_impls(trait_id);
-
-    // The coherence checking implementation seems to rely on impls being
-    // iterated over (roughly) in definition order, so we are sorting by
-    // negated `CrateNum` (so remote definitions are visited first) and then
-    // by a flattened version of the `DefIndex`.
-    trait_impls
-        .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
-
-    for impl_def_id in trait_impls {
-        if impl_def_id.is_local() {
-            // This is where impl overlap checking happens:
-            let insert_result = sg.insert(tcx, impl_def_id);
-            // Report error if there was one.
-            let (overlap, used_to_be_allowed) = match insert_result {
-                Err(overlap) => (Some(overlap), None),
-                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
-                Ok(None) => (None, None),
-            };
-
-            if let Some(overlap) = overlap {
-                let impl_span =
-                    tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
-
-                // Work to be done after we've built the DiagnosticBuilder. We have to define it
-                // now because the struct_lint methods don't return back the DiagnosticBuilder
-                // that's passed in.
-                let decorate = |err: LintDiagnosticBuilder<'_>| {
-                    let msg = format!(
-                        "conflicting implementations of trait `{}`{}:{}",
-                        overlap.trait_desc,
-                        overlap
-                            .self_desc
-                            .clone()
-                            .map_or(String::new(), |ty| { format!(" for type `{}`", ty) }),
-                        match used_to_be_allowed {
-                            Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)",
-                            _ => "",
-                        }
-                    );
-                    let mut err = err.build(&msg);
-                    match tcx.span_of_impl(overlap.with_impl) {
-                        Ok(span) => {
-                            err.span_label(
-                                tcx.sess.source_map().def_span(span),
-                                "first implementation here".to_string(),
-                            );
-
-                            err.span_label(
-                                impl_span,
-                                format!(
-                                    "conflicting implementation{}",
-                                    overlap
-                                        .self_desc
-                                        .map_or(String::new(), |ty| format!(" for `{}`", ty))
-                                ),
-                            );
-                        }
-                        Err(cname) => {
-                            let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
-                                Some(s) => format!(
-                                    "conflicting implementation in crate `{}`:\n- {}",
-                                    cname, s
-                                ),
-                                None => format!("conflicting implementation in crate `{}`", cname),
-                            };
-                            err.note(&msg);
-                        }
-                    }
-
-                    for cause in &overlap.intercrate_ambiguity_causes {
-                        cause.add_intercrate_ambiguity_hint(&mut err);
-                    }
-
-                    if overlap.involves_placeholder {
-                        coherence::add_placeholder_note(&mut err);
-                    }
-                    err.emit()
-                };
-
-                match used_to_be_allowed {
-                    None => {
-                        let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
-                        decorate(LintDiagnosticBuilder::new(err));
-                    }
-                    Some(kind) => {
-                        let lint = match kind {
-                            FutureCompatOverlapErrorKind::Issue33140 => {
-                                ORDER_DEPENDENT_TRAIT_OBJECTS
-                            }
-                            FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
-                        };
-                        tcx.struct_span_lint_hir(
-                            lint,
-                            tcx.hir().as_local_hir_id(impl_def_id).unwrap(),
-                            impl_span,
-                            decorate,
-                        )
-                    }
-                };
-            }
-        } else {
-            let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
-            sg.record_impl_from_cstore(tcx, parent, impl_def_id)
-        }
-    }
-
-    tcx.arena.alloc(sg)
-}
-
-/// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
-/// string.
-fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
-    use std::fmt::Write;
-
-    let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) {
-        tr
-    } else {
-        return None;
-    };
-
-    let mut w = "impl".to_owned();
-
-    let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
-
-    // FIXME: Currently only handles ?Sized.
-    //        Needs to support ?Move and ?DynSized when they are implemented.
-    let mut types_without_default_bounds = FxHashSet::default();
-    let sized_trait = tcx.lang_items().sized_trait();
-
-    if !substs.is_noop() {
-        types_without_default_bounds.extend(substs.types());
-        w.push('<');
-        w.push_str(
-            &substs
-                .iter()
-                .map(|k| k.to_string())
-                .filter(|k| k != "'_")
-                .collect::<Vec<_>>()
-                .join(", "),
-        );
-        w.push('>');
-    }
-
-    write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
-
-    // The predicates will contain default bounds like `T: Sized`. We need to
-    // remove these bounds, and add `T: ?Sized` to any untouched type parameters.
-    let predicates = tcx.predicates_of(impl_def_id).predicates;
-    let mut pretty_predicates =
-        Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
-
-    for (p, _) in predicates {
-        if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
-            if Some(poly_trait_ref.def_id()) == sized_trait {
-                types_without_default_bounds.remove(poly_trait_ref.self_ty());
-                continue;
-            }
-        }
-        pretty_predicates.push(p.to_string());
-    }
-
-    pretty_predicates
-        .extend(types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)));
-
-    if !pretty_predicates.is_empty() {
-        write!(w, "\n  where {}", pretty_predicates.join(", ")).unwrap();
-    }
-
-    w.push(';');
-    Some(w)
-}
diff --git a/src/librustc_infer/traits/specialize/specialization_graph.rs b/src/librustc_infer/traits/specialize/specialization_graph.rs
deleted file mode 100644
index 17d4a22b9dd..00000000000
--- a/src/librustc_infer/traits/specialize/specialization_graph.rs
+++ /dev/null
@@ -1,379 +0,0 @@
-use super::OverlapError;
-
-use crate::traits;
-use rustc::ty::fast_reject::{self, SimplifiedType};
-use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc_hir::def_id::DefId;
-
-pub use rustc::traits::specialization_graph::*;
-
-#[derive(Copy, Clone, Debug)]
-pub enum FutureCompatOverlapErrorKind {
-    Issue33140,
-    LeakCheck,
-}
-
-#[derive(Debug)]
-pub struct FutureCompatOverlapError {
-    pub error: OverlapError,
-    pub kind: FutureCompatOverlapErrorKind,
-}
-
-/// The result of attempting to insert an impl into a group of children.
-enum Inserted {
-    /// The impl was inserted as a new child in this group of children.
-    BecameNewSibling(Option<FutureCompatOverlapError>),
-
-    /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
-    ReplaceChildren(Vec<DefId>),
-
-    /// The impl is a specialization of an existing child.
-    ShouldRecurseOn(DefId),
-}
-
-trait ChildrenExt {
-    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        simplified_self: Option<SimplifiedType>,
-    ) -> Result<Inserted, OverlapError>;
-}
-
-impl ChildrenExt for Children {
-    /// Insert an impl into this set of children without comparing to any existing impls.
-    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
-            debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
-            self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
-        } else {
-            debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
-            self.blanket_impls.push(impl_def_id)
-        }
-    }
-
-    /// Removes an impl from this set of children. Used when replacing
-    /// an impl with a parent. The impl must be present in the list of
-    /// children already.
-    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let vec: &mut Vec<DefId>;
-        if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
-            debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
-            vec = self.nonblanket_impls.get_mut(&st).unwrap();
-        } else {
-            debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
-            vec = &mut self.blanket_impls;
-        }
-
-        let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
-        vec.remove(index);
-    }
-
-    /// Attempt to insert an impl into this set of children, while comparing for
-    /// specialization relationships.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        simplified_self: Option<SimplifiedType>,
-    ) -> Result<Inserted, OverlapError> {
-        let mut last_lint = None;
-        let mut replace_children = Vec::new();
-
-        debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,);
-
-        let possible_siblings = match simplified_self {
-            Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)),
-            None => PotentialSiblings::Unfiltered(iter_children(self)),
-        };
-
-        for possible_sibling in possible_siblings {
-            debug!(
-                "insert: impl_def_id={:?}, simplified_self={:?}, possible_sibling={:?}",
-                impl_def_id, simplified_self, possible_sibling,
-            );
-
-            let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
-                let trait_ref = overlap.impl_header.trait_ref.unwrap();
-                let self_ty = trait_ref.self_ty();
-
-                OverlapError {
-                    with_impl: possible_sibling,
-                    trait_desc: trait_ref.print_only_trait_path().to_string(),
-                    // Only report the `Self` type if it has at least
-                    // some outer concrete shell; otherwise, it's
-                    // not adding much information.
-                    self_desc: if self_ty.has_concrete_skeleton() {
-                        Some(self_ty.to_string())
-                    } else {
-                        None
-                    },
-                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
-                    involves_placeholder: overlap.involves_placeholder,
-                }
-            };
-
-            let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
-                                        last_lint: &mut _| {
-                // Found overlap, but no specialization; error out or report future-compat warning.
-
-                // Do we *still* get overlap if we disable the future-incompatible modes?
-                let should_err = traits::overlapping_impls(
-                    tcx,
-                    possible_sibling,
-                    impl_def_id,
-                    traits::SkipLeakCheck::default(),
-                    |_| true,
-                    || false,
-                );
-
-                let error = create_overlap_error(overlap);
-
-                if should_err {
-                    Err(error)
-                } else {
-                    *last_lint = Some(FutureCompatOverlapError {
-                        error,
-                        kind: FutureCompatOverlapErrorKind::LeakCheck,
-                    });
-
-                    Ok((false, false))
-                }
-            };
-
-            let last_lint_mut = &mut last_lint;
-            let (le, ge) = traits::overlapping_impls(
-                tcx,
-                possible_sibling,
-                impl_def_id,
-                traits::SkipLeakCheck::Yes,
-                |overlap| {
-                    if let Some(overlap_kind) =
-                        tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
-                    {
-                        match overlap_kind {
-                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
-                            ty::ImplOverlapKind::Issue33140 => {
-                                *last_lint_mut = Some(FutureCompatOverlapError {
-                                    error: create_overlap_error(overlap),
-                                    kind: FutureCompatOverlapErrorKind::Issue33140,
-                                });
-                            }
-                        }
-
-                        return Ok((false, false));
-                    }
-
-                    let le = tcx.specializes((impl_def_id, possible_sibling));
-                    let ge = tcx.specializes((possible_sibling, impl_def_id));
-
-                    if le == ge {
-                        report_overlap_error(overlap, last_lint_mut)
-                    } else {
-                        Ok((le, ge))
-                    }
-                },
-                || Ok((false, false)),
-            )?;
-
-            if le && !ge {
-                debug!(
-                    "descending as child of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap()
-                );
-
-                // The impl specializes `possible_sibling`.
-                return Ok(Inserted::ShouldRecurseOn(possible_sibling));
-            } else if ge && !le {
-                debug!(
-                    "placing as parent of TraitRef {:?}",
-                    tcx.impl_trait_ref(possible_sibling).unwrap()
-                );
-
-                replace_children.push(possible_sibling);
-            } else {
-                // Either there's no overlap, or the overlap was already reported by
-                // `overlap_error`.
-            }
-        }
-
-        if !replace_children.is_empty() {
-            return Ok(Inserted::ReplaceChildren(replace_children));
-        }
-
-        // No overlap with any potential siblings, so add as a new sibling.
-        debug!("placing as new sibling");
-        self.insert_blindly(tcx, impl_def_id);
-        Ok(Inserted::BecameNewSibling(last_lint))
-    }
-}
-
-fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
-    let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
-    children.blanket_impls.iter().chain(nonblanket).cloned()
-}
-
-fn filtered_children(
-    children: &mut Children,
-    st: SimplifiedType,
-) -> impl Iterator<Item = DefId> + '_ {
-    let nonblanket = children.nonblanket_impls.entry(st).or_default().iter();
-    children.blanket_impls.iter().chain(nonblanket).cloned()
-}
-
-// A custom iterator used by Children::insert
-enum PotentialSiblings<I, J>
-where
-    I: Iterator<Item = DefId>,
-    J: Iterator<Item = DefId>,
-{
-    Unfiltered(I),
-    Filtered(J),
-}
-
-impl<I, J> Iterator for PotentialSiblings<I, J>
-where
-    I: Iterator<Item = DefId>,
-    J: Iterator<Item = DefId>,
-{
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match *self {
-            PotentialSiblings::Unfiltered(ref mut iter) => iter.next(),
-            PotentialSiblings::Filtered(ref mut iter) => iter.next(),
-        }
-    }
-}
-
-pub trait GraphExt {
-    /// Insert a local impl into the specialization graph. If an existing impl
-    /// conflicts with it (has overlap, but neither specializes the other),
-    /// information about the area of overlap is returned in the `Err`.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-    ) -> Result<Option<FutureCompatOverlapError>, OverlapError>;
-
-    /// Insert cached metadata mapping from a child impl back to its parent.
-    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId);
-}
-
-impl GraphExt for Graph {
-    /// Insert a local impl into the specialization graph. If an existing impl
-    /// conflicts with it (has overlap, but neither specializes the other),
-    /// information about the area of overlap is returned in the `Err`.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-    ) -> Result<Option<FutureCompatOverlapError>, OverlapError> {
-        assert!(impl_def_id.is_local());
-
-        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
-        let trait_def_id = trait_ref.def_id;
-
-        debug!(
-            "insert({:?}): inserting TraitRef {:?} into specialization graph",
-            impl_def_id, trait_ref
-        );
-
-        // If the reference itself contains an earlier error (e.g., due to a
-        // resolution failure), then we just insert the impl at the top level of
-        // the graph and claim that there's no overlap (in order to suppress
-        // bogus errors).
-        if trait_ref.references_error() {
-            debug!(
-                "insert: inserting dummy node for erroneous TraitRef {:?}, \
-                 impl_def_id={:?}, trait_def_id={:?}",
-                trait_ref, impl_def_id, trait_def_id
-            );
-
-            self.parent.insert(impl_def_id, trait_def_id);
-            self.children.entry(trait_def_id).or_default().insert_blindly(tcx, impl_def_id);
-            return Ok(None);
-        }
-
-        let mut parent = trait_def_id;
-        let mut last_lint = None;
-        let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false);
-
-        // Descend the specialization tree, where `parent` is the current parent node.
-        loop {
-            use self::Inserted::*;
-
-            let insert_result =
-                self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?;
-
-            match insert_result {
-                BecameNewSibling(opt_lint) => {
-                    last_lint = opt_lint;
-                    break;
-                }
-                ReplaceChildren(grand_children_to_be) => {
-                    // We currently have
-                    //
-                    //     P
-                    //     |
-                    //     G
-                    //
-                    // and we are inserting the impl N. We want to make it:
-                    //
-                    //     P
-                    //     |
-                    //     N
-                    //     |
-                    //     G
-
-                    // Adjust P's list of children: remove G and then add N.
-                    {
-                        let siblings = self.children.get_mut(&parent).unwrap();
-                        for &grand_child_to_be in &grand_children_to_be {
-                            siblings.remove_existing(tcx, grand_child_to_be);
-                        }
-                        siblings.insert_blindly(tcx, impl_def_id);
-                    }
-
-                    // Set G's parent to N and N's parent to P.
-                    for &grand_child_to_be in &grand_children_to_be {
-                        self.parent.insert(grand_child_to_be, impl_def_id);
-                    }
-                    self.parent.insert(impl_def_id, parent);
-
-                    // Add G as N's child.
-                    for &grand_child_to_be in &grand_children_to_be {
-                        self.children
-                            .entry(impl_def_id)
-                            .or_default()
-                            .insert_blindly(tcx, grand_child_to_be);
-                    }
-                    break;
-                }
-                ShouldRecurseOn(new_parent) => {
-                    parent = new_parent;
-                }
-            }
-        }
-
-        self.parent.insert(impl_def_id, parent);
-        Ok(last_lint)
-    }
-
-    /// Insert cached metadata mapping from a child impl back to its parent.
-    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) {
-        if self.parent.insert(child, parent).is_some() {
-            bug!(
-                "When recording an impl from the crate store, information about its parent \
-                 was already present."
-            );
-        }
-
-        self.children.entry(parent).or_default().insert_blindly(tcx, child);
-    }
-}
diff --git a/src/librustc_infer/traits/structural_impls.rs b/src/librustc_infer/traits/structural_impls.rs
index 6630f664f96..595a8cd7683 100644
--- a/src/librustc_infer/traits/structural_impls.rs
+++ b/src/librustc_infer/traits/structural_impls.rs
@@ -1,7 +1,7 @@
 use crate::traits;
 use crate::traits::project::Normalized;
-use rustc::ty;
-use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use rustc_middle::ty;
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 
 use std::fmt;
 
diff --git a/src/librustc_infer/traits/structural_match.rs b/src/librustc_infer/traits/structural_match.rs
deleted file mode 100644
index 60682f58129..00000000000
--- a/src/librustc_infer/traits/structural_match.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::ObligationCause;
-use crate::traits::{self, ConstPatternStructural, TraitEngine};
-
-use rustc::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_span::Span;
-
-#[derive(Debug)]
-pub enum NonStructuralMatchTy<'tcx> {
-    Adt(&'tcx AdtDef),
-    Param,
-}
-
-/// This method traverses the structure of `ty`, trying to find an
-/// instance of an ADT (i.e. struct or enum) that was declared without
-/// the `#[structural_match]` attribute, or a generic type parameter
-/// (which cannot be determined to be `structural_match`).
-///
-/// The "structure of a type" includes all components that would be
-/// considered when doing a pattern match on a constant of that
-/// type.
-///
-///  * This means this method descends into fields of structs/enums,
-///    and also descends into the inner type `T` of `&T` and `&mut T`
-///
-///  * The traversal doesn't dereference unsafe pointers (`*const T`,
-///    `*mut T`), and it does not visit the type arguments of an
-///    instantiated generic like `PhantomData<T>`.
-///
-/// The reason we do this search is Rust currently require all ADTs
-/// reachable from a constant's type to be annotated with
-/// `#[structural_match]`, an attribute which essentially says that
-/// the implementation of `PartialEq::eq` behaves *equivalently* to a
-/// comparison against the unfolded structure.
-///
-/// For more background on why Rust has this requirement, and issues
-/// that arose when the requirement was not enforced completely, see
-/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
-pub fn search_for_structural_match_violation<'tcx>(
-    id: hir::HirId,
-    span: Span,
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<NonStructuralMatchTy<'tcx>> {
-    // FIXME: we should instead pass in an `infcx` from the outside.
-    tcx.infer_ctxt().enter(|infcx| {
-        let mut search = Search { id, span, infcx, found: None, seen: FxHashSet::default() };
-        ty.visit_with(&mut search);
-        search.found
-    })
-}
-
-/// This method returns true if and only if `adt_ty` itself has been marked as
-/// eligible for structural-match: namely, if it implements both
-/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
-/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
-///
-/// Note that this does *not* recursively check if the substructure of `adt_ty`
-/// implements the traits.
-pub fn type_marked_structural(
-    id: hir::HirId,
-    span: Span,
-    infcx: &InferCtxt<'_, 'tcx>,
-    adt_ty: Ty<'tcx>,
-) -> bool {
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
-    // require `#[derive(PartialEq)]`
-    let structural_peq_def_id = infcx.tcx.lang_items().structural_peq_trait().unwrap();
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_peq_def_id,
-        cause,
-    );
-    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
-    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
-    let structural_teq_def_id = infcx.tcx.lang_items().structural_teq_trait().unwrap();
-    fulfillment_cx.register_bound(
-        infcx,
-        ty::ParamEnv::empty(),
-        adt_ty,
-        structural_teq_def_id,
-        cause,
-    );
-
-    // We deliberately skip *reporting* fulfillment errors (via
-    // `report_fulfillment_errors`), for two reasons:
-    //
-    // 1. The error messages would mention `std::marker::StructuralPartialEq`
-    //    (a trait which is solely meant as an implementation detail
-    //    for now), and
-    //
-    // 2. We are sometimes doing future-incompatibility lints for
-    //    now, so we do not want unconditional errors here.
-    fulfillment_cx.select_all_or_error(infcx).is_ok()
-}
-
-/// This implements the traversal over the structure of a given type to try to
-/// find instances of ADTs (specifically structs or enums) that do not implement
-/// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
-struct Search<'a, 'tcx> {
-    id: hir::HirId,
-    span: Span,
-
-    infcx: InferCtxt<'a, 'tcx>,
-
-    /// Records first ADT that does not implement a structural-match trait.
-    found: Option<NonStructuralMatchTy<'tcx>>,
-
-    /// Tracks ADTs previously encountered during search, so that
-    /// we will not recur on them again.
-    seen: FxHashSet<hir::def_id::DefId>,
-}
-
-impl Search<'a, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
-        type_marked_structural(self.id, self.span, &self.infcx, adt_ty)
-    }
-}
-
-impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
-        debug!("Search visiting ty: {:?}", ty);
-
-        let (adt_def, substs) = match ty.kind {
-            ty::Adt(adt_def, substs) => (adt_def, substs),
-            ty::Param(_) => {
-                self.found = Some(NonStructuralMatchTy::Param);
-                return true; // Stop visiting.
-            }
-            ty::RawPtr(..) => {
-                // structural-match ignores substructure of
-                // `*const _`/`*mut _`, so skip `super_visit_with`.
-                //
-                // For example, if you have:
-                // ```
-                // struct NonStructural;
-                // #[derive(PartialEq, Eq)]
-                // struct T(*const NonStructural);
-                // const C: T = T(std::ptr::null());
-                // ```
-                //
-                // Even though `NonStructural` does not implement `PartialEq`,
-                // structural equality on `T` does not recur into the raw
-                // pointer. Therefore, one can still use `C` in a pattern.
-
-                // (But still tell caller to continue search.)
-                return false;
-            }
-            ty::FnDef(..) | ty::FnPtr(..) => {
-                // types of formals and return in `fn(_) -> _` are also irrelevant;
-                // so we do not recur into them via `super_visit_with`
-                //
-                // (But still tell caller to continue search.)
-                return false;
-            }
-            ty::Array(_, n)
-                if { n.try_eval_usize(self.tcx(), ty::ParamEnv::reveal_all()) == Some(0) } =>
-            {
-                // rust-lang/rust#62336: ignore type of contents
-                // for empty array.
-                return false;
-            }
-            _ => {
-                ty.super_visit_with(self);
-                return false;
-            }
-        };
-
-        if !self.seen.insert(adt_def.did) {
-            debug!("Search already seen adt_def: {:?}", adt_def);
-            // let caller continue its search
-            return false;
-        }
-
-        if !self.type_marked_structural(ty) {
-            debug!("Search found ty: {:?}", ty);
-            self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
-            return true; // Halt visiting!
-        }
-
-        // structural-match does not care about the
-        // instantiation of the generics in an ADT (it
-        // instead looks directly at its fields outside
-        // this match), so we skip super_visit_with.
-        //
-        // (Must not recur on substs for `PhantomData<T>` cf
-        // rust-lang/rust#55028 and rust-lang/rust#55837; but also
-        // want to skip substs when only uses of generic are
-        // behind unsafe pointers `*const T`/`*mut T`.)
-
-        // even though we skip super_visit_with, we must recur on
-        // fields of ADT.
-        let tcx = self.tcx();
-        for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
-            if field_ty.visit_with(self) {
-                // found an ADT without structural-match; halt visiting!
-                assert!(self.found.is_some());
-                return true;
-            }
-        }
-
-        // Even though we do not want to recur on substs, we do
-        // want our caller to continue its own search.
-        false
-    }
-}
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index 1dca01b3468..4fa74f93ddc 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -1,18 +1,13 @@
-use rustc_errors::DiagnosticBuilder;
-use rustc_span::Span;
 use smallvec::smallvec;
-use smallvec::SmallVec;
 
-use rustc::ty::outlives::Component;
-use rustc::ty::subst::{GenericArg, Subst, SubstsRef};
-use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_middle::ty::outlives::Component;
+use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, TyCtxt, WithConstness};
 
-use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
-
-fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+pub fn anonymize_predicate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    pred: &ty::Predicate<'tcx>,
+) -> ty::Predicate<'tcx> {
     match *pred {
         ty::Predicate::Trait(ref data, constness) => {
             ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
@@ -55,7 +50,7 @@ struct PredicateSet<'tcx> {
 
 impl PredicateSet<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> Self {
-        Self { tcx: tcx, set: Default::default() }
+        Self { tcx, set: Default::default() }
     }
 
     fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
@@ -272,182 +267,6 @@ pub fn transitive_bounds<'tcx>(
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// `TraitAliasExpander` iterator
-///////////////////////////////////////////////////////////////////////////
-
-/// "Trait alias expansion" is the process of expanding a sequence of trait
-/// references into another sequence by transitively following all trait
-/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
-/// `trait Foo = Bar + Sync;`, and another trait alias
-/// `trait Bar = Read + Write`, then the bounds would expand to
-/// `Read + Write + Sync + Send`.
-/// Expansion is done via a DFS (depth-first search), and the `visited` field
-/// is used to avoid cycles.
-pub struct TraitAliasExpander<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
-}
-
-/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
-#[derive(Debug, Clone)]
-pub struct TraitAliasExpansionInfo<'tcx> {
-    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
-}
-
-impl<'tcx> TraitAliasExpansionInfo<'tcx> {
-    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        Self { path: smallvec![(trait_ref, span)] }
-    }
-
-    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
-    /// trait aliases.
-    pub fn label_with_exp_info(
-        &self,
-        diag: &mut DiagnosticBuilder<'_>,
-        top_label: &str,
-        use_desc: &str,
-    ) {
-        diag.span_label(self.top().1, top_label);
-        if self.path.len() > 1 {
-            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
-                diag.span_label(*sp, format!("referenced here ({})", use_desc));
-            }
-        }
-        diag.span_label(
-            self.bottom().1,
-            format!("trait alias used in trait object type ({})", use_desc),
-        );
-    }
-
-    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
-        &self.top().0
-    }
-
-    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.last().unwrap()
-    }
-
-    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
-        self.path.first().unwrap()
-    }
-
-    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
-        let mut path = self.path.clone();
-        path.push((trait_ref, span));
-
-        Self { path }
-    }
-}
-
-pub fn expand_trait_aliases<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
-) -> TraitAliasExpander<'tcx> {
-    let items: Vec<_> = trait_refs
-        .into_iter()
-        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
-        .collect();
-    TraitAliasExpander { tcx, stack: items }
-}
-
-impl<'tcx> TraitAliasExpander<'tcx> {
-    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
-    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
-    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
-    /// trait alias.
-    /// The return value indicates whether `item` should be yielded to the user.
-    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
-        let tcx = self.tcx;
-        let trait_ref = item.trait_ref();
-        let pred = trait_ref.without_const().to_predicate();
-
-        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
-
-        // Don't recurse if this bound is not a trait alias.
-        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
-        if !is_alias {
-            return true;
-        }
-
-        // Don't recurse if this trait alias is already on the stack for the DFS search.
-        let anon_pred = anonymize_predicate(tcx, &pred);
-        if item.path.iter().rev().skip(1).any(|(tr, _)| {
-            anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred
-        }) {
-            return false;
-        }
-
-        // Get components of trait alias.
-        let predicates = tcx.super_predicates_of(trait_ref.def_id());
-
-        let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
-            pred.subst_supertrait(tcx, &trait_ref)
-                .to_opt_poly_trait_ref()
-                .map(|trait_ref| item.clone_and_push(trait_ref, *span))
-        });
-        debug!("expand_trait_aliases: items={:?}", items.clone());
-
-        self.stack.extend(items);
-
-        false
-    }
-}
-
-impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
-    type Item = TraitAliasExpansionInfo<'tcx>;
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.stack.len(), None)
-    }
-
-    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
-        while let Some(item) = self.stack.pop() {
-            if self.expand(&item) {
-                return Some(item);
-            }
-        }
-        None
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Iterator over def-IDs of supertraits
-///////////////////////////////////////////////////////////////////////////
-
-pub struct SupertraitDefIds<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    stack: Vec<DefId>,
-    visited: FxHashSet<DefId>,
-}
-
-pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
-    SupertraitDefIds {
-        tcx,
-        stack: vec![trait_def_id],
-        visited: Some(trait_def_id).into_iter().collect(),
-    }
-}
-
-impl Iterator for SupertraitDefIds<'tcx> {
-    type Item = DefId;
-
-    fn next(&mut self) -> Option<DefId> {
-        let def_id = self.stack.pop()?;
-        let predicates = self.tcx.super_predicates_of(def_id);
-        let visited = &mut self.visited;
-        self.stack.extend(
-            predicates
-                .predicates
-                .iter()
-                .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
-                .map(|trait_ref| trait_ref.def_id())
-                .filter(|&super_def_id| visited.insert(super_def_id)),
-        );
-        Some(def_id)
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
 // Other
 ///////////////////////////////////////////////////////////////////////////
 
@@ -480,196 +299,3 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<
         (0, upper)
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
-/// Instantiate all bound parameters of the impl with the given substs,
-/// returning the resulting trait ref and all obligations that arise.
-/// The obligations are closed under normalization.
-pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
-    selcx: &mut SelectionContext<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: DefId,
-    impl_substs: SubstsRef<'tcx>,
-) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
-    let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
-    let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
-    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
-
-    let predicates = selcx.tcx().predicates_of(impl_def_id);
-    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
-    let Normalized { value: predicates, obligations: normalization_obligations2 } =
-        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
-    let impl_obligations =
-        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
-
-    let impl_obligations: Vec<_> = impl_obligations
-        .into_iter()
-        .chain(normalization_obligations1)
-        .chain(normalization_obligations2)
-        .collect();
-
-    (impl_trait_ref, impl_obligations)
-}
-
-/// See [`super::obligations_for_generics`].
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    recursion_depth: usize,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: &ty::InstantiatedPredicates<'tcx>,
-) -> Vec<PredicateObligation<'tcx>> {
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
-    generic_bounds
-        .predicates
-        .iter()
-        .map(|&predicate| Obligation {
-            cause: cause.clone(),
-            recursion_depth,
-            param_env,
-            predicate,
-        })
-        .collect()
-}
-
-pub fn predicate_for_trait_ref<'tcx>(
-    cause: ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    recursion_depth: usize,
-) -> PredicateObligation<'tcx> {
-    Obligation {
-        cause,
-        param_env,
-        recursion_depth,
-        predicate: trait_ref.without_const().to_predicate(),
-    }
-}
-
-pub fn predicate_for_trait_def(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    cause: ObligationCause<'tcx>,
-    trait_def_id: DefId,
-    recursion_depth: usize,
-    self_ty: Ty<'tcx>,
-    params: &[GenericArg<'tcx>],
-) -> PredicateObligation<'tcx> {
-    let trait_ref =
-        ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
-    predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
-}
-
-/// Casts a trait reference into a reference to one of its super
-/// traits; returns `None` if `target_trait_def_id` is not a
-/// supertrait.
-pub fn upcast_choices(
-    tcx: TyCtxt<'tcx>,
-    source_trait_ref: ty::PolyTraitRef<'tcx>,
-    target_trait_def_id: DefId,
-) -> Vec<ty::PolyTraitRef<'tcx>> {
-    if source_trait_ref.def_id() == target_trait_def_id {
-        return vec![source_trait_ref]; // Shortcut the most common case.
-    }
-
-    supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
-}
-
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-    let mut entries = 0;
-    // Count number of methods and add them to the total offset.
-    // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-    entries
-}
-
-/// Given an upcast trait object described by `object`, returns the
-/// index of the method `method_def_id` (which should be part of
-/// `object.upcast_trait_ref`) within the vtable for `object`.
-pub fn get_vtable_index_of_object_method<N>(
-    tcx: TyCtxt<'tcx>,
-    object: &super::VtableObjectData<'tcx, N>,
-    method_def_id: DefId,
-) -> usize {
-    // Count number of methods preceding the one we are selecting and
-    // add them to the total offset.
-    // Skip over associated types and constants.
-    let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
-        if trait_item.def_id == method_def_id {
-            // The item with the ID we were given really ought to be a method.
-            assert_eq!(trait_item.kind, ty::AssocKind::Method);
-            return entries;
-        }
-        if trait_item.kind == ty::AssocKind::Method {
-            entries += 1;
-        }
-    }
-
-    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
-}
-
-pub fn closure_trait_ref_and_return_type(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyFnSig<'tcx>,
-    tuple_arguments: TupleArgumentsFlag,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)> {
-    let arguments_tuple = match tuple_arguments {
-        TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
-        TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
-    };
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().output()))
-}
-
-pub fn generator_trait_ref_and_outputs(
-    tcx: TyCtxt<'tcx>,
-    fn_trait_def_id: DefId,
-    self_ty: Ty<'tcx>,
-    sig: ty::PolyGenSig<'tcx>,
-) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
-    let trait_ref = ty::TraitRef {
-        def_id: fn_trait_def_id,
-        substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]),
-    };
-    ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
-}
-
-pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
-    match tcx.hir().as_local_hir_id(node_item_def_id) {
-        Some(hir_id) => {
-            let item = tcx.hir().expect_item(hir_id);
-            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
-                defaultness.is_default()
-            } else {
-                false
-            }
-        }
-        None => tcx.impl_defaultness(node_item_def_id).is_default(),
-    }
-}
-
-pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
-    assoc_item.defaultness.is_final() && !impl_is_default(tcx, assoc_item.container.id())
-}
-
-pub enum TupleArgumentsFlag {
-    Yes,
-    No,
-}
diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs
deleted file mode 100644
index 980a3f04781..00000000000
--- a/src/librustc_infer/traits/wf.rs
+++ /dev/null
@@ -1,753 +0,0 @@
-use crate::infer::opaque_types::required_region_bounds;
-use crate::infer::InferCtxt;
-use crate::traits::{self, AssocTypeBoundData};
-use rustc::middle::lang_items;
-use rustc::ty::subst::SubstsRef;
-use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{kw, Ident};
-use rustc_span::Span;
-
-/// Returns the set of obligations needed to make `ty` well-formed.
-/// If `ty` contains unresolved inference variables, this may include
-/// further WF obligations. However, if `ty` IS an unresolved
-/// inference variable, returns `None`, because we are not able to
-/// make any progress at all. This is to prevent "livelock" where we
-/// say "$0 is WF if $0 is WF".
-pub fn obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    ty: Ty<'tcx>,
-    span: Span,
-) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
-    if wf.compute(ty) {
-        debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
-
-        let result = wf.normalize();
-        debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", ty, body_id, result);
-        Some(result)
-    } else {
-        None // no progress made, return None
-    }
-}
-
-/// Returns the obligations that make this trait reference
-/// well-formed.  For example, if there is a trait `Set` defined like
-/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
-/// if `Bar: Eq`.
-pub fn trait_obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    trait_ref: &ty::TraitRef<'tcx>,
-    span: Span,
-    item: Option<&'tcx hir::Item<'tcx>>,
-) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
-    wf.compute_trait_ref(trait_ref, Elaborate::All);
-    wf.normalize()
-}
-
-pub fn predicate_obligations<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    predicate: &ty::Predicate<'tcx>,
-    span: Span,
-) -> Vec<traits::PredicateObligation<'tcx>> {
-    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
-
-    // (*) ok to skip binders, because wf code is prepared for it
-    match *predicate {
-        ty::Predicate::Trait(ref t, _) => {
-            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
-        }
-        ty::Predicate::RegionOutlives(..) => {}
-        ty::Predicate::TypeOutlives(ref t) => {
-            wf.compute(t.skip_binder().0);
-        }
-        ty::Predicate::Projection(ref t) => {
-            let t = t.skip_binder(); // (*)
-            wf.compute_projection(t.projection_ty);
-            wf.compute(t.ty);
-        }
-        ty::Predicate::WellFormed(t) => {
-            wf.compute(t);
-        }
-        ty::Predicate::ObjectSafe(_) => {}
-        ty::Predicate::ClosureKind(..) => {}
-        ty::Predicate::Subtype(ref data) => {
-            wf.compute(data.skip_binder().a); // (*)
-            wf.compute(data.skip_binder().b); // (*)
-        }
-        ty::Predicate::ConstEvaluatable(def_id, substs) => {
-            let obligations = wf.nominal_obligations(def_id, substs);
-            wf.out.extend(obligations);
-
-            for ty in substs.types() {
-                wf.compute(ty);
-            }
-        }
-    }
-
-    wf.normalize()
-}
-
-struct WfPredicates<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: hir::HirId,
-    span: Span,
-    out: Vec<traits::PredicateObligation<'tcx>>,
-    item: Option<&'tcx hir::Item<'tcx>>,
-}
-
-/// Controls whether we "elaborate" supertraits and so forth on the WF
-/// predicates. This is a kind of hack to address #43784. The
-/// underlying problem in that issue was a trait structure like:
-///
-/// ```
-/// trait Foo: Copy { }
-/// trait Bar: Foo { }
-/// impl<T: Bar> Foo for T { }
-/// impl<T> Bar for T { }
-/// ```
-///
-/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
-/// we decide that this is true because `T: Bar` is in the
-/// where-clauses (and we can elaborate that to include `T:
-/// Copy`). This wouldn't be a problem, except that when we check the
-/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
-/// impl. And so nowhere did we check that `T: Copy` holds!
-///
-/// To resolve this, we elaborate the WF requirements that must be
-/// proven when checking impls. This means that (e.g.) the `impl Bar
-/// for T` will be forced to prove not only that `T: Foo` but also `T:
-/// Copy` (which it won't be able to do, because there is no `Copy`
-/// impl for `T`).
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-enum Elaborate {
-    All,
-    None,
-}
-
-impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
-    fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
-        traits::ObligationCause::new(self.span, self.body_id, code)
-    }
-
-    fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
-        let cause = self.cause(traits::MiscObligation);
-        let infcx = &mut self.infcx;
-        let param_env = self.param_env;
-        let mut obligations = Vec::with_capacity(self.out.len());
-        for pred in &self.out {
-            assert!(!pred.has_escaping_bound_vars());
-            let mut selcx = traits::SelectionContext::new(infcx);
-            let i = obligations.len();
-            let value =
-                traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations);
-            obligations.insert(i, value);
-        }
-        obligations
-    }
-
-    /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
-    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
-        let tcx = self.infcx.tcx;
-        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
-
-        let cause = self.cause(traits::MiscObligation);
-        let param_env = self.param_env;
-
-        let item = &self.item;
-        let extend_cause_with_original_assoc_item_obligation =
-            |cause: &mut traits::ObligationCause<'_>,
-             pred: &ty::Predicate<'_>,
-             trait_assoc_items: &[ty::AssocItem]| {
-                let trait_item = tcx
-                    .hir()
-                    .as_local_hir_id(trait_ref.def_id)
-                    .and_then(|trait_id| tcx.hir().find(trait_id));
-                let (trait_name, trait_generics) = match trait_item {
-                    Some(hir::Node::Item(hir::Item {
-                        ident,
-                        kind: hir::ItemKind::Trait(.., generics, _, _),
-                        ..
-                    }))
-                    | Some(hir::Node::Item(hir::Item {
-                        ident,
-                        kind: hir::ItemKind::TraitAlias(generics, _),
-                        ..
-                    })) => (Some(ident), Some(generics)),
-                    _ => (None, None),
-                };
-
-                let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span));
-                match pred {
-                    ty::Predicate::Projection(proj) => {
-                        // The obligation comes not from the current `impl` nor the `trait` being
-                        // implemented, but rather from a "second order" obligation, like in
-                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
-                        //
-                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
-                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
-                        //      |
-                        //   LL |     type Ok;
-                        //      |          -- associated type defined here
-                        //   ...
-                        //   LL | impl Bar for Foo {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = ();
-                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
-                        //      |
-                        //      = note: expected type `u32`
-                        //                 found type `()`
-                        //
-                        // FIXME: we would want to point a span to all places that contributed to this
-                        // obligation. In the case above, it should be closer to:
-                        //
-                        //   error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
-                        //     --> $DIR/point-at-type-on-obligation-failure.rs:13:5
-                        //      |
-                        //   LL |     type Ok;
-                        //      |          -- associated type defined here
-                        //   LL |     type Sibling: Bar2<Ok=Self::Ok>;
-                        //      |     -------------------------------- obligation set here
-                        //   ...
-                        //   LL | impl Bar for Foo {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = ();
-                        //      |     ^^^^^^^^^^^^^ expected `u32`, found `()`
-                        //   ...
-                        //   LL | impl Bar2 for Foo2 {
-                        //      | ---------------- in this `impl` item
-                        //   LL |     type Ok = u32;
-                        //      |     -------------- obligation set here
-                        //      |
-                        //      = note: expected type `u32`
-                        //                 found type `()`
-                        if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) {
-                            let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
-                            if let Some(impl_item) =
-                                items.iter().find(|item| item.ident == trait_assoc_item.ident)
-                            {
-                                cause.span = impl_item.span;
-                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
-                                    impl_span: item_span,
-                                    original: trait_assoc_item.ident.span,
-                                    bounds: vec![],
-                                }));
-                            }
-                        }
-                    }
-                    ty::Predicate::Trait(proj, _) => {
-                        // An associated item obligation born out of the `trait` failed to be met.
-                        // Point at the `impl` that failed the obligation, the associated item that
-                        // needed to meet the obligation, and the definition of that associated item,
-                        // which should hold the obligation in most cases. An example can be seen in
-                        // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
-                        //
-                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
-                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
-                        //      |
-                        //   LL |     type Assoc: Bar;
-                        //      |          ----- associated type defined here
-                        //   ...
-                        //   LL | impl Foo for () {
-                        //      | --------------- in this `impl` item
-                        //   LL |     type Assoc = bool;
-                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
-                        //
-                        // If the obligation comes from the where clause in the `trait`, we point at it:
-                        //
-                        //   error[E0277]: the trait bound `bool: Bar` is not satisfied
-                        //     --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
-                        //      |
-                        //      | trait Foo where <Self as Foo>>::Assoc: Bar {
-                        //      |                 -------------------------- restricted in this bound
-                        //   LL |     type Assoc;
-                        //      |          ----- associated type defined here
-                        //   ...
-                        //   LL | impl Foo for () {
-                        //      | --------------- in this `impl` item
-                        //   LL |     type Assoc = bool;
-                        //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
-                        if let (
-                            ty::Projection(ty::ProjectionTy { item_def_id, .. }),
-                            Some(hir::ItemKind::Impl { items, .. }),
-                        ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
-                        {
-                            if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
-                                .iter()
-                                .find(|i| i.def_id == *item_def_id)
-                                .and_then(|trait_assoc_item| {
-                                    items
-                                        .iter()
-                                        .find(|i| i.ident == trait_assoc_item.ident)
-                                        .map(|impl_item| (impl_item, trait_assoc_item))
-                                })
-                            {
-                                let bounds = trait_generics
-                                    .map(|generics| {
-                                        get_generic_bound_spans(
-                                            &generics,
-                                            trait_name,
-                                            trait_assoc_item.ident,
-                                        )
-                                    })
-                                    .unwrap_or_else(Vec::new);
-                                cause.span = impl_item.span;
-                                cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData {
-                                    impl_span: item_span,
-                                    original: trait_assoc_item.ident.span,
-                                    bounds,
-                                }));
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            };
-
-        if let Elaborate::All = elaborate {
-            // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator
-            // instead of a slice.
-            let trait_assoc_items: Vec<_> =
-                tcx.associated_items(trait_ref.def_id).in_definition_order().copied().collect();
-
-            let predicates = obligations.iter().map(|obligation| obligation.predicate).collect();
-            let implied_obligations = traits::elaborate_predicates(tcx, predicates);
-            let implied_obligations = implied_obligations.map(|pred| {
-                let mut cause = cause.clone();
-                extend_cause_with_original_assoc_item_obligation(
-                    &mut cause,
-                    &pred,
-                    &*trait_assoc_items,
-                );
-                traits::Obligation::new(cause, param_env, pred)
-            });
-            self.out.extend(implied_obligations);
-        }
-
-        self.out.extend(obligations);
-
-        self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
-            |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
-        ));
-    }
-
-    /// Pushes the obligations required for `trait_ref::Item` to be WF
-    /// into `self.out`.
-    fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
-        // A projection is well-formed if (a) the trait ref itself is
-        // WF and (b) the trait-ref holds.  (It may also be
-        // normalizable and be WF that way.)
-        let trait_ref = data.trait_ref(self.infcx.tcx);
-        self.compute_trait_ref(&trait_ref, Elaborate::None);
-
-        if !data.has_escaping_bound_vars() {
-            let predicate = trait_ref.without_const().to_predicate();
-            let cause = self.cause(traits::ProjectionWf(data));
-            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-    }
-
-    /// Pushes the obligations required for an array length to be WF
-    /// into `self.out`.
-    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
-        if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val {
-            assert!(promoted.is_none());
-
-            let obligations = self.nominal_obligations(def_id, substs);
-            self.out.extend(obligations);
-
-            let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
-            let cause = self.cause(traits::MiscObligation);
-            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
-        }
-    }
-
-    fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
-        if !subty.has_escaping_bound_vars() {
-            let cause = self.cause(cause);
-            let trait_ref = ty::TraitRef {
-                def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
-                substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
-            };
-            self.out.push(traits::Obligation::new(
-                cause,
-                self.param_env,
-                trait_ref.without_const().to_predicate(),
-            ));
-        }
-    }
-
-    /// Pushes new obligations into `out`. Returns `true` if it was able
-    /// to generate all the predicates needed to validate that `ty0`
-    /// is WF. Returns false if `ty0` is an unresolved type variable,
-    /// in which case we are not able to simplify at all.
-    fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
-        let mut subtys = ty0.walk();
-        let param_env = self.param_env;
-        while let Some(ty) = subtys.next() {
-            match ty.kind {
-                ty::Bool
-                | ty::Char
-                | ty::Int(..)
-                | ty::Uint(..)
-                | ty::Float(..)
-                | ty::Error
-                | ty::Str
-                | ty::GeneratorWitness(..)
-                | ty::Never
-                | ty::Param(_)
-                | ty::Bound(..)
-                | ty::Placeholder(..)
-                | ty::Foreign(..) => {
-                    // WfScalar, WfParameter, etc
-                }
-
-                ty::Slice(subty) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                }
-
-                ty::Array(subty, len) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                    self.compute_array_len(*len);
-                }
-
-                ty::Tuple(ref tys) => {
-                    if let Some((_last, rest)) = tys.split_last() {
-                        for elem in rest {
-                            self.require_sized(elem.expect_ty(), traits::TupleElem);
-                        }
-                    }
-                }
-
-                ty::RawPtr(_) => {
-                    // simple cases that are WF if their type args are WF
-                }
-
-                ty::Projection(data) => {
-                    subtys.skip_current_subtree(); // subtree handled by compute_projection
-                    self.compute_projection(data);
-                }
-
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-
-                ty::Adt(def, substs) => {
-                    // WfNominalType
-                    let obligations = self.nominal_obligations(def.did, substs);
-                    self.out.extend(obligations);
-                }
-
-                ty::FnDef(did, substs) => {
-                    let obligations = self.nominal_obligations(did, substs);
-                    self.out.extend(obligations);
-                }
-
-                ty::Ref(r, rty, _) => {
-                    // WfReference
-                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
-                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
-                        self.out.push(traits::Obligation::new(
-                            cause,
-                            param_env,
-                            ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
-                                rty, r,
-                            ))),
-                        ));
-                    }
-                }
-
-                ty::Generator(..) => {
-                    // Walk ALL the types in the generator: this will
-                    // include the upvar types as well as the yield
-                    // type. Note that this is mildly distinct from
-                    // the closure case, where we have to be careful
-                    // about the signature of the closure. We don't
-                    // have the problem of implied bounds here since
-                    // generators don't take arguments.
-                }
-
-                ty::Closure(def_id, substs) => {
-                    // Only check the upvar types for WF, not the rest
-                    // of the types within. This is needed because we
-                    // capture the signature and it may not be WF
-                    // without the implied bounds. Consider a closure
-                    // like `|x: &'a T|` -- it may be that `T: 'a` is
-                    // not known to hold in the creator's context (and
-                    // indeed the closure may not be invoked by its
-                    // creator, but rather turned to someone who *can*
-                    // verify that).
-                    //
-                    // The special treatment of closures here really
-                    // ought not to be necessary either; the problem
-                    // is related to #25860 -- there is no way for us
-                    // to express a fn type complete with the implied
-                    // bounds that it is assuming. I think in reality
-                    // the WF rules around fn are a bit messed up, and
-                    // that is the rot problem: `fn(&'a T)` should
-                    // probably always be WF, because it should be
-                    // shorthand for something like `where(T: 'a) {
-                    // fn(&'a T) }`, as discussed in #25860.
-                    //
-                    // Note that we are also skipping the generic
-                    // types. This is consistent with the `outlives`
-                    // code, but anyway doesn't matter: within the fn
-                    // body where they are created, the generics will
-                    // always be WF, and outside of that fn body we
-                    // are not directly inspecting closure types
-                    // anyway, except via auto trait matching (which
-                    // only inspects the upvar types).
-                    subtys.skip_current_subtree(); // subtree handled by compute_projection
-                    for upvar_ty in substs.as_closure().upvar_tys(def_id, self.infcx.tcx) {
-                        self.compute(upvar_ty);
-                    }
-                }
-
-                ty::FnPtr(_) => {
-                    // let the loop iterate into the argument/return
-                    // types appearing in the fn signature
-                }
-
-                ty::Opaque(did, substs) => {
-                    // all of the requirements on type parameters
-                    // should've been checked by the instantiation
-                    // of whatever returned this exact `impl Trait`.
-
-                    // for named opaque `impl Trait` types we still need to check them
-                    if ty::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
-                        let obligations = self.nominal_obligations(did, substs);
-                        self.out.extend(obligations);
-                    }
-                }
-
-                ty::Dynamic(data, r) => {
-                    // WfObject
-                    //
-                    // Here, we defer WF checking due to higher-ranked
-                    // regions. This is perhaps not ideal.
-                    self.from_object_ty(ty, data, r);
-
-                    // FIXME(#27579) RFC also considers adding trait
-                    // obligations that don't refer to Self and
-                    // checking those
-
-                    let defer_to_coercion = self.infcx.tcx.features().object_safe_for_dispatch;
-
-                    if !defer_to_coercion {
-                        let cause = self.cause(traits::MiscObligation);
-                        let component_traits = data.auto_traits().chain(data.principal_def_id());
-                        self.out.extend(component_traits.map(|did| {
-                            traits::Obligation::new(
-                                cause.clone(),
-                                param_env,
-                                ty::Predicate::ObjectSafe(did),
-                            )
-                        }));
-                    }
-                }
-
-                // Inference variables are the complicated case, since we don't
-                // know what type they are. We do two things:
-                //
-                // 1. Check if they have been resolved, and if so proceed with
-                //    THAT type.
-                // 2. If not, check whether this is the type that we
-                //    started with (ty0). In that case, we've made no
-                //    progress at all, so return false. Otherwise,
-                //    we've at least simplified things (i.e., we went
-                //    from `Vec<$0>: WF` to `$0: WF`, so we can
-                //    register a pending obligation and keep
-                //    moving. (Goal is that an "inductive hypothesis"
-                //    is satisfied to ensure termination.)
-                ty::Infer(_) => {
-                    let ty = self.infcx.shallow_resolve(ty);
-                    if let ty::Infer(_) = ty.kind {
-                        // not yet resolved...
-                        if ty == ty0 {
-                            // ...this is the type we started from! no progress.
-                            return false;
-                        }
-
-                        let cause = self.cause(traits::MiscObligation);
-                        self.out.push(
-                            // ...not the type we started from, so we made progress.
-                            traits::Obligation::new(
-                                cause,
-                                self.param_env,
-                                ty::Predicate::WellFormed(ty),
-                            ),
-                        );
-                    } else {
-                        // Yes, resolved, proceed with the
-                        // result. Should never return false because
-                        // `ty` is not a Infer.
-                        assert!(self.compute(ty));
-                    }
-                }
-            }
-        }
-
-        // if we made it through that loop above, we made progress!
-        return true;
-    }
-
-    fn nominal_obligations(
-        &mut self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-    ) -> Vec<traits::PredicateObligation<'tcx>> {
-        let predicates = self.infcx.tcx.predicates_of(def_id).instantiate(self.infcx.tcx, substs);
-        let cause = self.cause(traits::ItemObligation(def_id));
-        predicates
-            .predicates
-            .into_iter()
-            .map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred))
-            .filter(|pred| !pred.has_escaping_bound_vars())
-            .collect()
-    }
-
-    fn from_object_ty(
-        &mut self,
-        ty: Ty<'tcx>,
-        data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-        region: ty::Region<'tcx>,
-    ) {
-        // Imagine a type like this:
-        //
-        //     trait Foo { }
-        //     trait Bar<'c> : 'c { }
-        //
-        //     &'b (Foo+'c+Bar<'d>)
-        //         ^
-        //
-        // In this case, the following relationships must hold:
-        //
-        //     'b <= 'c
-        //     'd <= 'c
-        //
-        // The first conditions is due to the normal region pointer
-        // rules, which say that a reference cannot outlive its
-        // referent.
-        //
-        // The final condition may be a bit surprising. In particular,
-        // you may expect that it would have been `'c <= 'd`, since
-        // usually lifetimes of outer things are conservative
-        // approximations for inner things. However, it works somewhat
-        // differently with trait objects: here the idea is that if the
-        // user specifies a region bound (`'c`, in this case) it is the
-        // "master bound" that *implies* that bounds from other traits are
-        // all met. (Remember that *all bounds* in a type like
-        // `Foo+Bar+Zed` must be met, not just one, hence if we write
-        // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
-        // 'y.)
-        //
-        // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
-        // am looking forward to the future here.
-        if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
-            let implicit_bounds = object_region_bounds(self.infcx.tcx, data);
-
-            let explicit_bound = region;
-
-            self.out.reserve(implicit_bounds.len());
-            for implicit_bound in implicit_bounds {
-                let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
-                let outlives =
-                    ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound));
-                self.out.push(traits::Obligation::new(
-                    cause,
-                    self.param_env,
-                    outlives.to_predicate(),
-                ));
-            }
-        }
-    }
-}
-
-/// Given an object type like `SomeTrait + Send`, computes the lifetime
-/// bounds that must hold on the elided self type. These are derived
-/// from the declarations of `SomeTrait`, `Send`, and friends -- if
-/// they declare `trait SomeTrait : 'static`, for example, then
-/// `'static` would appear in the list. The hard work is done by
-/// `infer::required_region_bounds`, see that for more information.
-pub fn object_region_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
-) -> Vec<ty::Region<'tcx>> {
-    // Since we don't actually *know* the self type for an object,
-    // this "open(err)" serves as a kind of dummy standin -- basically
-    // a placeholder type.
-    let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
-
-    let predicates = existential_predicates
-        .iter()
-        .filter_map(|predicate| {
-            if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
-                None
-            } else {
-                Some(predicate.with_self_ty(tcx, open_ty))
-            }
-        })
-        .collect();
-
-    required_region_bounds(tcx, open_ty, predicates)
-}
-
-/// Find the span of a generic bound affecting an associated type.
-fn get_generic_bound_spans(
-    generics: &hir::Generics<'_>,
-    trait_name: Option<&Ident>,
-    assoc_item_name: Ident,
-) -> Vec<Span> {
-    let mut bounds = vec![];
-    for clause in generics.where_clause.predicates.iter() {
-        if let hir::WherePredicate::BoundPredicate(pred) = clause {
-            match &pred.bounded_ty.kind {
-                hir::TyKind::Path(hir::QPath::Resolved(Some(ty), path)) => {
-                    let mut s = path.segments.iter();
-                    if let (a, Some(b), None) = (s.next(), s.next(), s.next()) {
-                        if a.map(|s| &s.ident) == trait_name
-                            && b.ident == assoc_item_name
-                            && is_self_path(&ty.kind)
-                        {
-                            // `<Self as Foo>::Bar`
-                            bounds.push(pred.span);
-                        }
-                    }
-                }
-                hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
-                    if segment.ident == assoc_item_name {
-                        if is_self_path(&ty.kind) {
-                            // `Self::Bar`
-                            bounds.push(pred.span);
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-    }
-    bounds
-}
-
-fn is_self_path(kind: &hir::TyKind<'_>) -> bool {
-    match kind {
-        hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
-            let mut s = path.segments.iter();
-            if let (Some(segment), None) = (s.next(), s.next()) {
-                if segment.ident.name == kw::SelfUpper {
-                    // `type(Self)`
-                    return true;
-                }
-            }
-        }
-        _ => {}
-    }
-    false
-}