// Copyright 2014 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.

//! "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 hir::def_id::DefId;
use lint;
use traits::{self, Obligation, ObligationCause};
use ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
use ty::subst::{Subst, Substs};
use std::borrow::Cow;
use std::iter::{self};
use syntax::ast::{self, Name};
use syntax_pos::Span;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObjectSafetyViolation {
    /// Self : Sized declared on the trait
    SizedSelf,

    /// Supertrait reference references `Self` an in illegal location
    /// (e.g. `trait Foo : Bar<Self>`)
    SupertraitSelf,

    /// Method has something illegal
    Method(ast::Name, MethodViolationCode),

    /// Associated const
    AssociatedConst(ast::Name),
}

impl ObjectSafetyViolation {
    pub fn error_msg(&self) -> Cow<'static, str> {
        match *self {
            ObjectSafetyViolation::SizedSelf =>
                "the trait cannot require that `Self : Sized`".into(),
            ObjectSafetyViolation::SupertraitSelf =>
                "the trait cannot use `Self` as a type parameter \
                 in the supertraits or where-clauses".into(),
            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
                format!("method `{}` has no receiver", name).into(),
            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
                format!("method `{}` references the `Self` type \
                         in its arguments or return type", name).into(),
            ObjectSafetyViolation::Method(name,
                                            MethodViolationCode::WhereClauseReferencesSelf(_)) =>
                format!("method `{}` references the `Self` type in where clauses", name).into(),
            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
                format!("method `{}` has generic type parameters", name).into(),
            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
                format!("method `{}`'s receiver cannot be dispatched on", name).into(),
            ObjectSafetyViolation::AssociatedConst(name) =>
                format!("the trait cannot contain associated consts like `{}`", name).into(),
        }
    }
}

/// Reasons a method might not be object-safe.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MethodViolationCode {
    /// e.g., `fn foo()`
    StaticMethod,

    /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
    ReferencesSelf,

    /// e.g. `fn foo(&self) where Self: Clone`
    WhereClauseReferencesSelf(Span),

    /// e.g., `fn foo<A>()`
    Generic,

    /// the method's receiver (`self` argument) can't be dispatched on
    UndispatchableReceiver,
}

impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {

    /// 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(self, trait_def_id: DefId)
                                            -> Vec<ObjectSafetyViolation>
    {
        let violations = traits::supertrait_def_ids(self, trait_def_id)
            .filter(|&def_id| self.predicates_reference_self(def_id, true))
            .map(|_| ObjectSafetyViolation::SupertraitSelf)
            .collect();

        debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}",
               trait_def_id,
               violations);

        violations
    }

    pub fn object_safety_violations(self, trait_def_id: DefId)
                                    -> Vec<ObjectSafetyViolation>
    {
        debug!("object_safety_violations: {:?}", trait_def_id);

        traits::supertrait_def_ids(self, trait_def_id)
            .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
            .collect()
    }

    fn object_safety_violations_for_trait(self, trait_def_id: DefId)
                                          -> Vec<ObjectSafetyViolation>
    {
        // Check methods for violations.
        let mut violations: Vec<_> = self.associated_items(trait_def_id)
            .filter(|item| item.kind == ty::AssociatedKind::Method)
            .filter_map(|item|
                self.object_safety_violation_for_method(trait_def_id, &item)
                    .map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
            ).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.
                    self.lint_node_note(
                        lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
                        ast::CRATE_NODE_ID,
                        *span,
                        &format!("the trait `{}` cannot be made into an object",
                                 self.item_path_str(trait_def_id)),
                        &violation.error_msg());
                    false
                } else {
                    true
                }
            }).collect();

        // Check the trait itself.
        if self.trait_has_sized_self(trait_def_id) {
            violations.push(ObjectSafetyViolation::SizedSelf);
        }
        if self.predicates_reference_self(trait_def_id, false) {
            violations.push(ObjectSafetyViolation::SupertraitSelf);
        }

        violations.extend(self.associated_items(trait_def_id)
            .filter(|item| item.kind == ty::AssociatedKind::Const)
            .map(|item| ObjectSafetyViolation::AssociatedConst(item.ident.name)));

        debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
               trait_def_id,
               violations);

        violations
    }

    fn predicates_reference_self(
        self,
        trait_def_id: DefId,
        supertraits_only: bool) -> bool
    {
        let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
        let predicates = if supertraits_only {
            self.super_predicates_of(trait_def_id)
        } else {
            self.predicates_of(trait_def_id)
        };
        predicates
            .predicates
            .iter()
            .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref))
            .any(|predicate| {
                match predicate {
                    ty::Predicate::Trait(ref data) => {
                        // In the case of a trait predicate, we can skip the "self" type.
                        data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
                    }
                    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.
                        data.skip_binder()
                            .projection_ty
                            .trait_ref(self)
                            .input_types()
                            .skip(1)
                            .any(|t| t.has_self_ty())
                    }
                    ty::Predicate::WellFormed(..) |
                    ty::Predicate::ObjectSafe(..) |
                    ty::Predicate::TypeOutlives(..) |
                    ty::Predicate::RegionOutlives(..) |
                    ty::Predicate::ClosureKind(..) |
                    ty::Predicate::Subtype(..) |
                    ty::Predicate::ConstEvaluatable(..) => {
                        false
                    }
                }
            })
    }

    fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
        self.generics_require_sized_self(trait_def_id)
    }

    fn generics_require_sized_self(self, def_id: DefId) -> bool {
        let sized_def_id = match self.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 = self.predicates_of(def_id);
        let predicates = predicates.instantiate_identity(self).predicates;
        elaborate_predicates(self, predicates)
            .any(|predicate| match predicate {
                ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
                    trait_pred.skip_binder().self_ty().is_self()
                }
                ty::Predicate::Projection(..) |
                ty::Predicate::Trait(..) |
                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(self,
                                          trait_def_id: DefId,
                                          method: &ty::AssociatedItem)
                                          -> Option<MethodViolationCode>
    {
        // Any method that has a `Self : Sized` requisite is otherwise
        // exempt from the regulations.
        if self.generics_require_sized_self(method.def_id) {
            return None;
        }

        self.virtual_call_violation_for_method(trait_def_id, method)
    }

    /// 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(self,
                                 trait_def_id: DefId,
                                 method: &ty::AssociatedItem)
                                 -> bool
    {
        // Any method that has a `Self : Sized` requisite can't be called.
        if self.generics_require_sized_self(method.def_id) {
            return false;
        }

        match self.virtual_call_violation_for_method(trait_def_id, method) {
            None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
            Some(_) => false,
        }
    }

    /// 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(self,
                                         trait_def_id: DefId,
                                         method: &ty::AssociatedItem)
                                         -> Option<MethodViolationCode>
    {
        // The method's first parameter must be named `self`
        if !method.method_has_self_argument {
            return Some(MethodViolationCode::StaticMethod);
        }

        let sig = self.fn_sig(method.def_id);

        for input_ty in &sig.skip_binder().inputs()[1..] {
            if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                return Some(MethodViolationCode::ReferencesSelf);
            }
        }
        if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
            return Some(MethodViolationCode::ReferencesSelf);
        }

        // We can't monomorphize things like `fn foo<A>(...)`.
        if self.generics_of(method.def_id).own_counts().types != 0 {
            return Some(MethodViolationCode::Generic);
        }

        if self.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| self.contains_illegal_self_type_reference(trait_def_id, t)) {
            let span = self.def_span(method.def_id);
            return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
        }

        let receiver_ty = self.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 != self.mk_self_type() {
            if !self.receiver_is_dispatchable(method, receiver_ty) {
                return Some(MethodViolationCode::UndispatchableReceiver);
            } else {
                // sanity check to make sure the receiver actually has the layout of a pointer

                use ty::layout::Abi;

                let param_env = self.param_env(method.def_id);

                let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
                    match self.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 = self.receiver_for_self_ty(
                    receiver_ty, self.mk_unit(), method.def_id
                );

                match abi_of_ty(unit_receiver_ty) {
                    &Abi::Scalar(..) => (),
                    abi => bug!("Receiver when Self = () should have a Scalar ABI, found {:?}", abi)
                }

                let trait_object_ty = self.object_ty_for_trait(
                    trait_def_id, self.mk_region(ty::ReStatic)
                );

                // e.g. Rc<dyn Trait>
                let trait_object_receiver = self.receiver_for_self_ty(
                    receiver_ty, trait_object_ty, method.def_id
                );

                match abi_of_ty(trait_object_receiver) {
                    &Abi::ScalarPair(..) => (),
                    abi => bug!(
                        "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`
    /// e.g. for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`
    fn receiver_for_self_ty(
        self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
    ) -> Ty<'tcx> {
        let substs = Substs::for_item(self, method_def_id, |param, _| {
            if param.index == 0 {
                self_ty.into()
            } else {
                self.mk_param_from_def(param)
            }
        });

        receiver_ty.subst(self, substs)
    }

    /// 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(self, 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(self, trait_def_id);

        let trait_predicate = ty::ExistentialPredicate::Trait(
            ty::ExistentialTraitRef::erase_self_ty(self, trait_ref)
        );

        let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
            .flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
            .filter(|item| item.kind == ty::AssociatedKind::Type)
            .collect::<Vec<_>>();

        // existential predicates need to be in a specific order
        associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id));

        let projection_predicates = associated_types.into_iter().map(|item| {
            ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
                ty: self.mk_projection(item.def_id, trait_ref.substs),
                item_def_id: item.def_id,
                substs: trait_ref.substs,
            })
        });

        let existential_predicates = self.mk_existential_predicates(
            iter::once(trait_predicate).chain(projection_predicates)
        );

        let object_ty = self.mk_dynamic(
            ty::Binder::dummy(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. So 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(
        self,
        method: &ty::AssociatedItem,
        receiver_ty: Ty<'tcx>,
    ) -> bool {
        debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);

        let traits = (self.lang_items().unsize_trait(),
                      self.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, and we should replace it when real forall queries
        // are implemented
        let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
            ::std::u32::MAX,
            Name::intern("RustaceansAreAwesome").as_interned_str(),
        );

        // `Receiver[Self => U]`
        let unsized_receiver_ty = self.receiver_for_self_ty(
            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 = self.param_env(method.def_id);

            // Self: Unsize<U>
            let unsize_predicate = ty::TraitRef {
                def_id: unsize_did,
                substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
            }.to_predicate();

            // U: Trait<Arg1, ..., ArgN>
            let trait_predicate = {
                let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
                    if param.index == 0 {
                        unsized_self_ty.into()
                    } else {
                        self.mk_param_from_def(param)
                    }
                });

                ty::TraitRef {
                    def_id: unsize_did,
                    substs,
                }.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 = self.intern_predicates(&caller_bounds);

            param_env
        };

        // Receiver: DispatchFromDyn<Receiver[Self => U]>
        let obligation = {
            let predicate = ty::TraitRef {
                def_id: dispatch_from_dyn_did,
                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
            }.to_predicate();

            Obligation::new(
                ObligationCause::dummy(),
                param_env,
                predicate,
            )
        };

        self.infer_ctxt().enter(|ref infcx| {
            // the receiver is dispatchable iff the obligation holds
            infcx.predicate_must_hold(&obligation)
        })
    }

    fn contains_illegal_self_type_reference(self,
                                            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;
        ty.maybe_walk(|ty| {
            match ty.sty {
                ty::Param(ref param_ty) => {
                    if param_ty.is_self() {
                        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(self, trait_def_id),
                        );
                        supertraits = Some(traits::supertraits(self, 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(self));
                    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(super) fn is_object_safe_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                trait_def_id: DefId) -> bool {
    tcx.object_safety_violations(trait_def_id).is_empty()
}
