1use std::ops::ControlFlow;
2
3use rustc_attr_ir::lang_items::LangItem;
4use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err};
5use rustc_hir as hir;
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::PrintPolyTraitClauseExt;
15use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _, Unnormalized};
16use rustc_session::diagnostics::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::query::evaluate_obligation::InferCtxtExt;
24use crate::traits::{FulfillmentError, ObligationCtxt};
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 {
Self::DefId(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "DefId",
&__self_0),
Self::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 ignore_predicates_of_impls: bool,
36) -> Vec<CandidateSource> {
37 let tcx = infcx.tcx;
38 let param_env = obligation.param_env;
39
40 let predicate_polarity = obligation.predicate.skip_binder().polarity;
41
42 let impl_may_apply = |impl_def_id| {
43 let ocx = ObligationCtxt::new(infcx);
44 infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
45 let obligation_trait_ref = ocx.normalize(
46 &ObligationCause::dummy(),
47 param_env,
48 Unnormalized::new_wip(placeholder_obligation.trait_ref),
49 );
50
51 let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
52 let impl_trait_ref =
53 tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip();
54 let impl_trait_ref = ocx.normalize(
55 &ObligationCause::dummy(),
56 param_env,
57 Unnormalized::new_wip(impl_trait_ref),
58 );
59
60 if let Err(_) =
61 ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
62 {
63 return false;
64 }
65
66 let impl_trait_header = tcx.impl_trait_header(impl_def_id);
67 let impl_polarity = impl_trait_header.polarity;
68
69 match (impl_polarity, predicate_polarity) {
70 (ty::ImplPolarity::Positive, ty::ClausePolarity::Positive)
71 | (ty::ImplPolarity::Negative, ty::ClausePolarity::Negative) => {}
72 _ => return false,
73 }
74
75 if !ignore_predicates_of_impls {
76 let obligations = tcx
77 .clauses_of(impl_def_id)
78 .instantiate(tcx, impl_args)
79 .into_iter()
80 .map(|(clause, _)| {
81 Obligation::new(
82 tcx,
83 ObligationCause::dummy(),
84 param_env,
85 clause.skip_norm_wip(),
86 )
87 })
88 .filter(|obligation| {
93 infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok()
94 });
95 ocx.register_obligations(obligations);
96 }
97
98 ocx.try_evaluate_obligations().no_errors()
99 })
100 };
101
102 let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitClause<'tcx>| {
103 let ocx = ObligationCtxt::new(infcx);
104 infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
105 let obligation_trait_ref = ocx.normalize(
106 &ObligationCause::dummy(),
107 param_env,
108 Unnormalized::new_wip(placeholder_obligation.trait_ref),
109 );
110
111 let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
112 DUMMY_SP,
113 BoundRegionConversionTime::HigherRankedType,
114 poly_trait_predicate,
115 );
116 let param_env_trait_ref = ocx.normalize(
117 &ObligationCause::dummy(),
118 param_env,
119 Unnormalized::new_wip(param_env_predicate.trait_ref),
120 );
121
122 if let Err(_) = ocx.eq(
123 &ObligationCause::dummy(),
124 param_env,
125 obligation_trait_ref,
126 param_env_trait_ref,
127 ) {
128 return false;
129 }
130
131 ocx.try_evaluate_obligations().no_errors()
132 })
133 };
134
135 let mut ambiguities = Vec::new();
136
137 tcx.for_each_relevant_impl(
138 obligation.predicate.def_id(),
139 obligation.predicate.skip_binder().trait_ref.self_ty(),
140 |impl_def_id| {
141 if infcx.probe(|_| impl_may_apply(impl_def_id)) {
142 ambiguities.push(CandidateSource::DefId(impl_def_id))
143 }
144 },
145 );
146
147 let body_def_id = obligation.cause.body_def_id;
153 if body_def_id != CRATE_DEF_ID {
154 let clauses = tcx.clauses_of(body_def_id.to_def_id()).instantiate_identity(tcx);
155 for (clause, span) in
156 elaborate(tcx, clauses.into_iter().map(|(c, s)| (c.skip_norm_wip(), s)))
157 {
158 let kind = clause.kind();
159 if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
160 && param_env_candidate_may_apply(kind.rebind(trait_pred))
161 {
162 if kind.rebind(trait_pred.trait_ref)
163 == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
164 {
165 ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
166 } else {
167 ambiguities.push(CandidateSource::ParamEnv(span))
168 }
169 }
170 }
171 }
172
173 ambiguities
174}
175
176impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
177 pub(super) fn ambiguity_term(&self, predicate: ty::Predicate<'tcx>) -> Option<ty::Term<'tcx>> {
184 match predicate.kind().skip_binder() {
185 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
186 data.trait_ref.args.terms().find(|term| term.has_non_region_infer())
187 }
188 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => data
189 .projection_term
190 .args
191 .terms()
192 .chain([data.term])
193 .find(|term| term.has_non_region_infer()),
194 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => Some(term),
195 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
196 data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer())
197 }
198 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => Some(ct.into()),
199 ty::PredicateKind::Subtype(data) => Some(data.a.into()),
200 ty::PredicateKind::NormalizesTo(data) if data.term.is_infer() => Some(data.term),
201 _ => None,
202 }
203 }
204
205 {}
#[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("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
::tracing_core::__macro_support::Option::Some(205u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("obligation")
}> =
::tracing::__macro_support::FieldName::new("obligation");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("related")
}> =
::tracing::__macro_support::FieldName::new("related");
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(&obligation)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&related)
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: ErrorGuaranteed = loop {};
return __tracing_attr_fake_return;
}
{
let predicate =
self.deeply_resolve_ignoring_regions(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 /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs:220",
"rustc_trait_selection::error_reporting::traits::ambiguity",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
::tracing_core::__macro_support::Option::Some(220u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("predicate")
}> =
::tracing::__macro_support::FieldName::new("predicate");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("obligation.cause.code")
}> =
::tracing::__macro_support::FieldName::new("obligation.cause.code");
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(&predicate)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&obligation.cause.code())
as &dyn ::tracing::field::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 /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs:229",
"rustc_trait_selection::error_reporting::traits::ambiguity",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs"),
::tracing_core::__macro_support::Option::Some(229u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::traits::ambiguity"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_pred")
}> =
::tracing::__macro_support::FieldName::new("trait_pred");
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(&trait_pred)
as &dyn ::tracing::field::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_def_id,
span, trait_pred.self_ty().skip_binder().into(),
TypeAnnotationNeeded::E0282, false).emit_err(),
Some(e) => e,
};
}
let term = self.ambiguity_term(predicate);
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_def_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)
};
if let Some(ambiguities) =
self.applicable_impls_to_mention(obligation, trait_pred) {
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 clause = predicate.as_trait_clause().unwrap();
let impl_candidates =
self.find_similar_impl_candidates(clause.def_id(),
clause.self_ty().skip_binder());
if impl_candidates.len() < 40 {
self.report_similar_impl_candidates(impl_candidates.as_slice(),
obligation, trait_pred, obligation.cause.body_def_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_def_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().skip_norm_wip()))
})])))
} 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().skip_norm_wip()))
})
}).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_def_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_def_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 data.projection_term.kind.is_trait_projection() &&
let Err(guar) =
self.tcx.ensure_result().coherent_trait(self.tcx.parent(data.def_id()))
{
return guar;
}
let term = self.ambiguity_term(predicate);
let predicate =
self.tcx.short_string(predicate, &mut long_ty_path);
if let Some(term) = term {
self.emit_inference_failure_err(obligation.cause.body_def_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(_))
=> {
if let Err(e) = predicate.error_reported() { return e; }
if let Some(e) = self.tainted_by_errors() { return e; }
if let Some(term) = self.ambiguity_term(predicate) {
self.emit_inference_failure_err(obligation.cause.body_def_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_def_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)
}
};
let mut mentioned =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[predicate]));
let mut mentioned_strs: Vec<String> = ::alloc::vec::Vec::new();
for &error in related {
let related_pred =
self.deeply_resolve_ignoring_regions(error.obligation.predicate);
if mentioned.contains(&related_pred) { continue; }
let note =
match related_pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) if
!#[allow(non_exhaustive_omitted_patterns)] match self.tcx.as_lang_item(data.def_id())
{
Some(LangItem::Sized | LangItem::MetaSized |
LangItem::PointeeSized) => true,
_ => false,
} => {
let clause = related_pred.kind().rebind(data);
if 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());
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the type must also implement `{0}`",
tr))
})
} else {
let pred =
self.tcx.short_string(related_pred,
&mut err.long_ty_path());
let note =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
pred))
});
if !mentioned_strs.contains(¬e) &&
self.tainted_by_errors().is_none() &&
let Some(ambiguities) =
self.applicable_impls_to_mention(&error.obligation, clause)
{
self.annotate_source_of_ambiguity(&mut err, &ambiguities,
related_pred);
mentioned_strs.push(note);
mentioned.push(related_pred);
continue;
}
note
}
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) =>
{
let pred =
self.tcx.short_string(related_pred,
&mut err.long_ty_path());
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot satisfy `{0}`",
pred))
})
}
_ => { mentioned.push(related_pred); continue; }
};
if !mentioned_strs.contains(¬e) {
err.note(note.clone());
mentioned_strs.push(note);
}
mentioned.push(related_pred);
}
self.note_obligation_cause(&mut err, obligation);
for &error in related {
if error.obligation.cause.code() != obligation.cause.code() {
self.note_obligation_cause(&mut err, &error.obligation);
}
}
err.emit_err()
}
}
}#[instrument(skip(self), level = "debug")]
206 pub(super) fn maybe_report_ambiguity(
207 &self,
208 obligation: &PredicateObligation<'tcx>,
209 related: &[&FulfillmentError<'tcx>],
210 ) -> ErrorGuaranteed {
211 let predicate = self.deeply_resolve_ignoring_regions(obligation.predicate);
217 let span = obligation.cause.span;
218 let mut long_ty_path = None;
219
220 debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
221
222 let bound_predicate = predicate.kind();
226 let mut err = match bound_predicate.skip_binder() {
227 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
228 let trait_pred = bound_predicate.rebind(data);
229 debug!(?trait_pred);
230
231 if let Err(e) = predicate.error_reported() {
232 return e;
233 }
234
235 if let Err(guar) = self.tcx.ensure_result().coherent_trait(trait_pred.def_id()) {
236 return guar;
239 }
240
241 if matches!(
257 self.tcx.as_lang_item(trait_pred.def_id()),
258 Some(LangItem::Sized | LangItem::MetaSized)
259 ) {
260 return match self.tainted_by_errors() {
261 None => self
262 .emit_inference_failure_err(
263 obligation.cause.body_def_id,
264 span,
265 trait_pred.self_ty().skip_binder().into(),
266 TypeAnnotationNeeded::E0282,
267 false,
268 )
269 .emit_err(),
270 Some(e) => e,
271 };
272 }
273
274 let term = self.ambiguity_term(predicate);
288
289 let mut err = if let Some(term) = term {
290 let candidates: Vec<_> = self
291 .tcx
292 .all_impls(trait_pred.def_id())
293 .filter_map(|def_id| {
294 let imp = self.tcx.impl_trait_header(def_id);
295 if imp.polarity != ty::ImplPolarity::Positive
296 || !self.tcx.is_user_visible_dep(def_id.krate)
297 {
298 return None;
299 }
300 let imp = imp.trait_ref.skip_binder();
301 if imp
302 .with_replaced_self_ty(self.tcx, trait_pred.skip_binder().self_ty())
303 == trait_pred.skip_binder().trait_ref
304 {
305 Some(imp.self_ty())
306 } else {
307 None
308 }
309 })
310 .collect();
311 self.emit_inference_failure_err_with_type_hint(
312 obligation.cause.body_def_id,
313 span,
314 term,
315 TypeAnnotationNeeded::E0283,
316 true,
317 match &candidates[..] {
318 [candidate] => Some(*candidate),
319 _ => None,
320 },
321 )
322 } else {
323 struct_span_code_err!(
324 self.dcx(),
325 span,
326 E0283,
327 "type annotations needed: cannot satisfy `{}`",
328 self.tcx.short_string(predicate, &mut long_ty_path),
329 )
330 .with_long_ty_path(long_ty_path)
331 };
332
333 if let Some(ambiguities) = self.applicable_impls_to_mention(obligation, trait_pred)
334 {
335 if let Some(e) = self.tainted_by_errors()
336 && term.is_none()
337 {
338 err.cancel();
343 return e;
344 }
345 self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
346 } else {
347 if let Some(e) = self.tainted_by_errors() {
348 err.cancel();
349 return e;
350 }
351 if let Some(clause) = predicate.as_trait_clause()
352 && let ty::Infer(_) = clause.self_ty().skip_binder().kind()
353 {
354 let tr = self.tcx.short_string(
355 clause.print_modifiers_and_trait_path(),
356 &mut err.long_ty_path(),
357 );
358 err.note(format!("the type must implement `{tr}`"));
359 } else {
360 let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
361 err.note(format!("cannot satisfy `{pred}`"));
362 }
363 let clause = predicate.as_trait_clause().unwrap();
364 let impl_candidates = self.find_similar_impl_candidates(
365 clause.def_id(),
366 clause.self_ty().skip_binder(),
367 );
368 if impl_candidates.len() < 40 {
369 self.report_similar_impl_candidates(
370 impl_candidates.as_slice(),
371 obligation,
372 trait_pred,
373 obligation.cause.body_def_id,
374 &mut err,
375 false,
376 obligation.param_env,
377 );
378 }
379 }
380
381 if let ObligationCauseCode::WhereClause(def_id, _)
382 | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
383 {
384 self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
385 }
386
387 if term.is_some_and(|term| term.as_type().is_some())
388 && let Some(body) =
389 self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id)
390 {
391 let mut expr_finder = FindExprBySpan::new(span, self.tcx);
392 expr_finder.visit_expr(&body.value);
393
394 if let Some(hir::Expr {
395 kind:
396 hir::ExprKind::Call(
397 hir::Expr {
398 kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
399 ..
400 },
401 _,
402 )
403 | hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
404 ..
405 }) = expr_finder.result
406 && let [
407 ..,
408 trait_path_segment @ hir::PathSegment {
409 res: Res::Def(DefKind::Trait, trait_id),
410 ..
411 },
412 hir::PathSegment {
413 ident: assoc_item_ident,
414 res: Res::Def(_, item_id),
415 ..
416 },
417 ] = path.segments
418 && data.trait_ref.def_id == *trait_id
419 && self.tcx.trait_of_assoc(*item_id) == Some(*trait_id)
420 && let None = self.tainted_by_errors()
421 {
422 let assoc_item = self.tcx.associated_item(*item_id);
423 let (verb, noun) = match assoc_item.kind {
424 ty::AssocKind::Const { .. } => ("refer to the", "constant"),
425 ty::AssocKind::Fn { .. } => ("call", "function"),
426 ty::AssocKind::Type { .. } => ("refer to the", "type"),
429 };
430
431 err.cancel();
433 err = self.dcx().struct_span_err(
434 span,
435 format!(
436 "cannot {verb} associated {noun} on trait without specifying the \
437 corresponding `impl` type",
438 ),
439 );
440 err.code(E0790);
441
442 if item_id.is_local() {
443 let trait_ident = self.tcx.item_name(*trait_id);
444 err.span_label(
445 self.tcx.def_span(*item_id),
446 format!("`{trait_ident}::{assoc_item_ident}` defined here"),
447 );
448 }
449
450 err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
451
452 let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
453
454 if let Some(&impl_def_id) =
455 trait_impls.non_blanket_impls().values().flatten().next()
456 {
457 let non_blanket_impl_count =
458 trait_impls.non_blanket_impls().values().flatten().count();
459 let (message, self_types) = if non_blanket_impl_count == 1 {
462 (
463 "use the fully-qualified path to the only available \
464 implementation",
465 vec![format!(
466 "{}",
467 self.tcx
468 .type_of(impl_def_id)
469 .instantiate_identity()
470 .skip_norm_wip()
471 )],
472 )
473 } else if non_blanket_impl_count < 20 {
474 (
475 "use a fully-qualified path to one of the available \
476 implementations",
477 trait_impls
478 .non_blanket_impls()
479 .values()
480 .flatten()
481 .map(|&id| {
482 format!(
483 "{}",
484 self.tcx
485 .type_of(id)
486 .instantiate_identity()
487 .skip_norm_wip()
488 )
489 })
490 .collect::<Vec<String>>(),
491 )
492 } else {
493 (
494 "use a fully-qualified path to a specific available \
495 implementation",
496 vec!["/* self type */".to_string()],
497 )
498 };
499 let suggestions: Vec<_> = self_types
500 .into_iter()
501 .map(|self_type| {
502 let mut suggestions = vec![(
503 path.span.shrink_to_lo(),
504 format!("<{self_type} as "),
505 )];
506 if let Some(generic_arg) = trait_path_segment.args {
507 let between_span = trait_path_segment
508 .ident
509 .span
510 .between(generic_arg.span_ext);
511 suggestions.push((between_span, "".to_string()));
514 suggestions.push((
515 generic_arg.span_ext.shrink_to_hi(),
516 ">".to_string(),
517 ));
518 } else {
519 suggestions.push((
520 trait_path_segment.ident.span.shrink_to_hi(),
521 ">".to_string(),
522 ));
523 }
524 suggestions
525 })
526 .collect();
527 err.multipart_suggestions(
528 message,
529 suggestions,
530 Applicability::MaybeIncorrect,
531 );
532 }
533 }
534 };
535
536 err
537 }
538
539 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
540 if let Err(e) = term.error_reported() {
544 return e;
545 }
546 if let Some(e) = self.tainted_by_errors() {
547 return e;
548 }
549
550 self.emit_inference_failure_err(
551 obligation.cause.body_def_id,
552 span,
553 term,
554 TypeAnnotationNeeded::E0282,
555 false,
556 )
557 }
558
559 ty::PredicateKind::Subtype(data) => {
560 if let Err(e) = data.error_reported() {
561 return e;
562 }
563 if let Some(e) = self.tainted_by_errors() {
564 return e;
565 }
566 let ty::SubtypePredicate { a_is_expected: _, a, b } = data;
567 assert!(a.is_ty_var() && b.is_ty_var());
569 self.emit_inference_failure_err(
570 obligation.cause.body_def_id,
571 span,
572 a.into(),
573 TypeAnnotationNeeded::E0282,
574 true,
575 )
576 }
577
578 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
579 if let Err(e) = predicate.error_reported() {
580 return e;
581 }
582 if let Some(e) = self.tainted_by_errors() {
583 return e;
584 }
585
586 if data.projection_term.kind.is_trait_projection()
587 && let Err(guar) =
588 self.tcx.ensure_result().coherent_trait(self.tcx.parent(data.def_id()))
589 {
590 return guar;
593 }
594 let term = self.ambiguity_term(predicate);
595 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
596 if let Some(term) = term {
597 self.emit_inference_failure_err(
598 obligation.cause.body_def_id,
599 span,
600 term,
601 TypeAnnotationNeeded::E0284,
602 true,
603 )
604 .with_note(format!("cannot satisfy `{predicate}`"))
605 .with_long_ty_path(long_ty_path)
606 } else {
607 struct_span_code_err!(
609 self.dcx(),
610 span,
611 E0284,
612 "type annotations needed: cannot satisfy `{predicate}`",
613 )
614 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
615 .with_long_ty_path(long_ty_path)
616 }
617 }
618
619 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) => {
620 if let Err(e) = predicate.error_reported() {
621 return e;
622 }
623 if let Some(e) = self.tainted_by_errors() {
624 return e;
625 }
626 if let Some(term) = self.ambiguity_term(predicate) {
627 self.emit_inference_failure_err(
628 obligation.cause.body_def_id,
629 span,
630 term,
631 TypeAnnotationNeeded::E0284,
632 true,
633 )
634 } else {
635 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
637 struct_span_code_err!(
638 self.dcx(),
639 span,
640 E0284,
641 "type annotations needed: cannot satisfy `{predicate}`",
642 )
643 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
644 .with_long_ty_path(long_ty_path)
645 }
646 }
647
648 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
649 .emit_inference_failure_err(
650 obligation.cause.body_def_id,
651 span,
652 ct.into(),
653 TypeAnnotationNeeded::E0284,
654 true,
655 ),
656
657 ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
658 if term.is_infer() =>
659 {
660 if let Some(e) = self.tainted_by_errors() {
661 return e;
662 }
663 let alias = self.tcx.short_string(alias, &mut long_ty_path);
664 struct_span_code_err!(
665 self.dcx(),
666 span,
667 E0284,
668 "type annotations needed: cannot normalize `{alias}`",
669 )
670 .with_span_label(span, format!("cannot normalize `{alias}`"))
671 .with_long_ty_path(long_ty_path)
672 }
673
674 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
675 if let Some(e) = self.tainted_by_errors() {
676 return e;
677 }
678
679 if self.tcx.features().staged_api() {
680 self.dcx().struct_span_err(
681 span,
682 format!("unstable feature `{sym}` is used without being enabled."),
683 ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
684 } else {
685 feature_err_unstable_feature_bound(
686 &self.tcx.sess,
687 sym,
688 span,
689 format!("use of unstable library feature `{sym}`"),
690 )
691 }
692 }
693
694 _ => {
695 if let Some(e) = self.tainted_by_errors() {
696 return e;
697 }
698 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
699 struct_span_code_err!(
700 self.dcx(),
701 span,
702 E0284,
703 "type annotations needed: cannot satisfy `{predicate}`",
704 )
705 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
706 .with_long_ty_path(long_ty_path)
707 }
708 };
709
710 let mut mentioned = vec![predicate];
715 let mut mentioned_strs: Vec<String> = vec![];
716 for &error in related {
717 let related_pred = self.deeply_resolve_ignoring_regions(error.obligation.predicate);
718 if mentioned.contains(&related_pred) {
719 continue;
720 }
721 let note = match related_pred.kind().skip_binder() {
722 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data))
723 if !matches!(
724 self.tcx.as_lang_item(data.def_id()),
725 Some(LangItem::Sized | LangItem::MetaSized | LangItem::PointeeSized)
726 ) =>
727 {
728 let clause = related_pred.kind().rebind(data);
729 if let ty::Infer(_) = clause.self_ty().skip_binder().kind() {
730 let tr = self.tcx.short_string(
731 clause.print_modifiers_and_trait_path(),
732 &mut err.long_ty_path(),
733 );
734 format!("the type must also implement `{tr}`")
735 } else {
736 let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path());
737 let note = format!("cannot satisfy `{pred}`");
738 if !mentioned_strs.contains(¬e)
746 && self.tainted_by_errors().is_none()
747 && let Some(ambiguities) =
748 self.applicable_impls_to_mention(&error.obligation, clause)
749 {
750 self.annotate_source_of_ambiguity(&mut err, &ambiguities, related_pred);
751 mentioned_strs.push(note);
752 mentioned.push(related_pred);
753 continue;
754 }
755 note
756 }
757 }
758 ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
759 let pred = self.tcx.short_string(related_pred, &mut err.long_ty_path());
760 format!("cannot satisfy `{pred}`")
761 }
762 _ => {
763 mentioned.push(related_pred);
764 continue;
765 }
766 };
767 if !mentioned_strs.contains(¬e) {
770 err.note(note.clone());
771 mentioned_strs.push(note);
772 }
773 mentioned.push(related_pred);
774 }
775
776 self.note_obligation_cause(&mut err, obligation);
777 for &error in related {
781 if error.obligation.cause.code() != obligation.cause.code() {
782 self.note_obligation_cause(&mut err, &error.obligation);
783 }
784 }
785 err.emit_err()
786 }
787
788 fn applicable_impls_to_mention(
791 &self,
792 obligation: &PredicateObligation<'tcx>,
793 trait_pred: ty::PolyTraitClause<'tcx>,
794 ) -> Option<Vec<CandidateSource>> {
795 let mut ambiguities = compute_applicable_impls_for_diagnostics(
796 self.infcx,
797 &obligation.with(self.tcx, trait_pred),
798 false,
799 );
800 let has_non_region_infer =
801 trait_pred.skip_binder().trait_ref.args.types().any(|t| !t.is_ty_or_numeric_infer());
802 if ambiguities.len() > 5 {
806 let infcx = self.infcx;
807 if !ambiguities.iter().all(|option| match option {
808 CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
809 CandidateSource::ParamEnv(_) => true,
810 }) {
811 ambiguities.retain(|option| match option {
813 CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
814 CandidateSource::ParamEnv(_) => true,
815 });
816 }
817 }
818 (ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer)
819 .then_some(ambiguities)
820 }
821
822 fn annotate_source_of_ambiguity(
823 &self,
824 err: &mut Diag<'_>,
825 ambiguities: &[CandidateSource],
826 predicate: ty::Predicate<'tcx>,
827 ) {
828 let mut spans = ::alloc::vec::Vec::new()vec![];
829 let mut crates = ::alloc::vec::Vec::new()vec![];
830 let mut post = ::alloc::vec::Vec::new()vec![];
831 let mut has_param_env = false;
832 for ambiguity in ambiguities {
833 match ambiguity {
834 CandidateSource::DefId(impl_def_id) => match self.tcx.span_of_impl(*impl_def_id) {
835 Ok(span) => spans.push(span),
836 Err(name) => {
837 crates.push(name);
838 if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
839 post.push(header);
840 }
841 }
842 },
843 CandidateSource::ParamEnv(span) => {
844 has_param_env = true;
845 spans.push(*span);
846 }
847 }
848 }
849 let mut crate_names: Vec<_> = crates.iter().map(|n| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")).collect();
850 crate_names.sort();
851 crate_names.dedup();
852 post.sort();
853 post.dedup();
854
855 if self.tainted_by_errors().is_some()
856 && (crate_names.len() == 1
857 && spans.len() == 0
858 && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
859 || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
860 {
861 err.downgrade_to_delayed_bug();
867 return;
868 }
869
870 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!(
871 "multiple `impl`s{} satisfying `{}` found",
872 if has_param_env { " or `where` clauses" } else { "" },
873 predicate
874 );
875 let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
876 ::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"))
877 } else if post.len() == 1 {
878 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": `{0}`", post[0]))
})format!(": `{}`", post[0])
879 } else {
880 String::new()
881 };
882
883 match (spans.len(), crates.len(), crate_names.len()) {
884 (0, 0, 0) => {
885 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot satisfy `{0}`", predicate))
})format!("cannot satisfy `{predicate}`"));
886 }
887 (0, _, 1) => {
888 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]));
889 }
890 (0, _, _) => {
891 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} in the following crates: {1}{2}",
msg, crate_names.join(", "), post))
})format!(
892 "{} in the following crates: {}{}",
893 msg,
894 crate_names.join(", "),
895 post,
896 ));
897 }
898 (_, 0, 0) => {
899 let span: MultiSpan = spans.into();
900 err.span_note(span, msg);
901 }
902 (_, 1, 1) => {
903 let span: MultiSpan = spans.into();
904 err.span_note(span, msg);
905 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]));
906 }
907 _ => {
908 let span: MultiSpan = spans.into();
909 err.span_note(span, msg);
910 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!(
911 "and more `impl`s found in the following crates: {}{}",
912 crate_names.join(", "),
913 post,
914 ));
915 }
916 }
917 }
918}
919
920struct HasNumericInferVisitor;
921
922impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
923 type Result = ControlFlow<()>;
924
925 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
926 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(_))) {
927 ControlFlow::Break(())
928 } else {
929 ControlFlow::Continue(())
930 }
931 }
932}