<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use infer::InferCtxt;
use ty::subst::Substs;
use traits;
use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use std::iter::once;
use syntax::ast;
use syntax_pos::Span;
use middle::lang_items;

/// 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, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                   param_env: ty::ParamEnv<'tcx>,
                                   body_id: ast::NodeId,
                                   ty: Ty<'tcx>,
                                   span: Span)
                                   -> Option<Vec<traits::PredicateObligation<'tcx>>>
{
    let mut wf = WfPredicates { infcx,
                                param_env,
                                body_id,
                                span,
                                out: vec![] };
    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, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                         param_env: ty::ParamEnv<'tcx>,
                                         body_id: ast::NodeId,
                                         trait_ref: &ty::TraitRef<'tcx>,
                                         span: Span)
                                         -> Vec<traits::PredicateObligation<'tcx>>
{
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
    wf.compute_trait_ref(trait_ref);
    wf.normalize()
}

pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                             param_env: ty::ParamEnv<'tcx>,
                                             body_id: ast::NodeId,
                                             predicate: &ty::Predicate<'tcx>,
                                             span: Span)
                                             -> Vec<traits::PredicateObligation<'tcx>>
{
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };

    // (*) 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); // (*)
        }
        ty::Predicate::Equate(ref t) => {
            wf.compute(t.skip_binder().0);
            wf.compute(t.skip_binder().1);
        }
        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); // (*)
        }
    }

    wf.normalize()
}

struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    body_id: ast::NodeId,
    span: Span,
    out: Vec<traits::PredicateObligation<'tcx>>,
}

impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, '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;
        self.out.iter()
                .inspect(|pred| assert!(!pred.has_escaping_regions()))
                .flat_map(|pred| {
                    let mut selcx = traits::SelectionContext::new(infcx);
                    let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
                    once(pred.value).chain(pred.obligations)
                })
                .collect()
    }

    /// Pushes the obligations required for `trait_ref` to be WF into
    /// `self.out`.
    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
        self.out.extend(obligations);

        let cause = self.cause(traits::MiscObligation);
        let param_env = self.param_env;
        self.out.extend(
            trait_ref.substs.types()
                            .filter(|ty| !ty.has_escaping_regions())
                            .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);

        if !data.has_escaping_regions() {
            let predicate = trait_ref.to_predicate();
            let cause = self.cause(traits::ProjectionWf(data));
            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
        }
    }
<commit_msg>Fix for the supertrait example in #43784<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use infer::InferCtxt;
use ty::subst::Substs;
use traits;
use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use std::iter::once;
use syntax::ast;
use syntax_pos::Span;
use middle::lang_items;

/// 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, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                   param_env: ty::ParamEnv<'tcx>,
                                   body_id: ast::NodeId,
                                   ty: Ty<'tcx>,
                                   span: Span)
                                   -> Option<Vec<traits::PredicateObligation<'tcx>>>
{
    let mut wf = WfPredicates { infcx,
                                param_env,
                                body_id,
                                span,
                                out: vec![] };
    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, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                         param_env: ty::ParamEnv<'tcx>,
                                         body_id: ast::NodeId,
                                         trait_ref: &ty::TraitRef<'tcx>,
                                         span: Span)
                                         -> Vec<traits::PredicateObligation<'tcx>>
{
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
    wf.compute_trait_ref(trait_ref);
    wf.normalize()
}

pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                             param_env: ty::ParamEnv<'tcx>,
                                             body_id: ast::NodeId,
                                             predicate: &ty::Predicate<'tcx>,
                                             span: Span)
                                             -> Vec<traits::PredicateObligation<'tcx>>
{
    let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };

    // (*) 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); // (*)
        }
        ty::Predicate::Equate(ref t) => {
            wf.compute(t.skip_binder().0);
            wf.compute(t.skip_binder().1);
        }
        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); // (*)
        }
    }

    wf.normalize()
}

struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    body_id: ast::NodeId,
    span: Span,
    out: Vec<traits::PredicateObligation<'tcx>>,
}

impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, '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;
        self.out.iter()
                .inspect(|pred| assert!(!pred.has_escaping_regions()))
                .flat_map(|pred| {
                    let mut selcx = traits::SelectionContext::new(infcx);
                    let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
                    once(pred.value).chain(pred.obligations)
                })
                .collect()
    }

    /// Pushes the obligations required for `trait_ref` to be WF into
    /// `self.out`.
    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
        let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
        self.out.extend(obligations);

        let cause = self.cause(traits::MiscObligation);
        let param_env = self.param_env;

        let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, vec![
            ty::Predicate::Trait(ty::Binder(
                ty::TraitPredicate { trait_ref: *trait_ref }
            ))
        ]);
        let implied_obligations = implied_obligations.map(|pred| {
            traits::Obligation::new(cause.clone(), param_env, pred)
        });
        self.out.extend(implied_obligations);

        self.out.extend(
            trait_ref.substs.types()
                            .filter(|ty| !ty.has_escaping_regions())
                            .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);

        if !data.has_escaping_regions() {
            let predicate = trait_ref.to_predicate();
            let cause = self.cause(traits::ProjectionWf(data));
            self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
        }
    }

{'fraction_non_alphanumeric': 0.1416725228390724, 'fraction_numerical': 0.0027406886858749122, 'mean_word_length': 1.8314763231197773, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 60, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2187210', 'n_tokens_mistral': 4380, 'n_tokens_neox': 4348, 'n_words': 963}