Skip to main content

rustc_trait_selection/traits/
coherence.rs

1//! See Rustc Dev Guide chapters on [trait-resolution] and [trait-specialization] for more info on
2//! how this works.
3//!
4//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
5//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
6
7use std::fmt::Debug;
8
9use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
10use rustc_errors::Diag;
11use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
12use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
13use rustc_infer::traits::{PredicateObligations, TraitErrors};
14use rustc_macros::{TypeFoldable, TypeVisitable};
15use rustc_middle::traits::query::NoSolution;
16use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
17use rustc_middle::traits::specialization_graph::OverlapMode;
18use rustc_middle::ty::fast_reject::DeepRejectCtxt;
19use rustc_middle::ty::{
20    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
21    Unnormalized,
22};
23pub use rustc_next_trait_solver::coherence::*;
24use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
25use rustc_span::{DUMMY_SP, Span, bug};
26use tracing::{debug, instrument, warn};
27
28use super::ObligationCtxt;
29use crate::error_reporting::traits::suggest_new_overflow_limit;
30use crate::infer::InferOk;
31use crate::solve::inspect::{InferCtxtProofTreeExt, InspectGoal, ProofTreeVisitor};
32use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect};
33use crate::traits::query::evaluate_obligation::InferCtxtExt;
34use crate::traits::select::IntercrateAmbiguityCause;
35use crate::traits::{
36    FulfillmentErrorCode, Obligation, ObligationCause, PredicateObligation, SkipLeakCheck, util,
37};
38
39/// The "header" of an impl is everything outside the body: a Self type, a trait
40/// ref (in the case of a trait impl), and a set of predicates (from the
41/// bounds / where-clauses).
42#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for ImplHeader<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        ImplHeader {
            impl_args: ::core::clone::Clone::clone(&self.impl_args),
            self_ty: ::core::clone::Clone::clone(&self.self_ty),
            trait_ref: ::core::clone::Clone::clone(&self.trait_ref),
            predicates: ::core::clone::Clone::clone(&self.predicates),
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ImplHeader<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "ImplHeader",
            "impl_args", &self.impl_args, "self_ty", &self.self_ty,
            "trait_ref", &self.trait_ref, "predicates", &&self.predicates)
    }
}Debug, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for ImplHeader<'tcx> {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        ImplHeader {
                            impl_args: __binding_0,
                            self_ty: __binding_1,
                            trait_ref: __binding_2,
                            predicates: __binding_3 } => {
                            ImplHeader {
                                impl_args: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                self_ty: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                                trait_ref: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_2,
                                        __folder)?,
                                predicates: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_3,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    ImplHeader {
                        impl_args: __binding_0,
                        self_ty: __binding_1,
                        trait_ref: __binding_2,
                        predicates: __binding_3 } => {
                        ImplHeader {
                            impl_args: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            self_ty: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
                                __folder),
                            trait_ref: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_2,
                                __folder),
                            predicates: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_3,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for ImplHeader<'tcx> {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    ImplHeader {
                        impl_args: ref __binding_0,
                        self_ty: ref __binding_1,
                        trait_ref: ref __binding_2,
                        predicates: ref __binding_3 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_2,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_3,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
43pub struct ImplHeader<'tcx> {
44    pub impl_args: ty::GenericArgsRef<'tcx>,
45    pub self_ty: Ty<'tcx>,
46    pub trait_ref: Option<ty::TraitRef<'tcx>>,
47    pub predicates: Vec<ty::Predicate<'tcx>>,
48}
49
50pub struct OverlapResult<'tcx> {
51    pub impl_header: ImplHeader<'tcx>,
52    pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
53
54    /// `true` if the overlap might've been permitted before the shift
55    /// to universes.
56    pub involves_placeholder: bool,
57
58    /// Used in the new solver to suggest increasing the recursion limit.
59    pub overflowing_predicates: Vec<ty::Predicate<'tcx>>,
60}
61
62pub fn add_placeholder_note(err: &mut Diag<'_>) {
63    err.note(
64        "this behavior recently changed as a result of a bug fix; \
65         see rust-lang/rust#56105 for details",
66    );
67}
68
69pub(crate) fn suggest_increasing_recursion_limit<'tcx>(
70    tcx: TyCtxt<'tcx>,
71    err: &mut Diag<'_>,
72    overflowing_predicates: &[ty::Predicate<'tcx>],
73) {
74    for pred in overflowing_predicates {
75        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("overflow evaluating the requirement `{0}`",
                pred))
    })format!("overflow evaluating the requirement `{}`", pred));
76    }
77
78    suggest_new_overflow_limit(tcx, err);
79}
80
81/// If there are types that satisfy both impls, returns `Some`
82/// with a suitably-freshened `ImplHeader` with those types
83/// instantiated. Otherwise, returns `None`.
84{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("overlapping_inherent_impls",
                                    "rustc_trait_selection::traits::coherence",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                    ::tracing_core::__macro_support::Option::Some(84u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl1_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl1_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl2_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl2_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("overlap_mode")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("overlap_mode");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl1_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl2_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&overlap_mode)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Option<OverlapResult<'_>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
            let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
            let may_overlap =
                DeepRejectCtxt::relate_infer_infer(tcx).types_may_unify(self_ty1,
                    self_ty2);
            if !may_overlap {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:101",
                                        "rustc_trait_selection::traits::coherence",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                        ::tracing_core::__macro_support::Option::Some(101u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                        ::tracing_core::field::FieldSet::new(&["message"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("overlapping_inherent_impls: fast_reject early-exit")
                                                            as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
                return None;
            }
            overlapping_impls(tcx, impl1_def_id, impl2_def_id,
                skip_leak_check, overlap_mode, false)
        }
    }
}#[instrument(skip(tcx, skip_leak_check), level = "debug")]
85pub fn overlapping_inherent_impls(
86    tcx: TyCtxt<'_>,
87    impl1_def_id: DefId,
88    impl2_def_id: DefId,
89    skip_leak_check: SkipLeakCheck,
90    overlap_mode: OverlapMode,
91) -> Option<OverlapResult<'_>> {
92    // Before doing expensive operations like entering an inference context, do
93    // a quick check via fast_reject to tell if the impl headers could possibly
94    // unify.
95    let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
96    let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
97    let may_overlap = DeepRejectCtxt::relate_infer_infer(tcx).types_may_unify(self_ty1, self_ty2);
98
99    if !may_overlap {
100        // Some types involved are definitely different, so the impls couldn't possibly overlap.
101        debug!("overlapping_inherent_impls: fast_reject early-exit");
102        return None;
103    }
104
105    overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, false)
106}
107
108/// If there are types that satisfy both impls, returns `Some`
109/// with a suitably-freshened `ImplHeader` with those types
110/// instantiated. Otherwise, returns `None`.
111{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("overlapping_trait_impls",
                                    "rustc_trait_selection::traits::coherence",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                    ::tracing_core::__macro_support::Option::Some(111u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl1_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl1_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl2_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl2_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("overlap_mode")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("overlap_mode");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl1_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl2_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&overlap_mode)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Option<OverlapResult<'_>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let impl1_args =
                tcx.impl_trait_ref(impl1_def_id).skip_binder().args;
            let impl2_args =
                tcx.impl_trait_ref(impl2_def_id).skip_binder().args;
            let may_overlap =
                DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args,
                    impl2_args);
            if !may_overlap {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:129",
                                        "rustc_trait_selection::traits::coherence",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                        ::tracing_core::__macro_support::Option::Some(129u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                        ::tracing_core::field::FieldSet::new(&["message"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("overlapping_impls: fast_reject early-exit")
                                                            as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
                return None;
            }
            overlapping_impls(tcx, impl1_def_id, impl2_def_id,
                skip_leak_check, overlap_mode, true)
        }
    }
}#[instrument(skip(tcx, skip_leak_check), level = "debug")]
112pub fn overlapping_trait_impls(
113    tcx: TyCtxt<'_>,
114    impl1_def_id: DefId,
115    impl2_def_id: DefId,
116    skip_leak_check: SkipLeakCheck,
117    overlap_mode: OverlapMode,
118) -> Option<OverlapResult<'_>> {
119    // Before doing expensive operations like entering an inference context, do
120    // a quick check via fast_reject to tell if the impl headers could possibly
121    // unify.
122    let impl1_args = tcx.impl_trait_ref(impl1_def_id).skip_binder().args;
123    let impl2_args = tcx.impl_trait_ref(impl2_def_id).skip_binder().args;
124    let may_overlap =
125        DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args);
126
127    if !may_overlap {
128        // Some types involved are definitely different, so the impls couldn't possibly overlap.
129        debug!("overlapping_impls: fast_reject early-exit");
130        return None;
131    }
132
133    overlapping_impls(tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, true)
134}
135
136fn overlapping_impls(
137    tcx: TyCtxt<'_>,
138    impl1_def_id: DefId,
139    impl2_def_id: DefId,
140    skip_leak_check: SkipLeakCheck,
141    overlap_mode: OverlapMode,
142    is_of_trait: bool,
143) -> Option<OverlapResult<'_>> {
144    overlap(tcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode, is_of_trait)
145}
146
147fn fresh_impl_header<'tcx>(
148    infcx: &InferCtxt<'tcx>,
149    impl_def_id: DefId,
150    is_of_trait: bool,
151) -> ImplHeader<'tcx> {
152    let tcx = infcx.tcx;
153    let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
154
155    ImplHeader {
156        impl_args,
157        self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(),
158        trait_ref: is_of_trait
159            .then(|| tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip()),
160        predicates: tcx
161            .clauses_of(impl_def_id)
162            .instantiate(tcx, impl_args)
163            .iter()
164            .map(|(c, _)| c.skip_norm_wip().as_predicate())
165            .collect(),
166    }
167}
168
169/// Can both impl `a` and impl `b` be satisfied by a common type (including
170/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
171{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("overlap",
                                    "rustc_trait_selection::traits::coherence",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                    ::tracing_core::__macro_support::Option::Some(171u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("skip_leak_check")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("skip_leak_check");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl1_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl1_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("impl2_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("impl2_def_id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("overlap_mode")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("overlap_mode");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("is_of_trait")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("is_of_trait");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&skip_leak_check)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl1_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl2_def_id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&overlap_mode)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&is_of_trait as
                                                            &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: Option<OverlapResult<'tcx>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if overlap_mode.use_negative_impl() {
                if impl_intersection_has_negative_obligation(tcx,
                            impl1_def_id, impl2_def_id, is_of_trait) ||
                        impl_intersection_has_negative_obligation(tcx, impl2_def_id,
                            impl1_def_id, is_of_trait) {
                    return None;
                }
            }
            let infcx =
                tcx.infer_ctxt().skip_leak_check(skip_leak_check.is_yes()).with_next_trait_solver(true).enable_next_solver_overflow_fcw(false).build(TypingMode::Coherence);
            let param_env = ty::ParamEnv::empty();
            let impl1_header =
                fresh_impl_header(&infcx, impl1_def_id, is_of_trait);
            let impl2_header =
                fresh_impl_header(&infcx, impl2_def_id, is_of_trait);
            let mut obligations =
                equate_impl_headers(&infcx, param_env, &impl1_header,
                        &impl2_header)?;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:212",
                                    "rustc_trait_selection::traits::coherence",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                    ::tracing_core::__macro_support::Option::Some(212u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                    ::tracing_core::field::FieldSet::new(&["message"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("overlap: unification check succeeded")
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            obligations.extend([&impl1_header.predicates,
                                    &impl2_header.predicates].into_iter().flatten().map(|&predicate|
                        Obligation::new(infcx.tcx, ObligationCause::dummy(),
                            param_env, predicate)));
            let mut overflowing_predicates = Vec::new();
            if overlap_mode.use_implicit_negative() {
                match impl_intersection_has_impossible_obligation(&infcx,
                        &obligations) {
                    IntersectionHasImpossibleObligations::Yes => return None,
                    IntersectionHasImpossibleObligations::No {
                        overflowing_predicates: p } => {
                        overflowing_predicates = p
                    }
                }
            }
            if infcx.leak_check(ty::UniverseIndex::ROOT, None).is_err() {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:233",
                                        "rustc_trait_selection::traits::coherence",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                        ::tracing_core::__macro_support::Option::Some(233u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                        ::tracing_core::field::FieldSet::new(&["message"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("overlap: leak check failed")
                                                            as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
                return None;
            }
            let intercrate_ambiguity_causes =
                if !overlap_mode.use_implicit_negative() {
                    Default::default()
                } else {
                    compute_intercrate_ambiguity_causes(&infcx, &obligations)
                };
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:243",
                                    "rustc_trait_selection::traits::coherence",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                    ::tracing_core::__macro_support::Option::Some(243u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                    ::tracing_core::field::FieldSet::new(&["message"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("overlap: intercrate_ambiguity_causes={0:#?}",
                                                                intercrate_ambiguity_causes) as
                                                        &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            let involves_placeholder =
                infcx.inner.borrow_mut().unwrap_region_constraints().legacy_data().constraints.iter().any(|c|
                        c.0.involves_placeholders());
            let mut impl_header =
                infcx.deeply_resolve_ignoring_regions(impl1_header);
            impl_header =
                deeply_normalize_for_diagnostics(&infcx, param_env,
                    impl_header);
            Some(OverlapResult {
                    impl_header,
                    intercrate_ambiguity_causes,
                    involves_placeholder,
                    overflowing_predicates,
                })
        }
    }
}#[instrument(level = "debug", skip(tcx))]
172fn overlap<'tcx>(
173    tcx: TyCtxt<'tcx>,
174    skip_leak_check: SkipLeakCheck,
175    impl1_def_id: DefId,
176    impl2_def_id: DefId,
177    overlap_mode: OverlapMode,
178    is_of_trait: bool,
179) -> Option<OverlapResult<'tcx>> {
180    if overlap_mode.use_negative_impl() {
181        if impl_intersection_has_negative_obligation(tcx, impl1_def_id, impl2_def_id, is_of_trait)
182            || impl_intersection_has_negative_obligation(
183                tcx,
184                impl2_def_id,
185                impl1_def_id,
186                is_of_trait,
187            )
188        {
189            return None;
190        }
191    }
192
193    let infcx = tcx
194        .infer_ctxt()
195        .skip_leak_check(skip_leak_check.is_yes())
196        .with_next_trait_solver(true)
197        .enable_next_solver_overflow_fcw(false)
198        .build(TypingMode::Coherence);
199
200    // For the purposes of this check, we don't bring any placeholder
201    // types into scope; instead, we replace the generic types with
202    // fresh type variables, and hence we do our evaluations in an
203    // empty environment.
204    let param_env = ty::ParamEnv::empty();
205
206    let impl1_header = fresh_impl_header(&infcx, impl1_def_id, is_of_trait);
207    let impl2_header = fresh_impl_header(&infcx, impl2_def_id, is_of_trait);
208
209    // Equate the headers to find their intersection (the general type, with infer vars,
210    // that may apply both impls).
211    let mut obligations = equate_impl_headers(&infcx, param_env, &impl1_header, &impl2_header)?;
212    debug!("overlap: unification check succeeded");
213
214    obligations.extend(
215        [&impl1_header.predicates, &impl2_header.predicates].into_iter().flatten().map(
216            |&predicate| Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate),
217        ),
218    );
219
220    let mut overflowing_predicates = Vec::new();
221    if overlap_mode.use_implicit_negative() {
222        match impl_intersection_has_impossible_obligation(&infcx, &obligations) {
223            IntersectionHasImpossibleObligations::Yes => return None,
224            IntersectionHasImpossibleObligations::No { overflowing_predicates: p } => {
225                overflowing_predicates = p
226            }
227        }
228    }
229
230    // We toggle the `leak_check` by using `skip_leak_check` when constructing the
231    // inference context, so this may be a noop.
232    if infcx.leak_check(ty::UniverseIndex::ROOT, None).is_err() {
233        debug!("overlap: leak check failed");
234        return None;
235    }
236
237    let intercrate_ambiguity_causes = if !overlap_mode.use_implicit_negative() {
238        Default::default()
239    } else {
240        compute_intercrate_ambiguity_causes(&infcx, &obligations)
241    };
242
243    debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
244    let involves_placeholder = infcx
245        .inner
246        .borrow_mut()
247        .unwrap_region_constraints()
248        // FIXME(-Zassumptions-on-binders): Handle solver_data
249        .legacy_data()
250        .constraints
251        .iter()
252        .any(|c| c.0.involves_placeholders());
253
254    let mut impl_header = infcx.deeply_resolve_ignoring_regions(impl1_header);
255
256    // Deeply normalize the impl header for diagnostics, ignoring any errors if this fails.
257    impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header);
258
259    Some(OverlapResult {
260        impl_header,
261        intercrate_ambiguity_causes,
262        involves_placeholder,
263        overflowing_predicates,
264    })
265}
266
267{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("equate_impl_headers",
                                "rustc_trait_selection::traits::coherence",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                ::tracing_core::__macro_support::Option::Some(267u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("param_env")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("param_env");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("impl1")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("impl1");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("impl2")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("impl2");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param_env)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl1)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&impl2)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return:
                                Option<PredicateObligations<'tcx>> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let result =
                            match (impl1.trait_ref, impl2.trait_ref) {
                                (Some(impl1_ref), Some(impl2_ref)) =>
                                    infcx.at(&ObligationCause::dummy(),
                                            param_env).eq(DefineOpaqueTypes::Yes, impl1_ref, impl2_ref),
                                (None, None) =>
                                    infcx.at(&ObligationCause::dummy(),
                                            param_env).eq(DefineOpaqueTypes::Yes, impl1.self_ty,
                                        impl2.self_ty),
                                _ =>
                                    ::rustc_span::macros::bug_impl(None,
                                        format_args!("equate_impl_headers given mismatched impl kinds"),
                                        Location::caller()),
                            };
                        result.map(|infer_ok| infer_ok.obligations).ok()
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:267",
                        "rustc_trait_selection::traits::coherence",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                        ::tracing_core::__macro_support::Option::Some(267u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(infcx), ret)]
268fn equate_impl_headers<'tcx>(
269    infcx: &InferCtxt<'tcx>,
270    param_env: ty::ParamEnv<'tcx>,
271    impl1: &ImplHeader<'tcx>,
272    impl2: &ImplHeader<'tcx>,
273) -> Option<PredicateObligations<'tcx>> {
274    let result =
275        match (impl1.trait_ref, impl2.trait_ref) {
276            (Some(impl1_ref), Some(impl2_ref)) => infcx
277                .at(&ObligationCause::dummy(), param_env)
278                .eq(DefineOpaqueTypes::Yes, impl1_ref, impl2_ref),
279            (None, None) => infcx.at(&ObligationCause::dummy(), param_env).eq(
280                DefineOpaqueTypes::Yes,
281                impl1.self_ty,
282                impl2.self_ty,
283            ),
284            _ => bug!("equate_impl_headers given mismatched impl kinds"),
285        };
286
287    result.map(|infer_ok| infer_ok.obligations).ok()
288}
289
290/// The result of [fn impl_intersection_has_impossible_obligation].
291#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for IntersectionHasImpossibleObligations<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Yes => ::core::fmt::Formatter::write_str(f, "Yes"),
            Self::No { overflowing_predicates: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "No",
                    "overflowing_predicates", &__self_0),
        }
    }
}Debug)]
292enum IntersectionHasImpossibleObligations<'tcx> {
293    Yes,
294    No {
295        /// With the next solver, some obligations may
296        /// fail if only the user increased the recursion limit.
297        ///
298        /// We return those obligations here and mention them in the
299        /// error message.
300        overflowing_predicates: Vec<ty::Predicate<'tcx>>,
301    },
302}
303
304/// Check if both impls can be satisfied by a common type by considering whether
305/// any of either impl's obligations is not known to hold.
306///
307/// For example, given these two impls:
308///     `impl From<MyLocalType> for Box<dyn Error>` (in my crate)
309///     `impl<E> From<E> for Box<dyn Error> where E: Error` (in libstd)
310///
311/// After replacing both impl headers with inference vars (which happens before
312/// this function is called), we get:
313///     `Box<dyn Error>: From<MyLocalType>`
314///     `Box<dyn Error>: From<?E>`
315///
316/// This gives us `?E = MyLocalType`. We then certainly know that `MyLocalType: Error`
317/// never holds in intercrate mode since a local impl does not exist, and a
318/// downstream impl cannot be added -- therefore can consider the intersection
319/// of the two impls above to be empty.
320///
321/// Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
322{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
            ::tracing::Level::DEBUG <=
                ::tracing::level_filters::LevelFilter::current() || { false }
    {
    __tracing_attr_span =
        {
            use ::tracing::__macro_support::Callsite as _;
            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                {
                    static META: ::tracing::Metadata<'static> =
                        {
                            ::tracing_core::metadata::Metadata::new("impl_intersection_has_impossible_obligation",
                                "rustc_trait_selection::traits::coherence",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                                ::tracing_core::__macro_support::Option::Some(322u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("obligations")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("obligations");
                                                    NAME.as_str()
                                                }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                ::tracing::metadata::Kind::SPAN)
                        };
                    ::tracing::callsite::DefaultCallsite::new(&META)
                };
            let mut interest = ::tracing::subscriber::Interest::never();
            if ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        { interest = __CALLSITE.interest(); !interest.is_never() }
                    &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest) {
                let meta = __CALLSITE.metadata();
                ::tracing::Span::new(meta,
                    &{
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligations)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[allow(unknown_lints, unreachable_code, clippy ::
                    diverging_sub_expression, clippy :: empty_loop, clippy ::
                    let_unit_value, clippy :: let_with_type_underscore, clippy
                    :: needless_return, clippy :: unreachable)]
                    if false {
                        let __tracing_attr_fake_return:
                                IntersectionHasImpossibleObligations<'tcx> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        if !obligations.iter().all(|o|
                                        {
                                            <&SolverDelegate<'tcx>>::from(infcx).root_goal_may_hold_with_depth(8,
                                                Goal::new(infcx.tcx, o.param_env, o.predicate))
                                        }) {
                            return IntersectionHasImpossibleObligations::Yes;
                        }
                        let ocx = ObligationCtxt::new(infcx);
                        ocx.register_obligations(obligations.iter().cloned());
                        let hard_errors = ocx.try_evaluate_obligations();
                        if let TraitErrors::HasErrors(hard_errors) = hard_errors {
                            if !hard_errors.iter().all(|e| e.is_true_error()) {
                                {
                                    ::core::panicking::panic_fmt(format_args!("should not have detected ambiguity during first pass"));
                                }
                            };
                            return IntersectionHasImpossibleObligations::Yes;
                        }
                        let ambiguities = ocx.into_pending_obligations();
                        let ocx = ObligationCtxt::new_with_diagnostics(infcx);
                        ocx.register_obligations(ambiguities);
                        let errors_and_ambiguities =
                            ocx.evaluate_obligations_error_on_ambiguity();
                        let (errors, ambiguities): (Vec<_>, Vec<_>) =
                            errors_and_ambiguities.into_iter().partition(|error|
                                    error.is_true_error());
                        if !errors.is_empty() {
                            {
                                ::core::panicking::panic_fmt(format_args!("should not have ambiguities during second pass"));
                            }
                        };
                        IntersectionHasImpossibleObligations::No {
                            overflowing_predicates: ambiguities.into_iter().filter(|error|
                                            {

                                                #[allow(non_exhaustive_omitted_patterns)]
                                                match error.code {
                                                    FulfillmentErrorCode::Ambiguity { overflow: Some(true) } =>
                                                        true,
                                                    _ => false,
                                                }
                                            }).map(|e|
                                        infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)).collect(),
                        }
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:322",
                        "rustc_trait_selection::traits::coherence",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                        ::tracing_core::__macro_support::Option::Some(322u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(infcx), ret)]
323fn impl_intersection_has_impossible_obligation<'a, 'tcx>(
324    infcx: &InferCtxt<'tcx>,
325    obligations: &'a [PredicateObligation<'tcx>],
326) -> IntersectionHasImpossibleObligations<'tcx> {
327    // A fast path optimization, try evaluating all goals with
328    // a very low recursion depth and bail if any of them don't
329    // hold.
330    if !obligations.iter().all(|o| {
331        <&SolverDelegate<'tcx>>::from(infcx)
332            .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate))
333    }) {
334        return IntersectionHasImpossibleObligations::Yes;
335    }
336
337    let ocx = ObligationCtxt::new(infcx);
338    ocx.register_obligations(obligations.iter().cloned());
339    let hard_errors = ocx.try_evaluate_obligations();
340    if let TraitErrors::HasErrors(hard_errors) = hard_errors {
341        assert!(
342            hard_errors.iter().all(|e| e.is_true_error()),
343            "should not have detected ambiguity during first pass"
344        );
345        return IntersectionHasImpossibleObligations::Yes;
346    }
347
348    // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer
349    // `FulfillmentError`. This is so that we can detect overflowing obligations
350    // without needing to run the `BestObligation` visitor on true errors.
351    let ambiguities = ocx.into_pending_obligations();
352    let ocx = ObligationCtxt::new_with_diagnostics(infcx);
353    ocx.register_obligations(ambiguities);
354    let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity();
355    // We only care about the obligations that are *definitely* true errors.
356    // Ambiguities do not prove the disjointness of two impls.
357    let (errors, ambiguities): (Vec<_>, Vec<_>) =
358        errors_and_ambiguities.into_iter().partition(|error| error.is_true_error());
359    assert!(errors.is_empty(), "should not have ambiguities during second pass");
360
361    IntersectionHasImpossibleObligations::No {
362        overflowing_predicates: ambiguities
363            .into_iter()
364            .filter(|error| {
365                matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) })
366            })
367            .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate))
368            .collect(),
369    }
370}
371
372/// Check if both impls can be satisfied by a common type by considering whether
373/// any of first impl's obligations is known not to hold *via a negative predicate*.
374///
375/// For example, given these two impls:
376///     `struct MyCustomBox<T: ?Sized>(Box<T>);`
377///     `impl From<&str> for MyCustomBox<dyn Error>` (in my crate)
378///     `impl<E> From<E> for MyCustomBox<dyn Error> where E: Error` (in my crate)
379///
380/// After replacing the second impl's header with inference vars, we get:
381///     `MyCustomBox<dyn Error>: From<&str>`
382///     `MyCustomBox<dyn Error>: From<?E>`
383///
384/// This gives us `?E = &str`. We then try to prove the first impl's predicates
385/// after negating, giving us `&str: !Error`. This is a negative impl provided by
386/// libstd, and therefore we can guarantee for certain that libstd will never add
387/// a positive impl for `&str: Error` (without it being a breaking change).
388fn impl_intersection_has_negative_obligation(
389    tcx: TyCtxt<'_>,
390    impl1_def_id: DefId,
391    impl2_def_id: DefId,
392    is_of_trait: bool,
393) -> bool {
394    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:394",
                        "rustc_trait_selection::traits::coherence",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                        ::tracing_core::__macro_support::Option::Some(394u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("negative_impl(impl1_def_id={0:?}, impl2_def_id={1:?})",
                                                    impl1_def_id, impl2_def_id) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
395
396    // N.B. We need to unify impl headers *with* `TypingMode::Coherence`,
397    // even if proving negative predicates doesn't need `TypingMode::Coherence`.
398    let ref infcx = tcx
399        .infer_ctxt()
400        .with_next_trait_solver(true)
401        .enable_next_solver_overflow_fcw(false)
402        .build(TypingMode::Coherence);
403    let root_universe = infcx.universe();
404    {
    match (&root_universe, &ty::UniverseIndex::ROOT) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(root_universe, ty::UniverseIndex::ROOT);
405
406    let impl1_header = fresh_impl_header(infcx, impl1_def_id, is_of_trait);
407    let impl2_header = fresh_impl_header(infcx, impl2_def_id, is_of_trait);
408
409    // Equate the headers to find their intersection (the general type, with infer vars,
410    // that may apply both impls).
411    let Some(equate_obligations) =
412        equate_impl_headers(infcx, ty::ParamEnv::empty(), &impl1_header, &impl2_header)
413    else {
414        return false;
415    };
416
417    // FIXME(with_negative_coherence): the infcx has constraints from equating
418    // the impl headers. We should use these constraints as assumptions, not as
419    // requirements, when proving the negated where clauses below.
420    drop(equate_obligations);
421    drop(infcx.take_registered_region_obligations());
422    drop(infcx.take_registered_region_assumptions());
423    drop(infcx.take_and_reset_region_constraints());
424
425    plug_infer_with_placeholders(
426        infcx,
427        root_universe,
428        (impl1_header.impl_args, impl2_header.impl_args),
429    );
430
431    // Right above we plug inference variables with placeholders,
432    // this gets us new impl1_header_args with the inference variables actually resolved
433    // to those placeholders.
434    let impl1_header_args = infcx.deeply_resolve_ignoring_regions(impl1_header.impl_args);
435    // So there are no infer variables left now, except regions which aren't resolved by
436    // `deeply_resolve_ignoring_regions`.
437    if !!impl1_header_args.has_non_region_infer() {
    ::core::panicking::panic("assertion failed: !impl1_header_args.has_non_region_infer()")
};assert!(!impl1_header_args.has_non_region_infer());
438
439    let param_env = ty::EarlyBinder::bind(tcx, tcx.param_env(impl1_def_id))
440        .instantiate(tcx, impl1_header_args)
441        .skip_norm_wip();
442
443    util::elaborate(
444        tcx,
445        tcx.clauses_of(impl2_def_id)
446            .instantiate(tcx, impl2_header.impl_args)
447            .into_iter()
448            .map(|(c, s)| (c.skip_norm_wip(), s)),
449    )
450    .elaborate_sized()
451    .any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
452}
453
454fn plug_infer_with_placeholders<'tcx>(
455    infcx: &InferCtxt<'tcx>,
456    universe: ty::UniverseIndex,
457    value: impl TypeVisitable<TyCtxt<'tcx>>,
458) {
459    struct PlugInferWithPlaceholder<'a, 'tcx> {
460        infcx: &'a InferCtxt<'tcx>,
461        universe: ty::UniverseIndex,
462        var: ty::BoundVar,
463    }
464
465    impl<'tcx> PlugInferWithPlaceholder<'_, 'tcx> {
466        fn next_var(&mut self) -> ty::BoundVar {
467            let var = self.var;
468            self.var = self.var + 1;
469            var
470        }
471    }
472
473    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlugInferWithPlaceholder<'_, 'tcx> {
474        fn visit_ty(&mut self, ty: Ty<'tcx>) {
475            let ty = self.infcx.shallow_resolve(ty);
476            if ty.is_ty_var() {
477                let Ok(InferOk { value: (), obligations }) =
478                    self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
479                        // Comparing against a type variable never registers hidden types anyway
480                        DefineOpaqueTypes::Yes,
481                        ty,
482                        Ty::new_placeholder(
483                            self.infcx.tcx,
484                            ty::PlaceholderType::new(
485                                self.universe,
486                                ty::BoundTy { var: self.next_var(), kind: ty::BoundTyKind::Anon },
487                            ),
488                        ),
489                    )
490                else {
491                    ::rustc_span::macros::bug_impl(None,
    format_args!("we always expect to be able to plug an infer var with placeholder"),
    Location::caller())bug!("we always expect to be able to plug an infer var with placeholder")
492                };
493                {
    match (&obligations.len(), &0) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(obligations.len(), 0);
494            } else {
495                ty.super_visit_with(self);
496            }
497        }
498
499        fn visit_const(&mut self, ct: ty::Const<'tcx>) {
500            let ct = self.infcx.shallow_resolve_const(ct);
501            if ct.is_ct_infer() {
502                let Ok(InferOk { value: (), obligations }) =
503                    self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
504                        // The types of the constants are the same, so there is no hidden type
505                        // registration happening anyway.
506                        DefineOpaqueTypes::Yes,
507                        ct,
508                        ty::Const::new_placeholder(
509                            self.infcx.tcx,
510                            ty::PlaceholderConst::new(
511                                self.universe,
512                                ty::BoundConst::new(self.next_var()),
513                            ),
514                        ),
515                    )
516                else {
517                    ::rustc_span::macros::bug_impl(None,
    format_args!("we always expect to be able to plug an infer var with placeholder"),
    Location::caller())bug!("we always expect to be able to plug an infer var with placeholder")
518                };
519                {
    match (&obligations.len(), &0) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(obligations.len(), 0);
520            } else {
521                ct.super_visit_with(self);
522            }
523        }
524
525        fn visit_region(&mut self, r: ty::Region<'tcx>) {
526            if let ty::ReVar(vid) = r.kind() {
527                let r = self
528                    .infcx
529                    .inner
530                    .borrow_mut()
531                    .unwrap_region_constraints()
532                    .shallow_resolve_region_var(self.infcx.tcx, vid);
533                if r.is_var() {
534                    let Ok(InferOk { value: (), obligations }) =
535                        self.infcx.at(&ObligationCause::dummy(), ty::ParamEnv::empty()).eq(
536                            // Lifetimes don't contain opaque types (or any types for that matter).
537                            DefineOpaqueTypes::Yes,
538                            r,
539                            ty::Region::new_placeholder(
540                                self.infcx.tcx,
541                                ty::PlaceholderRegion::new(
542                                    self.universe,
543                                    ty::BoundRegion {
544                                        var: self.next_var(),
545                                        kind: ty::BoundRegionKind::Anon,
546                                    },
547                                ),
548                            ),
549                        )
550                    else {
551                        ::rustc_span::macros::bug_impl(None,
    format_args!("we always expect to be able to plug an infer var with placeholder"),
    Location::caller())bug!("we always expect to be able to plug an infer var with placeholder")
552                    };
553                    {
    match (&obligations.len(), &0) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(obligations.len(), 0);
554                }
555            }
556        }
557    }
558
559    value.visit_with(&mut PlugInferWithPlaceholder { infcx, universe, var: ty::BoundVar::ZERO });
560}
561
562fn try_prove_negated_where_clause<'tcx>(
563    root_infcx: &InferCtxt<'tcx>,
564    clause: ty::Clause<'tcx>,
565    param_env: ty::ParamEnv<'tcx>,
566) -> bool {
567    let Some(negative_predicate) = clause.as_predicate().flip_polarity(root_infcx.tcx) else {
568        return false;
569    };
570
571    // N.B. We don't need to use intercrate mode here because we're trying to prove
572    // the *existence* of a negative goal, not the non-existence of a positive goal.
573    // Without this, we over-eagerly register coherence ambiguity candidates when
574    // impl candidates do exist.
575    // FIXME(#132279): `TypingMode::non_body_analysis` is a bit questionable here as it
576    // would cause us to reveal opaque types to leak their auto traits.
577    let ref infcx = root_infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
578    let ocx = ObligationCtxt::new(infcx);
579    ocx.register_obligation(Obligation::new(
580        infcx.tcx,
581        ObligationCause::dummy(),
582        param_env,
583        negative_predicate,
584    ));
585    if !ocx.evaluate_obligations_error_on_ambiguity().no_errors() {
586        return false;
587    }
588
589    // FIXME: We could use the assumed_wf_types from both impls, I think,
590    // if that wasn't implemented just for LocalDefId, and we'd need to do
591    // the normalization ourselves since this is totally fallible...
592    ocx.resolve_regions(CRATE_DEF_ID, param_env, []).is_empty()
593}
594
595/// Compute the `intercrate_ambiguity_causes` for the new solver using
596/// "proof trees".
597///
598/// This is a bit scuffed but seems to be good enough, at least
599/// when looking at UI tests. Given that it is only used to improve
600/// diagnostics this is good enough. We can always improve it once there
601/// are test cases where it is currently not enough.
602fn compute_intercrate_ambiguity_causes<'tcx>(
603    infcx: &InferCtxt<'tcx>,
604    obligations: &[PredicateObligation<'tcx>],
605) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
606    let mut causes: FxIndexSet<IntercrateAmbiguityCause<'tcx>> = Default::default();
607
608    for obligation in obligations {
609        search_ambiguity_causes(infcx, obligation.as_goal(), &mut causes);
610    }
611
612    causes
613}
614
615struct AmbiguityCausesVisitor<'a, 'tcx> {
616    cache: FxHashSet<Goal<'tcx, ty::Predicate<'tcx>>>,
617    causes: &'a mut FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
618}
619
620impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
621    fn span(&self) -> Span {
622        DUMMY_SP
623    }
624
625    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) {
626        if !self.cache.insert(goal.goal()) {
627            return;
628        }
629
630        let infcx = goal.infcx();
631        for cand in goal.candidates() {
632            cand.visit_nested_in_probe(self);
633        }
634        // When searching for intercrate ambiguity causes, we only need to look
635        // at ambiguous goals, as for others the coherence unknowable candidate
636        // was irrelevant.
637        match goal.result() {
638            Ok(Certainty::Yes) | Err(NoSolution) => return,
639            Ok(Certainty::Maybe(_)) => {}
640        }
641
642        // For bound predicates we simply call `infcx.enter_forall`
643        // and then prove the resulting predicate as a nested goal.
644        let Goal { param_env, predicate } = goal.goal();
645        let predicate_kind = goal.infcx().enter_forall_and_leak_universe(predicate.kind());
646        let trait_ref = match predicate_kind {
647            ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.trait_ref,
648            ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))
649                if proj.projection_term.kind.is_trait_projection() =>
650            {
651                proj.projection_term.trait_ref(infcx.tcx)
652            }
653            _ => return,
654        };
655
656        if trait_ref.references_error() {
657            return;
658        }
659
660        let mut candidates = goal.candidates();
661
662        // We also look for unknowable candidates. In case a goal is unknowable, there's
663        // always exactly 1 candidate.
664        let Some(cand) = candidates.pop() else {
665            return;
666        };
667
668        let inspect::ProbeKind::TraitCandidate {
669            source: CandidateSource::CoherenceUnknowable,
670            result: Ok(_),
671        } = cand.kind()
672        else {
673            return;
674        };
675
676        let lazily_normalize_ty = |mut ty: Ty<'tcx>| {
677            if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Alias(..) => true,
    _ => false,
}matches!(ty.kind(), ty::Alias(..)) {
678                let ocx = ObligationCtxt::new(infcx);
679                ty = ocx
680                    .structurally_normalize_ty(
681                        &ObligationCause::dummy(),
682                        param_env,
683                        Unnormalized::new_wip(ty),
684                    )
685                    .map_err(|_| ())?;
686                if !ocx.try_evaluate_obligations().no_errors() {
687                    return Err(());
688                }
689            }
690            Ok(ty)
691        };
692
693        infcx.probe(|_| {
694            let conflict = match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) {
695                Err(()) => return,
696                Ok(Ok(())) => {
697                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs:697",
                        "rustc_trait_selection::traits::coherence",
                        ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/traits/coherence.rs"),
                        ::tracing_core::__macro_support::Option::Some(697u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::coherence"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("expected an unknowable trait ref: {0:?}",
                                                    trait_ref) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};warn!("expected an unknowable trait ref: {trait_ref:?}");
698                    return;
699                }
700                Ok(Err(conflict)) => conflict,
701            };
702
703            // It is only relevant that a goal is unknowable if it would have otherwise
704            // failed.
705            // FIXME(#132279): Forking with `TypingMode::non_body_analysis` is a bit questionable
706            // as it would allow us to reveal opaque types, potentially causing unexpected
707            // cycles.
708            let non_intercrate_infcx = infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
709            if non_intercrate_infcx.predicate_may_hold(&Obligation::new(
710                infcx.tcx,
711                ObligationCause::dummy(),
712                param_env,
713                predicate,
714            )) {
715                return;
716            }
717
718            // Normalize the trait ref for diagnostics, ignoring any errors if this fails.
719            let trait_ref = deeply_normalize_for_diagnostics(infcx, param_env, trait_ref);
720            let self_ty = trait_ref.self_ty();
721            let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);
722            self.causes.insert(match conflict {
723                Conflict::Upstream => {
724                    IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty }
725                }
726                Conflict::Downstream => {
727                    IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty }
728                }
729            });
730        });
731    }
732}
733
734fn search_ambiguity_causes<'tcx>(
735    infcx: &InferCtxt<'tcx>,
736    goal: Goal<'tcx, ty::Predicate<'tcx>>,
737    causes: &mut FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
738) {
739    infcx.probe(|_| {
740        infcx.visit_proof_tree(
741            goal,
742            &mut AmbiguityCausesVisitor { cache: Default::default(), causes },
743        )
744    });
745}