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 _, Unnormalized};
16use rustc_session::errors::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 Unnormalized::new_wip(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 =
52 tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip();
53 let impl_trait_ref = ocx.normalize(
54 &ObligationCause::dummy(),
55 param_env,
56 Unnormalized::new_wip(impl_trait_ref),
57 );
58
59 if let Err(_) =
60 ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
61 {
62 return false;
63 }
64
65 let impl_trait_header = tcx.impl_trait_header(impl_def_id);
66 let impl_polarity = impl_trait_header.polarity;
67
68 match (impl_polarity, predicate_polarity) {
69 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)
70 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {}
71 _ => return false,
72 }
73
74 let obligations = tcx
75 .predicates_of(impl_def_id)
76 .instantiate(tcx, impl_args)
77 .into_iter()
78 .map(|(predicate, _)| {
79 Obligation::new(
80 tcx,
81 ObligationCause::dummy(),
82 param_env,
83 predicate.skip_norm_wip(),
84 )
85 })
86 .filter(|obligation| {
91 infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok()
92 });
93 ocx.register_obligations(obligations);
94
95 ocx.try_evaluate_obligations().is_empty()
96 })
97 };
98
99 let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
100 let ocx = ObligationCtxt::new(infcx);
101 infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
102 let obligation_trait_ref = ocx.normalize(
103 &ObligationCause::dummy(),
104 param_env,
105 Unnormalized::new_wip(placeholder_obligation.trait_ref),
106 );
107
108 let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
109 DUMMY_SP,
110 BoundRegionConversionTime::HigherRankedType,
111 poly_trait_predicate,
112 );
113 let param_env_trait_ref = ocx.normalize(
114 &ObligationCause::dummy(),
115 param_env,
116 Unnormalized::new_wip(param_env_predicate.trait_ref),
117 );
118
119 if let Err(_) = ocx.eq(
120 &ObligationCause::dummy(),
121 param_env,
122 obligation_trait_ref,
123 param_env_trait_ref,
124 ) {
125 return false;
126 }
127
128 ocx.try_evaluate_obligations().is_empty()
129 })
130 };
131
132 let mut ambiguities = Vec::new();
133
134 tcx.for_each_relevant_impl(
135 obligation.predicate.def_id(),
136 obligation.predicate.skip_binder().trait_ref.self_ty(),
137 |impl_def_id| {
138 if infcx.probe(|_| impl_may_apply(impl_def_id)) {
139 ambiguities.push(CandidateSource::DefId(impl_def_id))
140 }
141 },
142 );
143
144 let body_id = obligation.cause.body_id;
150 if body_id != CRATE_DEF_ID {
151 let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
152 for (pred, span) in
153 elaborate(tcx, predicates.into_iter().map(|(c, s)| (c.skip_norm_wip(), s)))
154 {
155 let kind = pred.kind();
156 if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
157 && param_env_candidate_may_apply(kind.rebind(trait_pred))
158 {
159 if kind.rebind(trait_pred.trait_ref)
160 == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
161 {
162 ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
163 } else {
164 ambiguities.push(CandidateSource::ParamEnv(span))
165 }
166 }
167 }
168 }
169
170 ambiguities
171}
172
173impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
174 #[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(174u32),
::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:188",
"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(188u32),
::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:197",
"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(197u32),
::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(),
obligation, 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().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_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")]
175 pub(super) fn maybe_report_ambiguity(
176 &self,
177 obligation: &PredicateObligation<'tcx>,
178 ) -> ErrorGuaranteed {
179 let predicate = self.resolve_vars_if_possible(obligation.predicate);
185 let span = obligation.cause.span;
186 let mut long_ty_path = None;
187
188 debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
189
190 let bound_predicate = predicate.kind();
194 let mut err = match bound_predicate.skip_binder() {
195 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
196 let trait_pred = bound_predicate.rebind(data);
197 debug!(?trait_pred);
198
199 if let Err(e) = predicate.error_reported() {
200 return e;
201 }
202
203 if let Err(guar) = self.tcx.ensure_result().coherent_trait(trait_pred.def_id()) {
204 return guar;
207 }
208
209 if matches!(
225 self.tcx.as_lang_item(trait_pred.def_id()),
226 Some(LangItem::Sized | LangItem::MetaSized)
227 ) {
228 return match self.tainted_by_errors() {
229 None => self
230 .emit_inference_failure_err(
231 obligation.cause.body_id,
232 span,
233 trait_pred.self_ty().skip_binder().into(),
234 TypeAnnotationNeeded::E0282,
235 false,
236 )
237 .emit(),
238 Some(e) => e,
239 };
240 }
241
242 let term = data
256 .trait_ref
257 .args
258 .iter()
259 .filter_map(ty::GenericArg::as_term)
260 .find(|s| s.has_non_region_infer());
261
262 let mut err = if let Some(term) = term {
263 let candidates: Vec<_> = self
264 .tcx
265 .all_impls(trait_pred.def_id())
266 .filter_map(|def_id| {
267 let imp = self.tcx.impl_trait_header(def_id);
268 if imp.polarity != ty::ImplPolarity::Positive
269 || !self.tcx.is_user_visible_dep(def_id.krate)
270 {
271 return None;
272 }
273 let imp = imp.trait_ref.skip_binder();
274 if imp
275 .with_replaced_self_ty(self.tcx, trait_pred.skip_binder().self_ty())
276 == trait_pred.skip_binder().trait_ref
277 {
278 Some(imp.self_ty())
279 } else {
280 None
281 }
282 })
283 .collect();
284 self.emit_inference_failure_err_with_type_hint(
285 obligation.cause.body_id,
286 span,
287 term,
288 TypeAnnotationNeeded::E0283,
289 true,
290 match &candidates[..] {
291 [candidate] => Some(*candidate),
292 _ => None,
293 },
294 )
295 } else {
296 struct_span_code_err!(
297 self.dcx(),
298 span,
299 E0283,
300 "type annotations needed: cannot satisfy `{}`",
301 self.tcx.short_string(predicate, &mut long_ty_path),
302 )
303 .with_long_ty_path(long_ty_path)
304 };
305
306 let mut ambiguities = compute_applicable_impls_for_diagnostics(
307 self.infcx,
308 &obligation.with(self.tcx, trait_pred),
309 );
310 let has_non_region_infer = trait_pred
311 .skip_binder()
312 .trait_ref
313 .args
314 .types()
315 .any(|t| !t.is_ty_or_numeric_infer());
316 if ambiguities.len() > 5 {
320 let infcx = self.infcx;
321 if !ambiguities.iter().all(|option| match option {
322 CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
323 CandidateSource::ParamEnv(_) => true,
324 }) {
325 ambiguities.retain(|option| match option {
327 CandidateSource::DefId(did) => infcx.tcx.generics_of(*did).count() == 0,
328 CandidateSource::ParamEnv(_) => true,
329 });
330 }
331 }
332 if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
333 if let Some(e) = self.tainted_by_errors()
334 && term.is_none()
335 {
336 err.cancel();
341 return e;
342 }
343 self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate);
344 } else {
345 if let Some(e) = self.tainted_by_errors() {
346 err.cancel();
347 return e;
348 }
349 if let Some(clause) = predicate.as_trait_clause()
350 && let ty::Infer(_) = clause.self_ty().skip_binder().kind()
351 {
352 let tr = self.tcx.short_string(
353 clause.print_modifiers_and_trait_path(),
354 &mut err.long_ty_path(),
355 );
356 err.note(format!("the type must implement `{tr}`"));
357 } else {
358 let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
359 err.note(format!("cannot satisfy `{pred}`"));
360 }
361 let impl_candidates =
362 self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
363 if impl_candidates.len() < 40 {
364 self.report_similar_impl_candidates(
365 impl_candidates.as_slice(),
366 obligation,
367 trait_pred,
368 obligation.cause.body_id,
369 &mut err,
370 false,
371 obligation.param_env,
372 );
373 }
374 }
375
376 if let ObligationCauseCode::WhereClause(def_id, _)
377 | ObligationCauseCode::WhereClauseInExpr(def_id, ..) = *obligation.cause.code()
378 {
379 self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id());
380 }
381
382 if term.is_some_and(|term| term.as_type().is_some())
383 && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id)
384 {
385 let mut expr_finder = FindExprBySpan::new(span, self.tcx);
386 expr_finder.visit_expr(&body.value);
387
388 if let Some(hir::Expr {
389 kind:
390 hir::ExprKind::Call(
391 hir::Expr {
392 kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
393 ..
394 },
395 _,
396 )
397 | hir::ExprKind::Path(hir::QPath::Resolved(None, path)),
398 ..
399 }) = expr_finder.result
400 && let [
401 ..,
402 trait_path_segment @ hir::PathSegment {
403 res: Res::Def(DefKind::Trait, trait_id),
404 ..
405 },
406 hir::PathSegment {
407 ident: assoc_item_ident,
408 res: Res::Def(_, item_id),
409 ..
410 },
411 ] = path.segments
412 && data.trait_ref.def_id == *trait_id
413 && self.tcx.trait_of_assoc(*item_id) == Some(*trait_id)
414 && let None = self.tainted_by_errors()
415 {
416 let assoc_item = self.tcx.associated_item(*item_id);
417 let (verb, noun) = match assoc_item.kind {
418 ty::AssocKind::Const { .. } => ("refer to the", "constant"),
419 ty::AssocKind::Fn { .. } => ("call", "function"),
420 ty::AssocKind::Type { .. } => ("refer to the", "type"),
423 };
424
425 err.cancel();
427 err = self.dcx().struct_span_err(
428 span,
429 format!(
430 "cannot {verb} associated {noun} on trait without specifying the \
431 corresponding `impl` type",
432 ),
433 );
434 err.code(E0790);
435
436 if item_id.is_local() {
437 let trait_ident = self.tcx.item_name(*trait_id);
438 err.span_label(
439 self.tcx.def_span(*item_id),
440 format!("`{trait_ident}::{assoc_item_ident}` defined here"),
441 );
442 }
443
444 err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
445
446 let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
447
448 if let Some(&impl_def_id) =
449 trait_impls.non_blanket_impls().values().flatten().next()
450 {
451 let non_blanket_impl_count =
452 trait_impls.non_blanket_impls().values().flatten().count();
453 let (message, self_types) = if non_blanket_impl_count == 1 {
456 (
457 "use the fully-qualified path to the only available \
458 implementation",
459 vec![format!(
460 "{}",
461 self.tcx
462 .type_of(impl_def_id)
463 .instantiate_identity()
464 .skip_norm_wip()
465 )],
466 )
467 } else if non_blanket_impl_count < 20 {
468 (
469 "use a fully-qualified path to one of the available \
470 implementations",
471 trait_impls
472 .non_blanket_impls()
473 .values()
474 .flatten()
475 .map(|&id| {
476 format!(
477 "{}",
478 self.tcx
479 .type_of(id)
480 .instantiate_identity()
481 .skip_norm_wip()
482 )
483 })
484 .collect::<Vec<String>>(),
485 )
486 } else {
487 (
488 "use a fully-qualified path to a specific available \
489 implementation",
490 vec!["/* self type */".to_string()],
491 )
492 };
493 let suggestions: Vec<_> = self_types
494 .into_iter()
495 .map(|self_type| {
496 let mut suggestions = vec![(
497 path.span.shrink_to_lo(),
498 format!("<{self_type} as "),
499 )];
500 if let Some(generic_arg) = trait_path_segment.args {
501 let between_span = trait_path_segment
502 .ident
503 .span
504 .between(generic_arg.span_ext);
505 suggestions.push((between_span, "".to_string()));
508 suggestions.push((
509 generic_arg.span_ext.shrink_to_hi(),
510 ">".to_string(),
511 ));
512 } else {
513 suggestions.push((
514 trait_path_segment.ident.span.shrink_to_hi(),
515 ">".to_string(),
516 ));
517 }
518 suggestions
519 })
520 .collect();
521 err.multipart_suggestions(
522 message,
523 suggestions,
524 Applicability::MaybeIncorrect,
525 );
526 }
527 }
528 };
529
530 err
531 }
532
533 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
534 if let Err(e) = term.error_reported() {
538 return e;
539 }
540 if let Some(e) = self.tainted_by_errors() {
541 return e;
542 }
543
544 self.emit_inference_failure_err(
545 obligation.cause.body_id,
546 span,
547 term,
548 TypeAnnotationNeeded::E0282,
549 false,
550 )
551 }
552
553 ty::PredicateKind::Subtype(data) => {
554 if let Err(e) = data.error_reported() {
555 return e;
556 }
557 if let Some(e) = self.tainted_by_errors() {
558 return e;
559 }
560 let ty::SubtypePredicate { a_is_expected: _, a, b } = data;
561 assert!(a.is_ty_var() && b.is_ty_var());
563 self.emit_inference_failure_err(
564 obligation.cause.body_id,
565 span,
566 a.into(),
567 TypeAnnotationNeeded::E0282,
568 true,
569 )
570 }
571
572 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
573 if let Err(e) = predicate.error_reported() {
574 return e;
575 }
576 if let Some(e) = self.tainted_by_errors() {
577 return e;
578 }
579
580 if let Err(guar) = self
581 .tcx
582 .ensure_result()
583 .coherent_trait(self.tcx.parent(data.projection_term.def_id()))
584 {
585 return guar;
588 }
589 let term = data
590 .projection_term
591 .args
592 .iter()
593 .filter_map(ty::GenericArg::as_term)
594 .chain([data.term])
595 .find(|g| g.has_non_region_infer());
596 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
597 if let Some(term) = term {
598 self.emit_inference_failure_err(
599 obligation.cause.body_id,
600 span,
601 term,
602 TypeAnnotationNeeded::E0284,
603 true,
604 )
605 .with_note(format!("cannot satisfy `{predicate}`"))
606 .with_long_ty_path(long_ty_path)
607 } else {
608 struct_span_code_err!(
610 self.dcx(),
611 span,
612 E0284,
613 "type annotations needed: cannot satisfy `{predicate}`",
614 )
615 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
616 .with_long_ty_path(long_ty_path)
617 }
618 }
619
620 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => {
621 if let Err(e) = predicate.error_reported() {
622 return e;
623 }
624 if let Some(e) = self.tainted_by_errors() {
625 return e;
626 }
627 let term =
628 data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
629 if let Some(term) = term {
630 self.emit_inference_failure_err(
631 obligation.cause.body_id,
632 span,
633 term,
634 TypeAnnotationNeeded::E0284,
635 true,
636 )
637 } else {
638 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
640 struct_span_code_err!(
641 self.dcx(),
642 span,
643 E0284,
644 "type annotations needed: cannot satisfy `{predicate}`",
645 )
646 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
647 .with_long_ty_path(long_ty_path)
648 }
649 }
650
651 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ..)) => self
652 .emit_inference_failure_err(
653 obligation.cause.body_id,
654 span,
655 ct.into(),
656 TypeAnnotationNeeded::E0284,
657 true,
658 ),
659
660 ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
661 if term.is_infer() =>
662 {
663 if let Some(e) = self.tainted_by_errors() {
664 return e;
665 }
666 let alias = self.tcx.short_string(alias, &mut long_ty_path);
667 struct_span_code_err!(
668 self.dcx(),
669 span,
670 E0284,
671 "type annotations needed: cannot normalize `{alias}`",
672 )
673 .with_span_label(span, format!("cannot normalize `{alias}`"))
674 .with_long_ty_path(long_ty_path)
675 }
676
677 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
678 if let Some(e) = self.tainted_by_errors() {
679 return e;
680 }
681
682 if self.tcx.features().staged_api() {
683 self.dcx().struct_span_err(
684 span,
685 format!("unstable feature `{sym}` is used without being enabled."),
686 ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
687 } else {
688 feature_err_unstable_feature_bound(
689 &self.tcx.sess,
690 sym,
691 span,
692 format!("use of unstable library feature `{sym}`"),
693 )
694 }
695 }
696
697 _ => {
698 if let Some(e) = self.tainted_by_errors() {
699 return e;
700 }
701 let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
702 struct_span_code_err!(
703 self.dcx(),
704 span,
705 E0284,
706 "type annotations needed: cannot satisfy `{predicate}`",
707 )
708 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
709 .with_long_ty_path(long_ty_path)
710 }
711 };
712 self.note_obligation_cause(&mut err, obligation);
713 err.emit()
714 }
715
716 fn annotate_source_of_ambiguity(
717 &self,
718 err: &mut Diag<'_>,
719 ambiguities: &[CandidateSource],
720 predicate: ty::Predicate<'tcx>,
721 ) {
722 let mut spans = ::alloc::vec::Vec::new()vec![];
723 let mut crates = ::alloc::vec::Vec::new()vec![];
724 let mut post = ::alloc::vec::Vec::new()vec![];
725 let mut has_param_env = false;
726 for ambiguity in ambiguities {
727 match ambiguity {
728 CandidateSource::DefId(impl_def_id) => match self.tcx.span_of_impl(*impl_def_id) {
729 Ok(span) => spans.push(span),
730 Err(name) => {
731 crates.push(name);
732 if let Some(header) = to_pretty_impl_header(self.tcx, *impl_def_id) {
733 post.push(header);
734 }
735 }
736 },
737 CandidateSource::ParamEnv(span) => {
738 has_param_env = true;
739 spans.push(*span);
740 }
741 }
742 }
743 let mut crate_names: Vec<_> = crates.iter().map(|n| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")).collect();
744 crate_names.sort();
745 crate_names.dedup();
746 post.sort();
747 post.dedup();
748
749 if self.tainted_by_errors().is_some()
750 && (crate_names.len() == 1
751 && spans.len() == 0
752 && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
753 || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
754 {
755 err.downgrade_to_delayed_bug();
761 return;
762 }
763
764 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!(
765 "multiple `impl`s{} satisfying `{}` found",
766 if has_param_env { " or `where` clauses" } else { "" },
767 predicate
768 );
769 let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
770 ::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"))
771 } else if post.len() == 1 {
772 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": `{0}`", post[0]))
})format!(": `{}`", post[0])
773 } else {
774 String::new()
775 };
776
777 match (spans.len(), crates.len(), crate_names.len()) {
778 (0, 0, 0) => {
779 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot satisfy `{0}`", predicate))
})format!("cannot satisfy `{predicate}`"));
780 }
781 (0, _, 1) => {
782 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]));
783 }
784 (0, _, _) => {
785 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} in the following crates: {1}{2}",
msg, crate_names.join(", "), post))
})format!(
786 "{} in the following crates: {}{}",
787 msg,
788 crate_names.join(", "),
789 post,
790 ));
791 }
792 (_, 0, 0) => {
793 let span: MultiSpan = spans.into();
794 err.span_note(span, msg);
795 }
796 (_, 1, 1) => {
797 let span: MultiSpan = spans.into();
798 err.span_note(span, msg);
799 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]));
800 }
801 _ => {
802 let span: MultiSpan = spans.into();
803 err.span_note(span, msg);
804 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!(
805 "and more `impl`s found in the following crates: {}{}",
806 crate_names.join(", "),
807 post,
808 ));
809 }
810 }
811 }
812}
813
814struct HasNumericInferVisitor;
815
816impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
817 type Result = ControlFlow<()>;
818
819 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
820 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(_))) {
821 ControlFlow::Break(())
822 } else {
823 ControlFlow::Continue(())
824 }
825 }
826}