1use std::ops::ControlFlow;
2
3use rustc_attr_ir::lang_items::LangItem;
4use rustc_infer::infer::InferCtxt;
5use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
6use rustc_infer::traits::{
7 self, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
8 PredicateObligation, SelectionError,
9};
10use rustc_middle::traits::query::NoSolution;
11use rustc_middle::ty::error::{ExpectedFound, TypeError};
12use rustc_middle::ty::{self, Ty, TyCtxt};
13use rustc_next_trait_solver::solve::{GoalEvaluation, MaybeInfo, SolverDelegateEvalExt as _};
14use rustc_span::{bug, span_bug};
15use tracing::{instrument, trace};
16
17use crate::solve::delegate::SolverDelegate;
18use crate::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
19use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
20use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
21
22pub(super) fn fulfillment_error_for_no_solution<'tcx>(
23 infcx: &InferCtxt<'tcx>,
24 root_obligation: PredicateObligation<'tcx>,
25) -> FulfillmentError<'tcx> {
26 let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
27
28 let code = match obligation.predicate.kind().skip_binder() {
29 ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
30 FulfillmentErrorCode::Project(
31 MismatchedProjectionTypes { err: TypeError::Mismatch },
33 )
34 }
35 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => {
36 let ct_ty = match ct.kind() {
37 ty::ConstKind::Alias(_, alias_const) => {
38 alias_const.type_of(infcx.tcx).skip_norm_wip()
39 }
40 ty::ConstKind::Param(param_ct) => {
41 param_ct.find_const_ty_from_env(obligation.param_env)
42 }
43 ty::ConstKind::Value(cv) => cv.ty,
44 kind => ::rustc_span::macros::bug_impl(Some(obligation.cause.span),
format_args!("ConstArgHasWrongType failed but we don\'t know how to compute type for {0:?}",
kind), Location::caller())span_bug!(
45 obligation.cause.span,
46 "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}"
47 ),
48 };
49 FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType {
50 ct,
51 ct_ty,
52 expected_ty,
53 })
54 }
55 ty::PredicateKind::Subtype(pred) => {
56 let (a, b) = infcx.enter_forall_and_leak_universe(
57 obligation.predicate.kind().rebind((pred.a, pred.b)),
58 );
59 let expected_found = ExpectedFound::new(a, b);
60 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
61 }
62 ty::PredicateKind::Coerce(pred) => {
63 let (a, b) = infcx.enter_forall_and_leak_universe(
64 obligation.predicate.kind().rebind((pred.a, pred.b)),
65 );
66 let expected_found = ExpectedFound::new(b, a);
67 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
68 }
69 ty::PredicateKind::Clause(
70 ty::ClauseKind::RegionOutlives(_) | ty::ClauseKind::TypeOutlives(_),
71 ) if infcx.tcx.assumptions_on_binders() => FulfillmentErrorCode::Outlives,
72 ty::PredicateKind::Clause(_)
73 | ty::PredicateKind::DynCompatible(_)
74 | ty::PredicateKind::Ambiguous => {
75 FulfillmentErrorCode::Select(SelectionError::Unimplemented)
76 }
77 ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::NormalizesTo(..) => {
78 ::rustc_span::macros::bug_impl(None,
format_args!("unexpected goal: {0:?}", obligation), Location::caller())bug!("unexpected goal: {obligation:?}")
79 }
80 };
81
82 FulfillmentError { obligation, code, root_obligation }
83}
84
85pub(super) fn fulfillment_error_for_stalled<'tcx>(
86 infcx: &InferCtxt<'tcx>,
87 root_obligation: PredicateObligation<'tcx>,
88) -> FulfillmentError<'tcx> {
89 let (code, refine_obligation) = infcx.probe(|_| {
90 match <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal(
91 root_obligation.as_goal(),
92 root_obligation.cause.span,
93 None,
94 ) {
95 Ok(GoalEvaluation {
96 certainty:
97 Certainty::Maybe(MaybeInfo {
98 cause: MaybeCause::Ambiguity,
99 opaque_types_jank: _,
100 stalled_on_coroutines: _,
101 }),
102 ..
103 }) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true),
104 Ok(GoalEvaluation {
105 certainty:
106 Certainty::Maybe(MaybeInfo {
107 cause:
108 MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
109 opaque_types_jank: _,
110 stalled_on_coroutines: _,
111 }),
112 ..
113 }) => (
114 FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
115 false,
122 ),
123 Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
124 (FulfillmentErrorCode::Ambiguity { overflow: None }, false)
128 }
129 Err(_) => {
130 ::rustc_span::macros::bug_impl(Some(root_obligation.cause.span),
format_args!("did not expect selection error when collecting ambiguity errors for `{0:?}`",
infcx.deeply_resolve_ignoring_regions(root_obligation.predicate)),
Location::caller())span_bug!(
131 root_obligation.cause.span,
132 "did not expect selection error when collecting ambiguity errors for `{:?}`",
133 infcx.deeply_resolve_ignoring_regions(root_obligation.predicate),
134 )
135 }
136 }
137 });
138
139 FulfillmentError {
140 obligation: if refine_obligation {
141 find_best_leaf_obligation(infcx, &root_obligation, true)
142 } else {
143 root_obligation.clone()
144 },
145 code,
146 root_obligation,
147 }
148}
149
150{}
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("find_best_leaf_obligation",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(150u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::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("consider_ambiguities")
}> =
::tracing::__macro_support::FieldName::new("consider_ambiguities");
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(&consider_ambiguities
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: PredicateObligation<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
let obligation =
infcx.deeply_resolve_ignoring_regions(obligation.clone());
let obligation =
infcx.fudge_inference_if_ok(||
{
infcx.visit_proof_tree(obligation.as_goal(),
&mut BestObligation {
obligation: obligation.clone(),
consider_ambiguities,
}).break_value().ok_or(()).map(|o| (o.cause.clone(), o))
}).map(|(cause, o)|
PredicateObligation { cause, ..o }).unwrap_or(obligation);
deeply_normalize_for_diagnostics(infcx,
obligation.param_env, obligation)
}
})();
{
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/solve/fulfill/derive_errors.rs:150",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(150u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "debug", skip(infcx), ret)]
151fn find_best_leaf_obligation<'tcx>(
152 infcx: &InferCtxt<'tcx>,
153 obligation: &PredicateObligation<'tcx>,
154 consider_ambiguities: bool,
155) -> PredicateObligation<'tcx> {
156 let obligation = infcx.deeply_resolve_ignoring_regions(obligation.clone());
157 let obligation = infcx
163 .fudge_inference_if_ok(|| {
164 infcx
165 .visit_proof_tree(
166 obligation.as_goal(),
167 &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
168 )
169 .break_value()
170 .ok_or(())
171 .map(|o| (o.cause.clone(), o))
174 })
175 .map(|(cause, o)| PredicateObligation { cause, ..o })
176 .unwrap_or(obligation);
177 deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
178}
179
180struct BestObligation<'tcx> {
181 obligation: PredicateObligation<'tcx>,
182 consider_ambiguities: bool,
183}
184
185impl<'tcx> BestObligation<'tcx> {
186 fn with_derived_obligation(
187 &mut self,
188 derived_obligation: PredicateObligation<'tcx>,
189 and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
190 ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
191 let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
192 let res = and_then(self);
193 self.obligation = old_obligation;
194 res
195 }
196
197 fn non_trivial_candidates<'a>(
202 &self,
203 goal: &'a inspect::InspectGoal<'a, 'tcx>,
204 ) -> Vec<inspect::InspectCandidate<'a, 'tcx>> {
205 let mut candidates = goal.candidates();
206 match self.consider_ambiguities {
207 true => {
208 candidates.retain(|candidate| candidate.result().is_ok());
212 }
213 false => {
214 candidates.retain(|c| !#[allow(non_exhaustive_omitted_patterns)] match c.kind() {
inspect::ProbeKind::RigidAlias { .. } => true,
_ => false,
}matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
217 if candidates.len() > 1 {
221 candidates.retain(|candidate| {
222 goal.infcx().probe(|_| {
223 !candidate.instantiate_nested_goals(self.span()).iter().any(
224 |nested_goal| {
225 nested_goal.source() == GoalSource::Normalization
226 && nested_goal.result().is_err()
227 },
228 )
229 })
230 });
231 }
232 }
233 }
234
235 candidates
236 }
237
238 fn visit_well_formed_goal(
242 &mut self,
243 candidate: &inspect::InspectCandidate<'_, 'tcx>,
244 term: ty::Term<'tcx>,
245 ) -> ControlFlow<PredicateObligation<'tcx>> {
246 let infcx = candidate.goal().infcx();
247 let param_env = candidate.goal().goal().param_env;
248 let body_def_id = self.obligation.cause.body_def_id;
249
250 for obligation in
251 wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_def_id)
252 .into_flat_iter()
253 {
254 let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
255 GoalSource::Misc,
256 obligation.as_goal(),
257 self.span(),
258 );
259 match (self.consider_ambiguities, nested_goal.result()) {
261 (
262 true,
263 Ok(Certainty::Maybe(MaybeInfo {
264 cause: MaybeCause::Ambiguity,
265 opaque_types_jank: _,
266 stalled_on_coroutines: _,
267 })),
268 )
269 | (false, Err(_)) => {}
270 _ => continue,
271 }
272
273 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
274 }
275
276 ControlFlow::Break(self.obligation.clone())
277 }
278
279 fn detect_error_in_self_ty_normalization(
283 &mut self,
284 goal: &inspect::InspectGoal<'_, 'tcx>,
285 self_ty: Ty<'tcx>,
286 ) -> ControlFlow<PredicateObligation<'tcx>> {
287 if !!self.consider_ambiguities {
::core::panicking::panic("assertion failed: !self.consider_ambiguities")
};assert!(!self.consider_ambiguities);
288 let tcx = goal.infcx().tcx;
289 if let ty::Alias(_, alias) = *self_ty.kind() {
290 let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span);
291 let pred =
292 ty::ProjectionClause { projection_term: alias.into(), term: infer_term.into() };
293 let obligation =
294 Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
295 self.with_derived_obligation(obligation, |this| {
296 goal.infcx().visit_proof_tree_at_depth(
297 goal.goal().with(tcx, pred),
298 goal.depth() + 1,
299 this,
300 )
301 })
302 } else {
303 ControlFlow::Continue(())
304 }
305 }
306
307 fn detect_trait_error_in_higher_ranked_projection(
315 &mut self,
316 goal: &inspect::InspectGoal<'_, 'tcx>,
317 ) -> ControlFlow<PredicateObligation<'tcx>> {
318 let tcx = goal.infcx().tcx;
319 if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
320 && !projection_clause.bound_vars().is_empty()
321 {
322 let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
323 let obligation = Obligation::new(
324 tcx,
325 self.obligation.cause.clone(),
326 goal.goal().param_env,
327 deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
328 );
329 self.with_derived_obligation(obligation, |this| {
330 goal.infcx().visit_proof_tree_at_depth(
331 goal.goal().with(tcx, pred),
332 goal.depth() + 1,
333 this,
334 )
335 })
336 } else {
337 ControlFlow::Continue(())
338 }
339 }
340
341 fn detect_non_well_formed_assoc_item(
348 &mut self,
349 goal: &inspect::InspectGoal<'_, 'tcx>,
350 alias: ty::AliasTerm<'tcx>,
351 ) -> ControlFlow<PredicateObligation<'tcx>> {
352 let tcx = goal.infcx().tcx;
353
354 let trait_ref = alias.trait_ref(tcx);
355 let obligation =
356 Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, trait_ref);
357
358 self.with_derived_obligation(obligation, |this| {
359 goal.infcx().visit_proof_tree_at_depth(
360 goal.goal().with(tcx, trait_ref),
361 goal.depth() + 1,
362 this,
363 )
364 })?;
365
366 let def_id = alias.expect_projection_def_id();
367
368 for (clause, span) in tcx.clauses_of(def_id).instantiate_own(tcx, alias.args) {
369 let clause = clause.skip_norm_wip();
370
371 let cause = ObligationCause::new(
372 self.obligation.cause.span,
373 self.obligation.cause.body_def_id,
374 ObligationCauseCode::WhereClause(def_id, span),
375 );
376
377 let obligation = Obligation::new(tcx, cause, goal.goal().param_env, clause);
378
379 self.with_derived_obligation(obligation, |this| {
380 goal.infcx().visit_proof_tree_at_depth(
381 goal.goal().with(tcx, clause),
382 goal.depth() + 1,
383 this,
384 )
385 })?;
386 }
387
388 ControlFlow::Continue(())
389 }
390
391 fn detect_error_from_empty_candidates(
394 &mut self,
395 goal: &inspect::InspectGoal<'_, 'tcx>,
396 ) -> ControlFlow<PredicateObligation<'tcx>> {
397 let pred_kind = goal.goal().predicate.kind();
398
399 match pred_kind.no_bound_vars() {
400 Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) => {
401 self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
402 }
403 Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)))
404 if pred.projection_term.kind.is_trait_projection() =>
405 {
406 self.detect_error_in_self_ty_normalization(goal, pred.projection_term.self_ty())?;
407 self.detect_non_well_formed_assoc_item(goal, pred.projection_term)?;
408 }
409 Some(_) | None => {}
410 }
411
412 ControlFlow::Break(self.obligation.clone())
413 }
414}
415
416impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
417 type Result = ControlFlow<PredicateObligation<'tcx>>;
418
419 fn span(&self) -> rustc_span::Span {
420 self.obligation.cause.span
421 }
422
423 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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("visit_goal",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(423u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
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::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&goal.goal())
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: Self::Result = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = goal.infcx().tcx;
match (self.consider_ambiguities, goal.result()) {
(true,
Ok(Certainty::Maybe(MaybeInfo {
cause: MaybeCause::Ambiguity,
opaque_types_jank: _,
stalled_on_coroutines: _ }))) | (false, Err(_)) => {}
_ => return ControlFlow::Continue(()),
}
let pred = goal.goal().predicate;
let candidates = self.non_trivial_candidates(goal);
let candidate =
match candidates.as_slice() {
[candidate] => candidate,
[] => return self.detect_error_from_empty_candidates(goal),
_ => return ControlFlow::Break(self.obligation.clone()),
};
if let inspect::ProbeKind::TraitCandidate {
source: CandidateSource::Impl(impl_def_id), result: _ } =
candidate.kind() && tcx.do_not_recommend_impl(impl_def_id) {
{
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/solve/fulfill/derive_errors.rs:456",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(456u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("#[diagnostic::do_not_recommend] -> exit")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return ControlFlow::Break(self.obligation.clone());
}
let child_mode =
match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
=> {
ChildMode::Trait(pred.kind().rebind(trait_pred))
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_clause))
=> {
ChildMode::Host(pred.kind().rebind(host_clause))
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection))
if projection.projection_term.kind.is_trait_projection() =>
{
ChildMode::Trait(pred.kind().rebind(ty::TraitClause {
trait_ref: projection.projection_term.trait_ref(tcx),
polarity: ty::ClausePolarity::Positive,
}))
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term))
=> {
return self.visit_well_formed_goal(candidate, term);
}
_ => ChildMode::PassThrough,
};
let nested_goals =
candidate.instantiate_nested_goals(self.span());
for nested_goal in &nested_goals {
if let Some(poly_trait_pred) =
nested_goal.goal().predicate.as_trait_clause() &&
tcx.is_lang_item(poly_trait_pred.def_id(),
LangItem::FnPtrTrait) &&
let Err(NoSolution) = nested_goal.result() {
return ControlFlow::Break(self.obligation.clone());
}
}
let mut impl_where_bound_count = 0;
for nested_goal in nested_goals {
{
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/solve/fulfill/derive_errors.rs:503",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(503u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("nested_goal")
}> =
::tracing::__macro_support::FieldName::new("nested_goal");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&(nested_goal.goal(),
nested_goal.source(), nested_goal.result())) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
let nested_pred = nested_goal.goal().predicate;
let make_obligation =
|cause|
Obligation {
cause,
param_env: nested_goal.goal().param_env,
predicate: nested_pred,
recursion_depth: self.obligation.recursion_depth + 1,
};
let obligation;
match (child_mode, nested_goal.source()) {
(ChildMode::Trait(_) | ChildMode::Host(_),
GoalSource::Misc | GoalSource::Normalization) => {
continue;
}
(ChildMode::Trait(parent_trait_pred),
GoalSource::ImplWhereBound) => {
obligation =
make_obligation(derive_cause(tcx, candidate.kind(),
self.obligation.cause.clone(), impl_where_bound_count,
parent_trait_pred));
impl_where_bound_count += 1;
}
(ChildMode::Host(parent_host_clause),
GoalSource::ImplWhereBound |
GoalSource::AliasBoundConstCondition) => {
obligation =
make_obligation(derive_host_cause(tcx, candidate.kind(),
self.obligation.cause.clone(), impl_where_bound_count,
parent_host_clause));
impl_where_bound_count += 1;
}
(ChildMode::PassThrough, _) |
(_,
GoalSource::AliasWellFormed |
GoalSource::AliasBoundConstCondition) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}
self.with_derived_obligation(obligation,
|this| nested_goal.visit_with(this))?;
}
self.detect_trait_error_in_higher_ranked_projection(goal)?;
ControlFlow::Break(self.obligation.clone())
}
}
}#[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
424 fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
425 let tcx = goal.infcx().tcx;
426 match (self.consider_ambiguities, goal.result()) {
428 (
429 true,
430 Ok(Certainty::Maybe(MaybeInfo {
431 cause: MaybeCause::Ambiguity,
432 opaque_types_jank: _,
433 stalled_on_coroutines: _,
434 })),
435 )
436 | (false, Err(_)) => {}
437 _ => return ControlFlow::Continue(()),
438 }
439
440 let pred = goal.goal().predicate;
441
442 let candidates = self.non_trivial_candidates(goal);
443 let candidate = match candidates.as_slice() {
444 [candidate] => candidate,
445 [] => return self.detect_error_from_empty_candidates(goal),
446 _ => return ControlFlow::Break(self.obligation.clone()),
447 };
448
449 if let inspect::ProbeKind::TraitCandidate {
451 source: CandidateSource::Impl(impl_def_id),
452 result: _,
453 } = candidate.kind()
454 && tcx.do_not_recommend_impl(impl_def_id)
455 {
456 trace!("#[diagnostic::do_not_recommend] -> exit");
457 return ControlFlow::Break(self.obligation.clone());
458 }
459
460 let child_mode = match pred.kind().skip_binder() {
463 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
464 ChildMode::Trait(pred.kind().rebind(trait_pred))
465 }
466 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_clause)) => {
467 ChildMode::Host(pred.kind().rebind(host_clause))
468 }
469 ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection))
470 if projection.projection_term.kind.is_trait_projection() =>
471 {
472 ChildMode::Trait(pred.kind().rebind(ty::TraitClause {
473 trait_ref: projection.projection_term.trait_ref(tcx),
474 polarity: ty::ClausePolarity::Positive,
475 }))
476 }
477 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
478 return self.visit_well_formed_goal(candidate, term);
479 }
480 _ => ChildMode::PassThrough,
481 };
482
483 let nested_goals = candidate.instantiate_nested_goals(self.span());
484
485 for nested_goal in &nested_goals {
493 if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
494 && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
495 && let Err(NoSolution) = nested_goal.result()
496 {
497 return ControlFlow::Break(self.obligation.clone());
498 }
499 }
500
501 let mut impl_where_bound_count = 0;
502 for nested_goal in nested_goals {
503 trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
504
505 let nested_pred = nested_goal.goal().predicate;
506
507 let make_obligation = |cause| Obligation {
508 cause,
509 param_env: nested_goal.goal().param_env,
510 predicate: nested_pred,
511 recursion_depth: self.obligation.recursion_depth + 1,
512 };
513
514 let obligation;
515 match (child_mode, nested_goal.source()) {
516 (
517 ChildMode::Trait(_) | ChildMode::Host(_),
518 GoalSource::Misc | GoalSource::Normalization,
519 ) => {
520 continue;
521 }
522 (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
523 obligation = make_obligation(derive_cause(
524 tcx,
525 candidate.kind(),
526 self.obligation.cause.clone(),
527 impl_where_bound_count,
528 parent_trait_pred,
529 ));
530 impl_where_bound_count += 1;
531 }
532 (
533 ChildMode::Host(parent_host_clause),
534 GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
535 ) => {
536 obligation = make_obligation(derive_host_cause(
537 tcx,
538 candidate.kind(),
539 self.obligation.cause.clone(),
540 impl_where_bound_count,
541 parent_host_clause,
542 ));
543 impl_where_bound_count += 1;
544 }
545 (ChildMode::PassThrough, _)
546 | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
547 obligation = make_obligation(self.obligation.cause.clone());
548 }
549 }
550
551 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
552 }
553
554 self.detect_trait_error_in_higher_ranked_projection(goal)?;
555
556 ControlFlow::Break(self.obligation.clone())
557 }
558}
559
560#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ChildMode<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Trait(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Trait",
&__self_0),
Self::Host(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Host",
&__self_0),
Self::PassThrough =>
::core::fmt::Formatter::write_str(f, "PassThrough"),
}
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ChildMode<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for ChildMode<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for ChildMode<'tcx> {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<ty::PolyTraitClause<'tcx>>;
let _:
::core::clone::AssertParamIsClone<ty::Binder<'tcx,
ty::HostEffectClause<'tcx>>>;
*self
}
}Clone)]
561enum ChildMode<'tcx> {
562 Trait(ty::PolyTraitClause<'tcx>),
566 Host(ty::Binder<'tcx, ty::HostEffectClause<'tcx>>),
570 PassThrough,
574}
575
576fn derive_cause<'tcx>(
577 tcx: TyCtxt<'tcx>,
578 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
579 mut cause: ObligationCause<'tcx>,
580 idx: usize,
581 parent_trait_pred: ty::PolyTraitClause<'tcx>,
582) -> ObligationCause<'tcx> {
583 match candidate_kind {
584 inspect::ProbeKind::TraitCandidate {
585 source: CandidateSource::Impl(impl_def_id),
586 result: _,
587 } => {
588 if let Some((_, span)) =
589 tcx.clauses_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
590 {
591 cause = cause.derived_cause(parent_trait_pred, |derived| {
592 ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
593 derived,
594 impl_or_alias_def_id: impl_def_id,
595 impl_def_clause_index: Some(idx),
596 span,
597 }))
598 })
599 }
600 }
601 inspect::ProbeKind::TraitCandidate {
602 source: CandidateSource::BuiltinImpl(..),
603 result: _,
604 } => {
605 cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived);
606 }
607 _ => {}
608 };
609 cause
610}
611
612fn derive_host_cause<'tcx>(
613 tcx: TyCtxt<'tcx>,
614 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
615 mut cause: ObligationCause<'tcx>,
616 idx: usize,
617 parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>,
618) -> ObligationCause<'tcx> {
619 match candidate_kind {
620 inspect::ProbeKind::TraitCandidate {
621 source: CandidateSource::Impl(impl_def_id),
622 result: _,
623 } => {
624 if let Some((_, span)) = tcx
625 .clauses_of(impl_def_id)
626 .instantiate_identity(tcx)
627 .into_iter()
628 .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
629 |(trait_ref, span)| {
630 (
631 trait_ref.to_host_effect_clause(
632 tcx,
633 parent_host_clause.skip_binder().constness,
634 ),
635 span,
636 )
637 },
638 ))
639 .nth(idx)
640 {
641 cause =
642 cause.derived_host_cause(parent_host_clause, |derived| {
643 ObligationCauseCode::ImplDerivedHost(Box::new(
644 traits::ImplDerivedHostCause { derived, impl_def_id, span },
645 ))
646 })
647 }
648 }
649 inspect::ProbeKind::TraitCandidate {
650 source: CandidateSource::BuiltinImpl(..),
651 result: _,
652 } => {
653 cause = cause
654 .derived_host_cause(parent_host_clause, ObligationCauseCode::BuiltinDerivedHost);
655 }
656 _ => {}
657 };
658 cause
659}