//! Support code for rustdoc and external tools . You really don't
//! want to be using this unless you need to.

use super::*;

use std::collections::hash_map::Entry;
use std::collections::VecDeque;

use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};

use crate::ty::fold::TypeFolder;
use crate::ty::{Region, RegionVid};

// 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 names_map: FxHashSet<String>,
    pub vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
}

pub struct AutoTraitFinder<'a, 'tcx: 'a> {
    tcx: &'a TyCtxt<'a, 'tcx, 'tcx>,
}

impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
    pub fn new(tcx: &'a TyCtxt<'a, 'tcx, '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,
        did: DefId,
        trait_did: DefId,
        generics: &ty::Generics,
        auto_trait_callback: impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>, AutoTraitInfo<'i>) -> A,
    ) -> AutoTraitResult<A> {
        let tcx = self.tcx;
        let ty = self.tcx.type_of(did);

        let orig_params = tcx.param_env(did);

        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_params,
                trait_pred.to_poly_trait_predicate(),
            ));

            match result {
                Ok(Some(Vtable::VtableImpl(_))) => {
                    debug!(
                        "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \
                         manual impl found, bailing out",
                        did, trait_did, generics
                    );
                    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,
                did,
                trait_did,
                ty,
                orig_params.clone(),
                orig_params,
                &mut fresh_preds,
                false,
            ) {
                Some(e) => e,
                None => return AutoTraitResult::NegativeImpl,
            };

            let (full_env, full_user_env) = self.evaluate_predicates(
                &mut infcx,
                did,
                trait_did,
                ty,
                new_env.clone(),
                user_env,
                &mut fresh_preds,
                true,
            ).unwrap_or_else(|| {
                panic!(
                    "Failed to fully process: {:?} {:?} {:?}",
                    ty, trait_did, orig_params
                )
            });

            debug!(
                "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): fulfilling \
                 with {:?}",
                did, trait_did, generics, 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 names_map: FxHashSet<String> = generics
                .params
                .iter()
                .filter_map(|param| match param.kind {
                    ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
                    _ => None,
                })
                .collect();

            let body_id_map: FxHashMap<_, _> = infcx
                .region_obligations
                .borrow()
                .iter()
                .map(|&(id, _)| (id, vec![]))
                .collect();

            infcx.process_registered_region_obligations(&body_id_map, None, full_env.clone());

            let region_data = infcx
                .borrow_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,
                names_map,
                vid_to_region,
            };

            return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info));
        });
    }
}

impl<'a, 'tcx> AutoTraitFinder<'a, '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 Iteratpr 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.
    pub fn evaluate_predicates<'b, 'gcx, 'c>(
        &self,
        infcx: &InferCtxt<'b, 'tcx, 'c>,
        ty_did: DefId,
        trait_did: DefId,
        ty: ty::Ty<'c>,
        param_env: ty::ParamEnv<'c>,
        user_env: ty::ParamEnv<'c>,
        fresh_preds: &mut FxHashSet<ty::Predicate<'c>>,
        only_projections: bool,
    ) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
        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.clone();
        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.clone()) {
                continue;
            }

            // Call infcx.resolve_type_vars_if_possible to see if we can
            // get rid of any inference variables.
            let obligation = infcx.resolve_type_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) == hir::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.clone()),
                        );
                        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.clone().into_iter().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_did={:?}, trait_did={:?}): succeeded with '{:?}' \
             '{:?}'",
            ty_did, 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 ther 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);
        }
    }

    pub fn region_name(&self, region: Region<'_>) -> Option<String> {
        match region {
            &ty::ReEarlyBound(r) => Some(r.name.to_string()),
            _ => None,
        }
    }

    pub fn get_lifetime(&self, region: Region<'_>,
                        names_map: &FxHashMap<String, String>) -> String {
        self.region_name(region)
            .map(|name|
                names_map.get(&name).unwrap_or_else(||
                    panic!("Missing lifetime with name {:?} for {:?}", name, region)
                )
            )
            .cloned()
            .unwrap_or_else(|| "'static".to_owned())
    }

    // 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
    pub 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").clone();
            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.sty {
            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().sty {
            ty::Projection(proj) if proj == p.skip_binder().projection_ty => {
                true
            },
            _ => false
        }
    }

    pub fn evaluate_nested_obligations<
        'b,
        'c,
        'd,
        'cx,
        T: Iterator<Item = Obligation<'cx, ty::Predicate<'cx>>>,
    >(
        &self,
        ty: ty::Ty<'_>,
        nested: T,
        computed_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
        fresh_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
        predicates: &'b mut VecDeque<ty::PolyTraitPredicate<'cx>>,
        select: &mut SelectionContext<'c, 'd, 'cx>,
        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.clone()))
        {
            let is_new_pred =
                fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone()));

            // Resolve any inference variables that we can, to help selection succeed
            predicate = select.infcx().resolve_type_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(ref 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.clone());
                }
                &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().is_ty_infer()
                        && 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);
                            }
                    }

                    // We can only call poly_project_and_unify_type when our predicate's
                    // Ty contains an inference variable - otherwise, there won't be anything to
                    // unify
                    if p.ty().skip_binder().has_infer_types() {
                        debug!("Projecting and unifying projection predicate {:?}",
                               predicate);
                        match poly_project_and_unify_type(select, &obligation.with(p.clone())) {
                            Err(e) => {
                                debug!(
                                    "evaluate_nested_obligations: Unable to unify predicate \
                                     '{:?}' '{:?}', bailing out",
                                    ty, e
                                );
                                return false;
                            }
                            Ok(Some(v)) => {
                                if !self.evaluate_nested_obligations(
                                    ty,
                                    v.clone().iter().cloned(),
                                    computed_preds,
                                    fresh_preds,
                                    predicates,
                                    select,
                                    only_projections,
                                ) {
                                    return false;
                                }
                            }
                            Ok(None) => {
                                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.types.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<'c, 'd, 'cx>(
        &self,
        infcx: &InferCtxt<'c, 'd, 'cx>,
        p: ty::Predicate<'cx>,
    ) -> ty::Predicate<'cx> {
        infcx.freshen(p)
    }
}

// Replaces all ReVars in a type with ty::Region's, using the provided map
pub struct RegionReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, '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))
    }
}
