1use std::ops::ControlFlow;
2
3use rustc_hir::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_middle::{bug, span_bug};
14use rustc_next_trait_solver::solve::{GoalEvaluation, MaybeInfo, SolverDelegateEvalExt as _};
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::Unevaluated(uv) => {
38 infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).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_middle::util::bug::span_bug_fmt(obligation.cause.span,
format_args!("ConstArgHasWrongType failed but we don\'t know how to compute type for {0:?}",
kind))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::NormalizesTo(..) => {
56 FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
57 }
58 ty::PredicateKind::AliasRelate(_, _, _) => {
59 FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
60 }
61 ty::PredicateKind::Subtype(pred) => {
62 let (a, b) = infcx.enter_forall_and_leak_universe(
63 obligation.predicate.kind().rebind((pred.a, pred.b)),
64 );
65 let expected_found = ExpectedFound::new(a, b);
66 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
67 }
68 ty::PredicateKind::Coerce(pred) => {
69 let (a, b) = infcx.enter_forall_and_leak_universe(
70 obligation.predicate.kind().rebind((pred.a, pred.b)),
71 );
72 let expected_found = ExpectedFound::new(b, a);
73 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
74 }
75 ty::PredicateKind::Clause(_)
76 | ty::PredicateKind::DynCompatible(_)
77 | ty::PredicateKind::Ambiguous => {
78 FulfillmentErrorCode::Select(SelectionError::Unimplemented)
79 }
80 ty::PredicateKind::ConstEquate(..) => {
81 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected goal: {0:?}",
obligation))bug!("unexpected goal: {obligation:?}")
82 }
83 };
84
85 FulfillmentError { obligation, code, root_obligation }
86}
87
88pub(super) fn fulfillment_error_for_stalled<'tcx>(
89 infcx: &InferCtxt<'tcx>,
90 root_obligation: PredicateObligation<'tcx>,
91) -> FulfillmentError<'tcx> {
92 let (code, refine_obligation) = infcx.probe(|_| {
93 match <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal(
94 root_obligation.as_goal(),
95 root_obligation.cause.span,
96 None,
97 ) {
98 Ok(GoalEvaluation {
99 certainty:
100 Certainty::Maybe(MaybeInfo {
101 cause: MaybeCause::Ambiguity,
102 opaque_types_jank: _,
103 stalled_on_coroutines: _,
104 }),
105 ..
106 }) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true),
107 Ok(GoalEvaluation {
108 certainty:
109 Certainty::Maybe(MaybeInfo {
110 cause:
111 MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
112 opaque_types_jank: _,
113 stalled_on_coroutines: _,
114 }),
115 ..
116 }) => (
117 FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
118 false,
125 ),
126 Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
127 ::rustc_middle::util::bug::span_bug_fmt(root_obligation.cause.span,
format_args!("did not expect successful goal when collecting ambiguity errors for `{0:?}`",
infcx.resolve_vars_if_possible(root_obligation.predicate)))span_bug!(
128 root_obligation.cause.span,
129 "did not expect successful goal when collecting ambiguity errors for `{:?}`",
130 infcx.resolve_vars_if_possible(root_obligation.predicate),
131 )
132 }
133 Err(_) => {
134 ::rustc_middle::util::bug::span_bug_fmt(root_obligation.cause.span,
format_args!("did not expect selection error when collecting ambiguity errors for `{0:?}`",
infcx.resolve_vars_if_possible(root_obligation.predicate)))span_bug!(
135 root_obligation.cause.span,
136 "did not expect selection error when collecting ambiguity errors for `{:?}`",
137 infcx.resolve_vars_if_possible(root_obligation.predicate),
138 )
139 }
140 }
141 });
142
143 FulfillmentError {
144 obligation: if refine_obligation {
145 find_best_leaf_obligation(infcx, &root_obligation, true)
146 } else {
147 root_obligation.clone()
148 },
149 code,
150 root_obligation,
151 }
152}
153
154pub(super) fn fulfillment_error_for_overflow<'tcx>(
155 infcx: &InferCtxt<'tcx>,
156 root_obligation: PredicateObligation<'tcx>,
157) -> FulfillmentError<'tcx> {
158 FulfillmentError {
159 obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
160 code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
161 root_obligation,
162 }
163}
164
165x;#[instrument(level = "debug", skip(infcx), ret)]
166fn find_best_leaf_obligation<'tcx>(
167 infcx: &InferCtxt<'tcx>,
168 obligation: &PredicateObligation<'tcx>,
169 consider_ambiguities: bool,
170) -> PredicateObligation<'tcx> {
171 let obligation = infcx.resolve_vars_if_possible(obligation.clone());
172 let obligation = infcx
178 .fudge_inference_if_ok(|| {
179 infcx
180 .visit_proof_tree(
181 obligation.as_goal(),
182 &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
183 )
184 .break_value()
185 .ok_or(())
186 .map(|o| (o.cause.clone(), o))
189 })
190 .map(|(cause, o)| PredicateObligation { cause, ..o })
191 .unwrap_or(obligation);
192 deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
193}
194
195struct BestObligation<'tcx> {
196 obligation: PredicateObligation<'tcx>,
197 consider_ambiguities: bool,
198}
199
200impl<'tcx> BestObligation<'tcx> {
201 fn with_derived_obligation(
202 &mut self,
203 derived_obligation: PredicateObligation<'tcx>,
204 and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
205 ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
206 let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
207 let res = and_then(self);
208 self.obligation = old_obligation;
209 res
210 }
211
212 fn non_trivial_candidates<'a>(
217 &self,
218 goal: &'a inspect::InspectGoal<'a, 'tcx>,
219 ) -> Vec<inspect::InspectCandidate<'a, 'tcx>> {
220 let mut candidates = goal.candidates();
221 match self.consider_ambiguities {
222 true => {
223 candidates.retain(|candidate| candidate.result().is_ok());
227 }
228 false => {
229 candidates.retain(|c| !#[allow(non_exhaustive_omitted_patterns)] match c.kind() {
inspect::ProbeKind::RigidAlias { .. } => true,
_ => false,
}matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
232 if candidates.len() > 1 {
236 candidates.retain(|candidate| {
237 goal.infcx().probe(|_| {
238 candidate.instantiate_nested_goals(self.span()).iter().any(
239 |nested_goal| {
240 #[allow(non_exhaustive_omitted_patterns)] match nested_goal.source() {
GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition |
GoalSource::AliasWellFormed => true,
_ => false,
}matches!(
241 nested_goal.source(),
242 GoalSource::ImplWhereBound
243 | GoalSource::AliasBoundConstCondition
244 | GoalSource::AliasWellFormed
245 ) && nested_goal.result().is_err()
246 },
247 )
248 })
249 });
250 }
251 }
252 }
253
254 candidates
255 }
256
257 fn visit_well_formed_goal(
261 &mut self,
262 candidate: &inspect::InspectCandidate<'_, 'tcx>,
263 term: ty::Term<'tcx>,
264 ) -> ControlFlow<PredicateObligation<'tcx>> {
265 let infcx = candidate.goal().infcx();
266 let param_env = candidate.goal().goal().param_env;
267 let body_id = self.obligation.cause.body_id;
268
269 for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id)
270 .into_iter()
271 .flatten()
272 {
273 let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
274 GoalSource::Misc,
275 obligation.as_goal(),
276 self.span(),
277 );
278 match (self.consider_ambiguities, nested_goal.result()) {
280 (
281 true,
282 Ok(Certainty::Maybe(MaybeInfo {
283 cause: MaybeCause::Ambiguity,
284 opaque_types_jank: _,
285 stalled_on_coroutines: _,
286 })),
287 )
288 | (false, Err(_)) => {}
289 _ => continue,
290 }
291
292 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
293 }
294
295 ControlFlow::Break(self.obligation.clone())
296 }
297
298 fn detect_error_in_self_ty_normalization(
302 &mut self,
303 goal: &inspect::InspectGoal<'_, 'tcx>,
304 self_ty: Ty<'tcx>,
305 ) -> ControlFlow<PredicateObligation<'tcx>> {
306 if !!self.consider_ambiguities {
::core::panicking::panic("assertion failed: !self.consider_ambiguities")
};assert!(!self.consider_ambiguities);
307 let tcx = goal.infcx().tcx;
308 if let ty::Alias(..) = self_ty.kind() {
309 let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span);
310 let pred = ty::PredicateKind::AliasRelate(
311 self_ty.into(),
312 infer_term.into(),
313 ty::AliasRelationDirection::Equate,
314 );
315 let obligation =
316 Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
317 self.with_derived_obligation(obligation, |this| {
318 goal.infcx().visit_proof_tree_at_depth(
319 goal.goal().with(tcx, pred),
320 goal.depth() + 1,
321 this,
322 )
323 })
324 } else {
325 ControlFlow::Continue(())
326 }
327 }
328
329 fn detect_trait_error_in_higher_ranked_projection(
337 &mut self,
338 goal: &inspect::InspectGoal<'_, 'tcx>,
339 ) -> ControlFlow<PredicateObligation<'tcx>> {
340 let tcx = goal.infcx().tcx;
341 if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
342 && !projection_clause.bound_vars().is_empty()
343 {
344 let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
345 let obligation = Obligation::new(
346 tcx,
347 self.obligation.cause.clone(),
348 goal.goal().param_env,
349 deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
350 );
351 self.with_derived_obligation(obligation, |this| {
352 goal.infcx().visit_proof_tree_at_depth(
353 goal.goal().with(tcx, pred),
354 goal.depth() + 1,
355 this,
356 )
357 })
358 } else {
359 ControlFlow::Continue(())
360 }
361 }
362
363 fn detect_non_well_formed_assoc_item(
370 &mut self,
371 goal: &inspect::InspectGoal<'_, 'tcx>,
372 alias: ty::AliasTerm<'tcx>,
373 ) -> ControlFlow<PredicateObligation<'tcx>> {
374 let tcx = goal.infcx().tcx;
375 let obligation = Obligation::new(
376 tcx,
377 self.obligation.cause.clone(),
378 goal.goal().param_env,
379 alias.trait_ref(tcx),
380 );
381 self.with_derived_obligation(obligation, |this| {
382 goal.infcx().visit_proof_tree_at_depth(
383 goal.goal().with(tcx, alias.trait_ref(tcx)),
384 goal.depth() + 1,
385 this,
386 )
387 })
388 }
389
390 fn detect_error_from_empty_candidates(
393 &mut self,
394 goal: &inspect::InspectGoal<'_, 'tcx>,
395 ) -> ControlFlow<PredicateObligation<'tcx>> {
396 let tcx = goal.infcx().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::NormalizesTo(pred))
404 if let ty::AliasTermKind::ProjectionTy { .. }
405 | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind(tcx) =>
406 {
407 self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?;
408 self.detect_non_well_formed_assoc_item(goal, pred.alias)?;
409 }
410 Some(_) | None => {}
411 }
412
413 ControlFlow::Break(self.obligation.clone())
414 }
415}
416
417impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
418 type Result = ControlFlow<PredicateObligation<'tcx>>;
419
420 fn span(&self) -> rustc_span::Span {
421 self.obligation.cause.span
422 }
423
424 #[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("compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(424u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&["goal"],
::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};
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(&debug(&goal.goal())
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: 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 compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:457",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(457u32),
::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};
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(&format_args!("#[diagnostic::do_not_recommend] -> exit")
as &dyn 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_pred))
=> {
ChildMode::Host(pred.kind().rebind(host_pred))
}
ty::PredicateKind::NormalizesTo(normalizes_to) if
#[allow(non_exhaustive_omitted_patterns)] match normalizes_to.alias.kind(tcx)
{
ty::AliasTermKind::ProjectionTy { .. } |
ty::AliasTermKind::ProjectionConst { .. } => true,
_ => false,
} => {
ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate {
trait_ref: normalizes_to.alias.trait_ref(tcx),
polarity: ty::PredicatePolarity::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 compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:508",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(508u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::solve::fulfill::derive_errors"),
::tracing_core::field::FieldSet::new(&["nested_goal"],
::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};
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(&(nested_goal.goal(),
nested_goal.source(), nested_goal.result())) as
&dyn 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::TypeRelating |
GoalSource::NormalizeGoal(_)) => {
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_pred),
GoalSource::ImplWhereBound |
GoalSource::AliasBoundConstCondition) => {
obligation =
make_obligation(derive_host_cause(tcx, candidate.kind(),
self.obligation.cause.clone(), impl_where_bound_count,
parent_host_pred));
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))?;
}
if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) =
pred.kind().no_bound_vars() {
goal.infcx().visit_proof_tree_at_depth(goal.goal().with(tcx,
ty::ClauseKind::WellFormed(lhs.into())), goal.depth() + 1,
self)?;
goal.infcx().visit_proof_tree_at_depth(goal.goal().with(tcx,
ty::ClauseKind::WellFormed(rhs.into())), goal.depth() + 1,
self)?;
}
self.detect_trait_error_in_higher_ranked_projection(goal)?;
ControlFlow::Break(self.obligation.clone())
}
}
}#[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
425 fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
426 let tcx = goal.infcx().tcx;
427 match (self.consider_ambiguities, goal.result()) {
429 (
430 true,
431 Ok(Certainty::Maybe(MaybeInfo {
432 cause: MaybeCause::Ambiguity,
433 opaque_types_jank: _,
434 stalled_on_coroutines: _,
435 })),
436 )
437 | (false, Err(_)) => {}
438 _ => return ControlFlow::Continue(()),
439 }
440
441 let pred = goal.goal().predicate;
442
443 let candidates = self.non_trivial_candidates(goal);
444 let candidate = match candidates.as_slice() {
445 [candidate] => candidate,
446 [] => return self.detect_error_from_empty_candidates(goal),
447 _ => return ControlFlow::Break(self.obligation.clone()),
448 };
449
450 if let inspect::ProbeKind::TraitCandidate {
452 source: CandidateSource::Impl(impl_def_id),
453 result: _,
454 } = candidate.kind()
455 && tcx.do_not_recommend_impl(impl_def_id)
456 {
457 trace!("#[diagnostic::do_not_recommend] -> exit");
458 return ControlFlow::Break(self.obligation.clone());
459 }
460
461 let child_mode = match pred.kind().skip_binder() {
464 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
465 ChildMode::Trait(pred.kind().rebind(trait_pred))
466 }
467 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => {
468 ChildMode::Host(pred.kind().rebind(host_pred))
469 }
470 ty::PredicateKind::NormalizesTo(normalizes_to)
471 if matches!(
472 normalizes_to.alias.kind(tcx),
473 ty::AliasTermKind::ProjectionTy { .. }
474 | ty::AliasTermKind::ProjectionConst { .. }
475 ) =>
476 {
477 ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate {
478 trait_ref: normalizes_to.alias.trait_ref(tcx),
479 polarity: ty::PredicatePolarity::Positive,
480 }))
481 }
482 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
483 return self.visit_well_formed_goal(candidate, term);
484 }
485 _ => ChildMode::PassThrough,
486 };
487
488 let nested_goals = candidate.instantiate_nested_goals(self.span());
489
490 for nested_goal in &nested_goals {
498 if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
499 && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
500 && let Err(NoSolution) = nested_goal.result()
501 {
502 return ControlFlow::Break(self.obligation.clone());
503 }
504 }
505
506 let mut impl_where_bound_count = 0;
507 for nested_goal in nested_goals {
508 trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
509
510 let nested_pred = nested_goal.goal().predicate;
511
512 let make_obligation = |cause| Obligation {
513 cause,
514 param_env: nested_goal.goal().param_env,
515 predicate: nested_pred,
516 recursion_depth: self.obligation.recursion_depth + 1,
517 };
518
519 let obligation;
520 match (child_mode, nested_goal.source()) {
521 (
522 ChildMode::Trait(_) | ChildMode::Host(_),
523 GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
524 ) => {
525 continue;
526 }
527 (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
528 obligation = make_obligation(derive_cause(
529 tcx,
530 candidate.kind(),
531 self.obligation.cause.clone(),
532 impl_where_bound_count,
533 parent_trait_pred,
534 ));
535 impl_where_bound_count += 1;
536 }
537 (
538 ChildMode::Host(parent_host_pred),
539 GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
540 ) => {
541 obligation = make_obligation(derive_host_cause(
542 tcx,
543 candidate.kind(),
544 self.obligation.cause.clone(),
545 impl_where_bound_count,
546 parent_host_pred,
547 ));
548 impl_where_bound_count += 1;
549 }
550 (ChildMode::PassThrough, _)
551 | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
552 obligation = make_obligation(self.obligation.cause.clone());
553 }
554 }
555
556 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
557 }
558
559 if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() {
562 goal.infcx().visit_proof_tree_at_depth(
563 goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())),
564 goal.depth() + 1,
565 self,
566 )?;
567 goal.infcx().visit_proof_tree_at_depth(
568 goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())),
569 goal.depth() + 1,
570 self,
571 )?;
572 }
573
574 self.detect_trait_error_in_higher_ranked_projection(goal)?;
575
576 ControlFlow::Break(self.obligation.clone())
577 }
578}
579
580#[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 {
ChildMode::Trait(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Trait",
&__self_0),
ChildMode::Host(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Host",
&__self_0),
ChildMode::PassThrough =>
::core::fmt::Formatter::write_str(f, "PassThrough"),
}
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ChildMode<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ChildMode<'tcx> {
#[inline]
fn clone(&self) -> ChildMode<'tcx> {
let _:
::core::clone::AssertParamIsClone<ty::PolyTraitPredicate<'tcx>>;
let _:
::core::clone::AssertParamIsClone<ty::Binder<'tcx,
ty::HostEffectPredicate<'tcx>>>;
*self
}
}Clone)]
581enum ChildMode<'tcx> {
582 Trait(ty::PolyTraitPredicate<'tcx>),
586 Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>),
590 PassThrough,
594}
595
596fn derive_cause<'tcx>(
597 tcx: TyCtxt<'tcx>,
598 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
599 mut cause: ObligationCause<'tcx>,
600 idx: usize,
601 parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
602) -> ObligationCause<'tcx> {
603 match candidate_kind {
604 inspect::ProbeKind::TraitCandidate {
605 source: CandidateSource::Impl(impl_def_id),
606 result: _,
607 } => {
608 if let Some((_, span)) =
609 tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
610 {
611 cause = cause.derived_cause(parent_trait_pred, |derived| {
612 ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
613 derived,
614 impl_or_alias_def_id: impl_def_id,
615 impl_def_predicate_index: Some(idx),
616 span,
617 }))
618 })
619 }
620 }
621 inspect::ProbeKind::TraitCandidate {
622 source: CandidateSource::BuiltinImpl(..),
623 result: _,
624 } => {
625 cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived);
626 }
627 _ => {}
628 };
629 cause
630}
631
632fn derive_host_cause<'tcx>(
633 tcx: TyCtxt<'tcx>,
634 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
635 mut cause: ObligationCause<'tcx>,
636 idx: usize,
637 parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
638) -> ObligationCause<'tcx> {
639 match candidate_kind {
640 inspect::ProbeKind::TraitCandidate {
641 source: CandidateSource::Impl(impl_def_id),
642 result: _,
643 } => {
644 if let Some((_, span)) = tcx
645 .predicates_of(impl_def_id)
646 .instantiate_identity(tcx)
647 .into_iter()
648 .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
649 |(trait_ref, span)| {
650 (
651 trait_ref.to_host_effect_clause(
652 tcx,
653 parent_host_pred.skip_binder().constness,
654 ),
655 span,
656 )
657 },
658 ))
659 .nth(idx)
660 {
661 cause =
662 cause.derived_host_cause(parent_host_pred, |derived| {
663 ObligationCauseCode::ImplDerivedHost(Box::new(
664 traits::ImplDerivedHostCause { derived, impl_def_id, span },
665 ))
666 })
667 }
668 }
669 inspect::ProbeKind::TraitCandidate {
670 source: CandidateSource::BuiltinImpl(..),
671 result: _,
672 } => {
673 cause =
674 cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost);
675 }
676 _ => {}
677 };
678 cause
679}