Skip to main content

rustc_trait_selection/error_reporting/traits/
ambiguity.rs

1use std::ops::ControlFlow;
2
3use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err};
4use rustc_hir as hir;
5use rustc_hir::LangItem;
6use rustc_hir::def::{DefKind, Res};
7use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
8use rustc_hir::intravisit::Visitor as _;
9use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
10use rustc_infer::traits::util::elaborate;
11use rustc_infer::traits::{
12    Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation,
13};
14use rustc_middle::ty::print::PrintPolyTraitPredicateExt;
15use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _};
16use rustc_session::parse::feature_err_unstable_feature_bound;
17use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
18use tracing::{debug, instrument};
19
20use crate::error_reporting::TypeErrCtxt;
21use crate::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
22use crate::error_reporting::traits::{FindExprBySpan, to_pretty_impl_header};
23use crate::traits::ObligationCtxt;
24use crate::traits::query::evaluate_obligation::InferCtxtExt;
25
26#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CandidateSource {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CandidateSource::DefId(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "DefId",
                    &__self_0),
            CandidateSource::ParamEnv(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ParamEnv", &__self_0),
        }
    }
}Debug)]
27pub enum CandidateSource {
28    DefId(DefId),
29    ParamEnv(Span),
30}
31
32pub fn compute_applicable_impls_for_diagnostics<'tcx>(
33    infcx: &InferCtxt<'tcx>,
34    obligation: &PolyTraitObligation<'tcx>,
35) -> Vec<CandidateSource> {
36    let tcx = infcx.tcx;
37    let param_env = obligation.param_env;
38
39    let predicate_polarity = obligation.predicate.skip_binder().polarity;
40
41    let impl_may_apply = |impl_def_id| {
42        let ocx = ObligationCtxt::new(infcx);
43        infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
44            let obligation_trait_ref = ocx.normalize(
45                &ObligationCause::dummy(),
46                param_env,
47                placeholder_obligation.trait_ref,
48            );
49
50            let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
51            let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args);
52            let impl_trait_ref =
53                ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
54
55            if let Err(_) =
56                ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
57            {
58                return false;
59            }
60
61            let impl_trait_header = tcx.impl_trait_header(impl_def_id);
62            let impl_polarity = impl_trait_header.polarity;
63
64            match (impl_polarity, predicate_polarity) {
65                (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
66                | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {}
67                _ => return false,
68            }
69
70            let obligations = tcx
71                .predicates_of(impl_def_id)
72                .instantiate(tcx, impl_args)
73                .into_iter()
74                .map(|(predicate, _)| {
75                    Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
76                })
77                // Kinda hacky, but let's just throw away obligations that overflow.
78                // This may reduce the accuracy of this check (if the obligation guides
79                // inference or it actually resulted in error after others are processed)
80                // ... but this is diagnostics code.
81                .filter(|obligation| {
82                    infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok()
83                });
84            ocx.register_obligations(obligations);
85
86            ocx.try_evaluate_obligations().is_empty()
87        })
88    };
89
90    let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
91        let ocx = ObligationCtxt::new(infcx);
92        infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
93            let obligation_trait_ref = ocx.normalize(
94                &ObligationCause::dummy(),
95                param_env,
96                placeholder_obligation.trait_ref,
97            );
98
99            let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
100                DUMMY_SP,
101                BoundRegionConversionTime::HigherRankedType,
102                poly_trait_predicate,
103            );
104            let param_env_trait_ref =
105                ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
106
107            if let Err(_) = ocx.eq(
108                &ObligationCause::dummy(),
109                param_env,
110                obligation_trait_ref,
111                param_env_trait_ref,
112            ) {
113                return false;
114            }
115
116            ocx.try_evaluate_obligations().is_empty()
117        })
118    };
119
120    let mut ambiguities = Vec::new();
121
122    tcx.for_each_relevant_impl(
123        obligation.predicate.def_id(),
124        obligation.predicate.skip_binder().trait_ref.self_ty(),
125        |impl_def_id| {
126            if infcx.probe(|_| impl_may_apply(impl_def_id)) {
127                ambiguities.push(CandidateSource::DefId(impl_def_id))
128            }
129        },
130    );
131
132    // If our `body_id` has been set (and isn't just from a dummy obligation cause),
133    // then try to look for a param-env clause that would apply. The way we compute
134    // this is somewhat manual, since we need the spans, so we elaborate this directly
135    // from `predicates_of` rather than actually looking at the param-env which
136    // otherwise would be more appropriate.
137    let body_id = obligation.cause.body_id;
138    if body_id != CRATE_DEF_ID {
139        let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
140        for (pred, span) in elaborate(tcx, predicates.into_iter()) {
141            let kind = pred.kind();
142            if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
143                && param_env_candidate_may_apply(kind.rebind(trait_pred))
144            {
145                if kind.rebind(trait_pred.trait_ref)
146                    == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
147                {
148                    ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
149                } else {
150                    ambiguities.push(CandidateSource::ParamEnv(span))
151                }
152            }
153        }
154    }
155
156    ambiguities
157}
158
159impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
160    #[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("maybe_report_ambiguity",
                                    "rustc_trait_selection::error_reporting::traits::ambiguity",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
                                    ::tracing_core::__macro_support::Option::Some(160u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
                                    ::tracing_core::field::FieldSet::new(&["obligation"],
                                        ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation)
                                                            as &dyn 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: ErrorGuaranteed = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let predicate =
                self.resolve_vars_if_possible(obligation.predicate);
            let span = obligation.cause.span;
            let mut long_ty_path = None;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs:174",
                                    "rustc_trait_selection::error_reporting::traits::ambiguity",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
                                    ::tracing_core::__macro_support::Option::Some(174u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
                                    ::tracing_core::field::FieldSet::new(&["predicate",
                                                    "obligation.cause.code"],
                                        ::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};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&predicate)
                                                        as &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&obligation.cause.code())
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            let bound_predicate = predicate.kind();
            let mut err =
                match bound_predicate.skip_binder() {
                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
                        let trait_pred = bound_predicate.rebind(data);
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs:183",
                                                "rustc_trait_selection::error_reporting::traits::ambiguity",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
                                                ::tracing_core::__macro_support::Option::Some(183u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
                                                ::tracing_core::field::FieldSet::new(&["trait_pred"],
                                                    ::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};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&trait_pred)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        if let Err(e) = predicate.error_reported() { return e; }
                        if let Err(guar) =
                                self.tcx.ensure_result().coherent_trait(trait_pred.def_id())
                            {
                            return guar;
                        }
                        if #[allow(non_exhaustive_omitted_patterns)] match self.tcx.as_lang_item(trait_pred.def_id())
                                {
                                Some(LangItem::Sized | LangItem::MetaSized) => true,
                                _ => false,
                            } {
                            return match self.tainted_by_errors() {
                                    None =>
                                        self.emit_inference_failure_err(obligation.cause.body_id,
                                                span, trait_pred.self_ty().skip_binder().into(),
                                                TypeAnnotationNeeded::E0282, false).emit(),
                                    Some(e) => e,
                                };
                        }
                        let term =
                            data.trait_ref.args.iter().filter_map(ty::GenericArg::as_term).find(|s|
                                    s.has_non_region_infer());
                        let mut err =
                            if let Some(term) = term {
                                let candidates: Vec<_> =
                                    self.tcx.all_impls(trait_pred.def_id()).filter_map(|def_id|
                                                {
                                                    let imp = self.tcx.impl_trait_header(def_id);
                                                    if imp.polarity != ty::ImplPolarity::Positive ||
                                                            !self.tcx.is_user_visible_dep(def_id.krate) {
                                                        return None;
                                                    }
                                                    let imp = imp.trait_ref.skip_binder();
                                                    if imp.with_replaced_self_ty(self.tcx,
                                                                trait_pred.skip_binder().self_ty()) ==
                                                            trait_pred.skip_binder().trait_ref {
                                                        Some(imp.self_ty())
                                                    } else { None }
                                                }).collect();
                                self.emit_inference_failure_err_with_type_hint(obligation.cause.body_id,
                                    span, term, TypeAnnotationNeeded::E0283, true,
                                    match &candidates[..] {
                                        [candidate] => Some(*candidate),
                                        _ => None,
                                    })
                            } else {
                                {
                                        self.dcx().struct_span_err(span,
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("type annotations needed: cannot satisfy `{0}`",
                                                                self.tcx.short_string(predicate, &mut long_ty_path)))
                                                    })).with_code(E0283)
                                    }.with_long_ty_path(long_ty_path)
                            };
                        let mut ambiguities =
                            compute_applicable_impls_for_diagnostics(self.infcx,
                                &obligation.with(self.tcx, trait_pred));
                        let has_non_region_infer =
                            trait_pred.skip_binder().trait_ref.args.types().any(|t|
                                    !t.is_ty_or_numeric_infer());
                        if ambiguities.len() > 5 {
                            let infcx = self.infcx;
                            if !ambiguities.iter().all(|option|
                                            match option {
                                                CandidateSource::DefId(did) =>
                                                    infcx.tcx.generics_of(*did).count() == 0,
                                                CandidateSource::ParamEnv(_) => true,
                                            }) {
                                ambiguities.retain(|option|
                                        match option {
                                            CandidateSource::DefId(did) =>
                                                infcx.tcx.generics_of(*did).count() == 0,
                                            CandidateSource::ParamEnv(_) => true,
                                        });
                            }
                        }
                        if ambiguities.len() > 1 && ambiguities.len() < 10 &&
                                has_non_region_infer {
                            if let Some(e) = self.tainted_by_errors() && term.is_none()
                                {
                                err.cancel();
                                return e;
                            }
                            self.annotate_source_of_ambiguity(&mut err, &ambiguities,
                                predicate);
                        } else {
                            if let Some(e) = self.tainted_by_errors() {
                                err.cancel();
                                return e;
                            }
                            if let Some(clause) = predicate.as_trait_clause() &&
                                    let ty::Infer(_) = clause.self_ty().skip_binder().kind() {
                                let tr =
                                    self.tcx.short_string(clause.print_modifiers_and_trait_path(),
                                        &mut err.long_ty_path());
                                err.note(::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("the type must implement `{0}`",
                                                    tr))
                                        }));
                            } else {
                                let pred =
                                    self.tcx.short_string(predicate, &mut err.long_ty_path());
                                err.note(::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
                                                    pred))
                                        }));
                            }
                            let impl_candidates =
                                self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
                            if impl_candidates.len() < 40 {
                                self.report_similar_impl_candidates(impl_candidates.as_slice(),
                                    trait_pred, obligation.cause.body_id, &mut err, false,
                                    obligation.param_env);
                            }
                        }
                        if let ObligationCauseCode::WhereClause(def_id, _) |
                                ObligationCauseCode::WhereClauseInExpr(def_id, ..) =
                                *obligation.cause.code() {
                            self.suggest_fully_qualified_path(&mut err, def_id, span,
                                trait_pred.def_id());
                        }
                        if term.is_some_and(|term| term.as_type().is_some()) &&
                                let Some(body) =
                                    self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) {
                            let mut expr_finder = FindExprBySpan::new(span, self.tcx);
                            expr_finder.visit_expr(&body.value);
                            if let Some(hir::Expr {
                                                    kind: hir::ExprKind::Call(hir::Expr {
                                                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
                                                        .. }, _) |
                                                        hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. })
                                                    = expr_finder.result &&
                                                let [.., trait_path_segment @ hir::PathSegment {
                                                    res: Res::Def(DefKind::Trait, trait_id), .. },
                                                    hir::PathSegment {
                                                    ident: assoc_item_ident, res: Res::Def(_, item_id), .. }] =
                                                    path.segments && data.trait_ref.def_id == *trait_id &&
                                        self.tcx.trait_of_assoc(*item_id) == Some(*trait_id) &&
                                    let None = self.tainted_by_errors() {
                                let assoc_item = self.tcx.associated_item(*item_id);
                                let (verb, noun) =
                                    match assoc_item.kind {
                                        ty::AssocKind::Const { .. } => ("refer to the", "constant"),
                                        ty::AssocKind::Fn { .. } => ("call", "function"),
                                        ty::AssocKind::Type { .. } => ("refer to the", "type"),
                                    };
                                err.cancel();
                                err =
                                    self.dcx().struct_span_err(span,
                                        ::alloc::__export::must_use({
                                                ::alloc::fmt::format(format_args!("cannot {0} associated {1} on trait without specifying the corresponding `impl` type",
                                                        verb, noun))
                                            }));
                                err.code(E0790);
                                if item_id.is_local() {
                                    let trait_ident = self.tcx.item_name(*trait_id);
                                    err.span_label(self.tcx.def_span(*item_id),
                                        ::alloc::__export::must_use({
                                                ::alloc::fmt::format(format_args!("`{0}::{1}` defined here",
                                                        trait_ident, assoc_item_ident))
                                            }));
                                }
                                err.span_label(span,
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("cannot {0} associated {1} of trait",
                                                    verb, noun))
                                        }));
                                let trait_impls =
                                    self.tcx.trait_impls_of(data.trait_ref.def_id);
                                if let Some(&impl_def_id) =
                                        trait_impls.non_blanket_impls().values().flatten().next() {
                                    let non_blanket_impl_count =
                                        trait_impls.non_blanket_impls().values().flatten().count();
                                    let (message, self_types) =
                                        if non_blanket_impl_count == 1 {
                                            ("use the fully-qualified path to the only available \
                                     implementation",
                                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                        [::alloc::__export::must_use({
                                                                        ::alloc::fmt::format(format_args!("{0}",
                                                                                self.tcx.type_of(impl_def_id).instantiate_identity()))
                                                                    })])))
                                        } else if non_blanket_impl_count < 20 {
                                            ("use a fully-qualified path to one of the available \
                                     implementations",
                                                trait_impls.non_blanket_impls().values().flatten().map(|&id|
                                                            {
                                                                ::alloc::__export::must_use({
                                                                        ::alloc::fmt::format(format_args!("{0}",
                                                                                self.tcx.type_of(id).instantiate_identity()))
                                                                    })
                                                            }).collect::<Vec<String>>())
                                        } else {
                                            ("use a fully-qualified path to a specific available \
                                     implementation",
                                                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                        ["/* self type */".to_string()])))
                                        };
                                    let suggestions: Vec<_> =
                                        self_types.into_iter().map(|self_type|
                                                    {
                                                        let mut suggestions =
                                                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                                                                    [(path.span.shrink_to_lo(),
                                                                                ::alloc::__export::must_use({
                                                                                        ::alloc::fmt::format(format_args!("<{0} as ", self_type))
                                                                                    }))]));
                                                        if let Some(generic_arg) = trait_path_segment.args {
                                                            let between_span =
                                                                trait_path_segment.ident.span.between(generic_arg.span_ext);
                                                            suggestions.push((between_span, "".to_string()));
                                                            suggestions.push((generic_arg.span_ext.shrink_to_hi(),
                                                                    ">".to_string()));
                                                        } else {
                                                            suggestions.push((trait_path_segment.ident.span.shrink_to_hi(),
                                                                    ">".to_string()));
                                                        }
                                                        suggestions
                                                    }).collect();
                                    err.multipart_suggestions(message, suggestions,
                                        Applicability::MaybeIncorrect);
                                }
                            }
                        };
                        err
                    }
                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term))
                        => {
                        if let Err(e) = term.error_reported() { return e; }
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        self.emit_inference_failure_err(obligation.cause.body_id,
                            span, term, TypeAnnotationNeeded::E0282, false)
                    }
                    ty::PredicateKind::Subtype(data) => {
                        if let Err(e) = data.error_reported() { return e; }
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        let ty::SubtypePredicate { a_is_expected: _, a, b } = data;
                        if !(a.is_ty_var() && b.is_ty_var()) {
                            ::core::panicking::panic("assertion failed: a.is_ty_var() && b.is_ty_var()")
                        };
                        self.emit_inference_failure_err(obligation.cause.body_id,
                            span, a.into(), TypeAnnotationNeeded::E0282, true)
                    }
                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(data))
                        => {
                        if let Err(e) = predicate.error_reported() { return e; }
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        if let Err(guar) =
                                self.tcx.ensure_result().coherent_trait(self.tcx.parent(data.projection_term.def_id))
                            {
                            return guar;
                        }
                        let term =
                            data.projection_term.args.iter().filter_map(ty::GenericArg::as_term).chain([data.term]).find(|g|
                                    g.has_non_region_infer());
                        let predicate =
                            self.tcx.short_string(predicate, &mut long_ty_path);
                        if let Some(term) = term {
                            self.emit_inference_failure_err(obligation.cause.body_id,
                                        span, term, TypeAnnotationNeeded::E0284,
                                        true).with_note(::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
                                                    predicate))
                                        })).with_long_ty_path(long_ty_path)
                        } else {
                            {
                                        self.dcx().struct_span_err(span,
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("type annotations needed: cannot satisfy `{0}`",
                                                                predicate))
                                                    })).with_code(E0284)
                                    }.with_span_label(span,
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
                                                    predicate))
                                        })).with_long_ty_path(long_ty_path)
                        }
                    }
                    ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data))
                        => {
                        if let Err(e) = predicate.error_reported() { return e; }
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        let term =
                            data.walk().filter_map(ty::GenericArg::as_term).find(|term|
                                    term.is_infer());
                        if let Some(term) = term {
                            self.emit_inference_failure_err(obligation.cause.body_id,
                                span, term, TypeAnnotationNeeded::E0284, true)
                        } else {
                            let predicate =
                                self.tcx.short_string(predicate, &mut long_ty_path);
                            {
                                        self.dcx().struct_span_err(span,
                                                ::alloc::__export::must_use({
                                                        ::alloc::fmt::format(format_args!("type annotations needed: cannot satisfy `{0}`",
                                                                predicate))
                                                    })).with_code(E0284)
                                    }.with_span_label(span,
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
                                                    predicate))
                                        })).with_long_ty_path(long_ty_path)
                        }
                    }
                    ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct,
                        ..)) =>
                        self.emit_inference_failure_err(obligation.cause.body_id,
                            span, ct.into(), TypeAnnotationNeeded::E0284, true),
                    ty::PredicateKind::NormalizesTo(ty::NormalizesTo {
                        alias, term }) if term.is_infer() => {
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        let alias = self.tcx.short_string(alias, &mut long_ty_path);
                        {
                                    self.dcx().struct_span_err(span,
                                            ::alloc::__export::must_use({
                                                    ::alloc::fmt::format(format_args!("type annotations needed: cannot normalize `{0}`",
                                                            alias))
                                                })).with_code(E0284)
                                }.with_span_label(span,
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("cannot normalize `{0}`",
                                                alias))
                                    })).with_long_ty_path(long_ty_path)
                    }
                    ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym))
                        => {
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        if self.tcx.features().staged_api() {
                            self.dcx().struct_span_err(span,
                                    ::alloc::__export::must_use({
                                            ::alloc::fmt::format(format_args!("unstable feature `{0}` is used without being enabled.",
                                                    sym))
                                        })).with_help(::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({0})]`",
                                                sym))
                                    }))
                        } else {
                            feature_err_unstable_feature_bound(&self.tcx.sess, sym,
                                span,
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("use of unstable library feature `{0}`",
                                                sym))
                                    }))
                        }
                    }
                    _ => {
                        if let Some(e) = self.tainted_by_errors() { return e; }
                        let predicate =
                            self.tcx.short_string(predicate, &mut long_ty_path);
                        {
                                    self.dcx().struct_span_err(span,
                                            ::alloc::__export::must_use({
                                                    ::alloc::fmt::format(format_args!("type annotations needed: cannot satisfy `{0}`",
                                                            predicate))
                                                })).with_code(E0284)
                                }.with_span_label(span,
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
                                                predicate))
                                    })).with_long_ty_path(long_ty_path)
                    }
                };
            self.note_obligation_cause(&mut err, obligation);
            err.emit()
        }
    }
}#[instrument(skip(self), level = "debug")]
161    pub(super) fn maybe_report_ambiguity(
162        &self,
163        obligation: &PredicateObligation<'tcx>,
164    ) -> ErrorGuaranteed {
165        // Unable to successfully determine, probably means
166        // insufficient type information, but could mean
167        // ambiguous impls. The latter *ought* to be a
168        // coherence violation, so we don't report it here.
169
170        let predicate = self.resolve_vars_if_possible(obligation.predicate);
171        let span = obligation.cause.span;
172        let mut long_ty_path = None;
173
174        debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
175
176        // Ambiguity errors are often caused as fallout from earlier errors.
177        // We ignore them if this `infcx` is tainted in some cases below.
178
179        let bound_predicate = predicate.kind();
180        let mut err = match bound_predicate.skip_binder() {
181            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
182                let trait_pred = bound_predicate.rebind(data);
183                debug!(?trait_pred);
184
185                if let Err(e) = predicate.error_reported() {
186                    return e;
187                }
188
189                if let Err(guar) = self.tcx.ensure_result().coherent_trait(trait_pred.def_id()) {
190                    // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for
191                    // Foo` in case other `Foo` impls are incoherent.
192                    return guar;
193                }
194
195                // This is kind of a hack: it frequently happens that some earlier
196                // error prevents types from being fully inferred, and then we get
197                // a bunch of uninteresting errors saying something like "<generic
198                // #0> doesn't implement Sized". It may even be true that we
199                // could just skip over all checks where the self-ty is an
200                // inference variable, but I was afraid that there might be an
201                // inference variable created, registered as an obligation, and
202                // then never forced by writeback, and hence by skipping here we'd
203                // be ignoring the fact that we don't KNOW the type works
204                // out. Though even that would probably be harmless, given that
205                // we're only talking about builtin traits, which are known to be
206                // inhabited. We used to check for `self.tainted_by_errors()` to
207                // avoid inundating the user with unnecessary errors, but we now
208                // check upstream for type errors and don't add the obligations to
209                // begin with in those cases.
210                if matches!(
211                    self.tcx.as_lang_item(trait_pred.def_id()),
212                    Some(LangItem::Sized | LangItem::MetaSized)
213                ) {
214                    return match self.tainted_by_errors() {
215                        None => self
216                            .emit_inference_failure_err(
217                                obligation.cause.body_id,
218                                span,
219                                trait_pred.self_ty().skip_binder().into(),
220                                TypeAnnotationNeeded::E0282,
221                                false,
222                            )
223                            .emit(),
224                        Some(e) => e,
225                    };
226                }
227
228                // Typically, this ambiguity should only happen if
229                // there are unresolved type inference variables
230                // (otherwise it would suggest a coherence
231                // failure). But given #21974 that is not necessarily
232                // the case -- we can have multiple where clauses that
233                // are only distinguished by a region, which results
234                // in an ambiguity even when all types are fully
235                // known, since we don't dispatch based on region
236                // relationships.
237
238                // Pick the first generic parameter that still contains inference variables as the one
239                // we're going to emit an error for. If there are none (see above), fall back to
240                // a more general error.
241                let term = data
242                    .trait_ref
243                    .args
244                    .iter()
245                    .filter_map(ty::GenericArg::as_term)
246                    .find(|s| s.has_non_region_infer());
247
248                let mut err = if let Some(term) = term {
249                    let candidates: Vec<_> = self
250                        .tcx
251                        .all_impls(trait_pred.def_id())
252                        .filter_map(|def_id| {
253                            let imp = self.tcx.impl_trait_header(def_id);
254                            if imp.polarity != ty::ImplPolarity::Positive
255                                || !self.tcx.is_user_visible_dep(def_id.krate)
256                            {
257                                return None;
258                            }
259                            let imp = imp.trait_ref.skip_binder();
260                            if imp
261                                .with_replaced_self_ty(self.tcx, trait_pred.skip_binder().self_ty())
262                                == trait_pred.skip_binder().trait_ref
263                            {
264                                Some(imp.self_ty())
265                            } else {
266                                None
267                            }
268                        })
269                        .collect();
270                    self.emit_inference_failure_err_with_type_hint(
271                        obligation.cause.body_id,
272                        span,
273                        term,
274                        TypeAnnotationNeeded::E0283,
275                        true,
276                        match &candidates[..] {
277                            [candidate] => Some(*candidate),
278                            _ => None,
279                        },
280                    )
281                } else {
282                    struct_span_code_err!(
283                        self.dcx(),
284                        span,
285                        E0283,
286                        "type annotations needed: cannot satisfy `{}`",
287                        self.tcx.short_string(predicate, &mut long_ty_path),
288                    )
289                    .with_long_ty_path(long_ty_path)
290                };
291
292                let mut ambiguities = compute_applicable_impls_for_diagnostics(
293                    self.infcx,
294                    &obligation.with(self.tcx, trait_pred),
295                );
296                let has_non_region_infer = trait_pred
297                    .skip_binder()
298                    .trait_ref
299                    .args
300                    .types()
301                    .any(|t| !t.is_ty_or_numeric_infer());
302                // It doesn't make sense to talk about applicable impls if there are more than a
303                // handful of them. If there are a lot of them, but only a few of them have no type
304                // params, we only show those, as they are more likely to be useful/intended.
305                if ambiguities.len() > 5 {
306                    let infcx = self.infcx;
307                    if !ambiguities.iter().all(|option| match option {
308                        CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
309                        CandidateSource::ParamEnv(_) => true,
310                    }) {
311                        // If not all are blanket impls, we filter blanked impls out.
312                        ambiguities.retain(|option| match option {
313                            CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
314                            CandidateSource::ParamEnv(_) => true,
315                        });
316                    }
317                }
318                if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
319                    if let Some(e) = self.tainted_by_errors()
320                        && term.is_none()
321                    {
322                        // If `arg.is_none()`, then this is probably two param-env
323                        // candidates or impl candidates that are equal modulo lifetimes.
324                        // Therefore, if we've already emitted an error, just skip this
325                        // one, since it's not particularly actionable.
326                        err.cancel();
327                        return e;
328                    }
329                    self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
330                } else {
331                    if let Some(e) = self.tainted_by_errors() {
332                        err.cancel();
333                        return e;
334                    }
335                    if let Some(clause) = predicate.as_trait_clause()
336                        && let ty::Infer(_) = clause.self_ty().skip_binder().kind()
337                    {
338                        let tr = self.tcx.short_string(
339                            clause.print_modifiers_and_trait_path(),
340                            &mut err.long_ty_path(),
341                        );
342                        err.note(format!("the type must implement `{tr}`"));
343                    } else {
344                        let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
345                        err.note(format!("cannot satisfy `{pred}`"));
346                    }
347                    let impl_candidates =
348                        self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
349                    if impl_candidates.len() < 40 {
350                        self.report_similar_impl_candidates(
351                            impl_candidates.as_slice(),
352                            trait_pred,
353                            obligation.cause.body_id,
354                            &mut err,
355                            false,
356                            obligation.param_env,
357                        );
358                    }
359                }
360
361                if let ObligationCauseCode::WhereClause(def_id, _)
362                | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
363                {
364                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
365                }
366
367                if term.is_some_and(|term| term.as_type().is_some())
368                    && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id)
369                {
370                    let mut expr_finder = FindExprBySpan::new(span, self.tcx);
371                    expr_finder.visit_expr(&body.value);
372
373                    if let Some(hir::Expr {
374                        kind:
375                            hir::ExprKind::Call(
376                                hir::Expr {
377                                    kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
378                                    ..
379                                },
380                                _,
381                            )
382                            | hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
383                        ..
384                    }) = expr_finder.result
385                        && let [
386                            ..,
387                            trait_path_segment @ hir::PathSegment {
388                                res: Res::Def(DefKind::Trait, trait_id),
389                                ..
390                            },
391                            hir::PathSegment {
392                                ident: assoc_item_ident,
393                                res: Res::Def(_, item_id),
394                                ..
395                            },
396                        ] = path.segments
397                        && data.trait_ref.def_id == *trait_id
398                        && self.tcx.trait_of_assoc(*item_id) == Some(*trait_id)
399                        && let None = self.tainted_by_errors()
400                    {
401                        let assoc_item = self.tcx.associated_item(*item_id);
402                        let (verb, noun) = match assoc_item.kind {
403                            ty::AssocKind::Const { .. } => ("refer to the", "constant"),
404                            ty::AssocKind::Fn { .. } => ("call", "function"),
405                            // This is already covered by E0223, but this following single match
406                            // arm doesn't hurt here.
407                            ty::AssocKind::Type { .. } => ("refer to the", "type"),
408                        };
409
410                        // Replace the more general E0283 with a more specific error
411                        err.cancel();
412                        err = self.dcx().struct_span_err(
413                            span,
414                            format!(
415                                "cannot {verb} associated {noun} on trait without specifying the \
416                                 corresponding `impl` type",
417                            ),
418                        );
419                        err.code(E0790);
420
421                        if item_id.is_local() {
422                            let trait_ident = self.tcx.item_name(*trait_id);
423                            err.span_label(
424                                self.tcx.def_span(*item_id),
425                                format!("`{trait_ident}::{assoc_item_ident}` defined here"),
426                            );
427                        }
428
429                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
430
431                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
432
433                        if let Some(&impl_def_id) =
434                            trait_impls.non_blanket_impls().values().flatten().next()
435                        {
436                            let non_blanket_impl_count =
437                                trait_impls.non_blanket_impls().values().flatten().count();
438                            // If there is only one implementation of the trait, suggest using it.
439                            // Otherwise, use a placeholder comment for the implementation.
440                            let (message, self_types) = if non_blanket_impl_count == 1 {
441                                (
442                                    "use the fully-qualified path to the only available \
443                                     implementation",
444                                    vec![format!(
445                                        "{}",
446                                        self.tcx.type_of(impl_def_id).instantiate_identity()
447                                    )],
448                                )
449                            } else if non_blanket_impl_count < 20 {
450                                (
451                                    "use a fully-qualified path to one of the available \
452                                     implementations",
453                                    trait_impls
454                                        .non_blanket_impls()
455                                        .values()
456                                        .flatten()
457                                        .map(|&id| {
458                                            format!(
459                                                "{}",
460                                                self.tcx.type_of(id).instantiate_identity()
461                                            )
462                                        })
463                                        .collect::<Vec<String>>(),
464                                )
465                            } else {
466                                (
467                                    "use a fully-qualified path to a specific available \
468                                     implementation",
469                                    vec!["/* self type */".to_string()],
470                                )
471                            };
472                            let suggestions: Vec<_> = self_types
473                                .into_iter()
474                                .map(|self_type| {
475                                    let mut suggestions = vec![(
476                                        path.span.shrink_to_lo(),
477                                        format!("<{self_type} as "),
478                                    )];
479                                    if let Some(generic_arg) = trait_path_segment.args {
480                                        let between_span = trait_path_segment
481                                            .ident
482                                            .span
483                                            .between(generic_arg.span_ext);
484                                        // get rid of :: between Trait and <type>
485                                        // must be '::' between them, otherwise the parser won't accept the code
486                                        suggestions.push((between_span, "".to_string()));
487                                        suggestions.push((
488                                            generic_arg.span_ext.shrink_to_hi(),
489                                            ">".to_string(),
490                                        ));
491                                    } else {
492                                        suggestions.push((
493                                            trait_path_segment.ident.span.shrink_to_hi(),
494                                            ">".to_string(),
495                                        ));
496                                    }
497                                    suggestions
498                                })
499                                .collect();
500                            err.multipart_suggestions(
501                                message,
502                                suggestions,
503                                Applicability::MaybeIncorrect,
504                            );
505                        }
506                    }
507                };
508
509                err
510            }
511
512            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
513                // Same hacky approach as above to avoid deluging user
514                // with error messages.
515
516                if let Err(e) = term.error_reported() {
517                    return e;
518                }
519                if let Some(e) = self.tainted_by_errors() {
520                    return e;
521                }
522
523                self.emit_inference_failure_err(
524                    obligation.cause.body_id,
525                    span,
526                    term,
527                    TypeAnnotationNeeded::E0282,
528                    false,
529                )
530            }
531
532            ty::PredicateKind::Subtype(data) => {
533                if let Err(e) = data.error_reported() {
534                    return e;
535                }
536                if let Some(e) = self.tainted_by_errors() {
537                    return e;
538                }
539                let ty::SubtypePredicate { a_is_expected: _, a, b } = data;
540                // both must be type variables, or the other would've been instantiated
541                assert!(a.is_ty_var() && b.is_ty_var());
542                self.emit_inference_failure_err(
543                    obligation.cause.body_id,
544                    span,
545                    a.into(),
546                    TypeAnnotationNeeded::E0282,
547                    true,
548                )
549            }
550
551            ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
552                if let Err(e) = predicate.error_reported() {
553                    return e;
554                }
555                if let Some(e) = self.tainted_by_errors() {
556                    return e;
557                }
558
559                if let Err(guar) = self
560                    .tcx
561                    .ensure_result()
562                    .coherent_trait(self.tcx.parent(data.projection_term.def_id))
563                {
564                    // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
565                    // other `Foo` impls are incoherent.
566                    return guar;
567                }
568                let term = data
569                    .projection_term
570                    .args
571                    .iter()
572                    .filter_map(ty::GenericArg::as_term)
573                    .chain([data.term])
574                    .find(|g| g.has_non_region_infer());
575                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
576                if let Some(term) = term {
577                    self.emit_inference_failure_err(
578                        obligation.cause.body_id,
579                        span,
580                        term,
581                        TypeAnnotationNeeded::E0284,
582                        true,
583                    )
584                    .with_note(format!("cannot satisfy `{predicate}`"))
585                    .with_long_ty_path(long_ty_path)
586                } else {
587                    // If we can't find a generic parameter, just print a generic error
588                    struct_span_code_err!(
589                        self.dcx(),
590                        span,
591                        E0284,
592                        "type annotations needed: cannot satisfy `{predicate}`",
593                    )
594                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
595                    .with_long_ty_path(long_ty_path)
596                }
597            }
598
599            ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
600                if let Err(e) = predicate.error_reported() {
601                    return e;
602                }
603                if let Some(e) = self.tainted_by_errors() {
604                    return e;
605                }
606                let term =
607                    data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
608                if let Some(term) = term {
609                    self.emit_inference_failure_err(
610                        obligation.cause.body_id,
611                        span,
612                        term,
613                        TypeAnnotationNeeded::E0284,
614                        true,
615                    )
616                } else {
617                    // If we can't find a generic parameter, just print a generic error
618                    let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
619                    struct_span_code_err!(
620                        self.dcx(),
621                        span,
622                        E0284,
623                        "type annotations needed: cannot satisfy `{predicate}`",
624                    )
625                    .with_span_label(span, format!("cannot satisfy `{predicate}`"))
626                    .with_long_ty_path(long_ty_path)
627                }
628            }
629
630            ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
631                .emit_inference_failure_err(
632                    obligation.cause.body_id,
633                    span,
634                    ct.into(),
635                    TypeAnnotationNeeded::E0284,
636                    true,
637                ),
638
639            ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
640                if term.is_infer() =>
641            {
642                if let Some(e) = self.tainted_by_errors() {
643                    return e;
644                }
645                let alias = self.tcx.short_string(alias, &mut long_ty_path);
646                struct_span_code_err!(
647                    self.dcx(),
648                    span,
649                    E0284,
650                    "type annotations needed: cannot normalize `{alias}`",
651                )
652                .with_span_label(span, format!("cannot normalize `{alias}`"))
653                .with_long_ty_path(long_ty_path)
654            }
655
656            ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
657                if let Some(e) = self.tainted_by_errors() {
658                    return e;
659                }
660
661                if self.tcx.features().staged_api() {
662                    self.dcx().struct_span_err(
663                        span,
664                        format!("unstable feature `{sym}` is used without being enabled."),
665                    ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
666                } else {
667                    feature_err_unstable_feature_bound(
668                        &self.tcx.sess,
669                        sym,
670                        span,
671                        format!("use of unstable library feature `{sym}`"),
672                    )
673                }
674            }
675
676            _ => {
677                if let Some(e) = self.tainted_by_errors() {
678                    return e;
679                }
680                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
681                struct_span_code_err!(
682                    self.dcx(),
683                    span,
684                    E0284,
685                    "type annotations needed: cannot satisfy `{predicate}`",
686                )
687                .with_span_label(span, format!("cannot satisfy `{predicate}`"))
688                .with_long_ty_path(long_ty_path)
689            }
690        };
691        self.note_obligation_cause(&mut err, obligation);
692        err.emit()
693    }
694
695    fn annotate_source_of_ambiguity(
696        &self,
697        err: &mut Diag<'_>,
698        ambiguities: &[CandidateSource],
699        predicate: ty::Predicate<'tcx>,
700    ) {
701        let mut spans = ::alloc::vec::Vec::new()vec![];
702        let mut crates = ::alloc::vec::Vec::new()vec![];
703        let mut post = ::alloc::vec::Vec::new()vec![];
704        let mut has_param_env = false;
705        for ambiguity in ambiguities {
706            match ambiguity {
707                CandidateSource::DefId(impl_def_id) => match self.tcx.span_of_impl(*impl_def_id) {
708                    Ok(span) => spans.push(span),
709                    Err(name) => {
710                        crates.push(name);
711                        if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
712                            post.push(header);
713                        }
714                    }
715                },
716                CandidateSource::ParamEnv(span) => {
717                    has_param_env = true;
718                    spans.push(*span);
719                }
720            }
721        }
722        let mut crate_names: Vec<_> = crates.iter().map(|n| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", n))
    })format!("`{n}`")).collect();
723        crate_names.sort();
724        crate_names.dedup();
725        post.sort();
726        post.dedup();
727
728        if self.tainted_by_errors().is_some()
729            && (crate_names.len() == 1
730                && spans.len() == 0
731                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
732                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
733        {
734            // Avoid complaining about other inference issues for expressions like
735            // `42 >> 1`, where the types are still `{integer}`, but we want to
736            // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
737            // NOTE(eddyb) this was `.cancel()`, but `err`
738            // is borrowed, so we can't fully defuse it.
739            err.downgrade_to_delayed_bug();
740            return;
741        }
742
743        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("multiple `impl`s{0} satisfying `{1}` found",
                if has_param_env { " or `where` clauses" } else { "" },
                predicate))
    })format!(
744            "multiple `impl`s{} satisfying `{}` found",
745            if has_param_env { " or `where` clauses" } else { "" },
746            predicate
747        );
748        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
749            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(":\n{0}",
                post.iter().map(|p|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("- {0}", p))
                                    })).collect::<Vec<_>>().join("\n")))
    })format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::<Vec<_>>().join("\n"))
750        } else if post.len() == 1 {
751            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(": `{0}`", post[0]))
    })format!(": `{}`", post[0])
752        } else {
753            String::new()
754        };
755
756        match (spans.len(), crates.len(), crate_names.len()) {
757            (0, 0, 0) => {
758                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot satisfy `{0}`", predicate))
    })format!("cannot satisfy `{predicate}`"));
759            }
760            (0, _, 1) => {
761                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1} in the `{0}` crate{2}",
                crates[0], msg, post))
    })format!("{msg} in the `{}` crate{post}", crates[0]));
762            }
763            (0, _, _) => {
764                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} in the following crates: {1}{2}",
                msg, crate_names.join(", "), post))
    })format!(
765                    "{} in the following crates: {}{}",
766                    msg,
767                    crate_names.join(", "),
768                    post,
769                ));
770            }
771            (_, 0, 0) => {
772                let span: MultiSpan = spans.into();
773                err.span_note(span, msg);
774            }
775            (_, 1, 1) => {
776                let span: MultiSpan = spans.into();
777                err.span_note(span, msg);
778                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("and another `impl` found in the `{0}` crate{1}",
                crates[0], post))
    })format!("and another `impl` found in the `{}` crate{post}", crates[0]));
779            }
780            _ => {
781                let span: MultiSpan = spans.into();
782                err.span_note(span, msg);
783                err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("and more `impl`s found in the following crates: {0}{1}",
                crate_names.join(", "), post))
    })format!(
784                    "and more `impl`s found in the following crates: {}{}",
785                    crate_names.join(", "),
786                    post,
787                ));
788            }
789        }
790    }
791}
792
793struct HasNumericInferVisitor;
794
795impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
796    type Result = ControlFlow<()>;
797
798    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
799        if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Infer(ty::FloatVar(_) | ty::IntVar(_)) => true,
    _ => false,
}matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
800            ControlFlow::Break(())
801        } else {
802            ControlFlow::Continue(())
803        }
804    }
805}