1use std::ops::ControlFlow;
2
3use rustc_hir::attrs::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_middle::{bug, span_bug};
14use rustc_next_trait_solver::solve::{GoalEvaluation, MaybeInfo, SolverDelegateEvalExt as _};
15use tracing::{instrument, trace};
16
17use super::NextSolverAmbiguityError;
18use crate::solve::delegate::SolverDelegate;
19use crate::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
20use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
21use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
22
23pub(super) fn fulfillment_error_for_no_solution<'tcx>(
24 infcx: &InferCtxt<'tcx>,
25 root_obligation: PredicateObligation<'tcx>,
26) -> FulfillmentError<'tcx> {
27 let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
28
29 let code = match obligation.predicate.kind().skip_binder() {
30 ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
31 FulfillmentErrorCode::Project(
32 MismatchedProjectionTypes { err: TypeError::Mismatch },
34 )
35 }
36 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => {
37 let ct_ty = match ct.kind() {
38 ty::ConstKind::Alias(_, alias_const) => {
39 alias_const.type_of(infcx.tcx).skip_norm_wip()
40 }
41 ty::ConstKind::Param(param_ct) => {
42 param_ct.find_const_ty_from_env(obligation.param_env)
43 }
44 ty::ConstKind::Value(cv) => cv.ty,
45 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!(
46 obligation.cause.span,
47 "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}"
48 ),
49 };
50 FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType {
51 ct,
52 ct_ty,
53 expected_ty,
54 })
55 }
56 ty::PredicateKind::Subtype(pred) => {
57 let (a, b) = infcx.enter_forall_and_leak_universe(
58 obligation.predicate.kind().rebind((pred.a, pred.b)),
59 );
60 let expected_found = ExpectedFound::new(a, b);
61 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
62 }
63 ty::PredicateKind::Coerce(pred) => {
64 let (a, b) = infcx.enter_forall_and_leak_universe(
65 obligation.predicate.kind().rebind((pred.a, pred.b)),
66 );
67 let expected_found = ExpectedFound::new(b, a);
68 FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
69 }
70 ty::PredicateKind::Clause(
71 ty::ClauseKind::RegionOutlives(_) | ty::ClauseKind::TypeOutlives(_),
72 ) if infcx.tcx.assumptions_on_binders() => FulfillmentErrorCode::Outlives,
73 ty::PredicateKind::Clause(_)
74 | ty::PredicateKind::DynCompatible(_)
75 | ty::PredicateKind::Ambiguous => {
76 FulfillmentErrorCode::Select(SelectionError::Unimplemented)
77 }
78 ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::NormalizesTo(..) => {
79 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected goal: {0:?}",
obligation))bug!("unexpected goal: {obligation:?}")
80 }
81 };
82
83 FulfillmentError { obligation, code, root_obligation }
84}
85
86pub(super) fn fulfillment_error_for_stalled<'tcx>(
87 infcx: &InferCtxt<'tcx>,
88 ambiguity: NextSolverAmbiguityError<'tcx>,
89) -> FulfillmentError<'tcx> {
90 let NextSolverAmbiguityError { root_obligation, code, refine_obligation } = ambiguity;
91
92 let obligation = if refine_obligation {
93 find_best_leaf_obligation(infcx, &root_obligation, true)
94 } else {
95 root_obligation.clone()
96 };
97
98 FulfillmentError { obligation, code, root_obligation }
99}
100
101pub(super) fn try_ambiguity_error_for_stalled<'tcx>(
102 infcx: &InferCtxt<'tcx>,
103 root_obligation: PredicateObligation<'tcx>,
104) -> Option<NextSolverAmbiguityError<'tcx>> {
105 let evaluation = infcx.probe(|_| {
106 match <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal(
107 root_obligation.as_goal(),
108 root_obligation.cause.span,
109 None,
110 ) {
111 Ok(GoalEvaluation {
112 certainty:
113 Certainty::Maybe(MaybeInfo {
114 cause: MaybeCause::Ambiguity,
115 opaque_types_jank: _,
116 stalled_on_coroutines: _,
117 }),
118 ..
119 }) => Some((FulfillmentErrorCode::Ambiguity { overflow: None }, true)),
120 Ok(GoalEvaluation {
121 certainty:
122 Certainty::Maybe(MaybeInfo {
123 cause:
124 MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
125 opaque_types_jank: _,
126 stalled_on_coroutines: _,
127 }),
128 ..
129 }) => Some((
130 FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
131 false,
138 )),
139 Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
140 infcx.dcx().span_delayed_bug(
141 root_obligation.cause.span,
142 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("did not expect successful goal when collecting ambiguity errors for `{0:?}`",
infcx.resolve_vars_if_possible(root_obligation.predicate)))
})format!(
143 "did not expect successful goal when collecting ambiguity errors for `{:?}`",
144 infcx.resolve_vars_if_possible(root_obligation.predicate),
145 ),
146 );
147 None
148 },
149 Err(_) => {
150 ::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!(
151 root_obligation.cause.span,
152 "did not expect selection error when collecting ambiguity errors for `{:?}`",
153 infcx.resolve_vars_if_possible(root_obligation.predicate),
154 )
155 }
156 }
157 });
158
159 let (code, refine_obligation) = evaluation?;
160
161 Some(NextSolverAmbiguityError { root_obligation, code, refine_obligation })
162}
163
164pub(super) fn fulfillment_error_for_overflow<'tcx>(
165 infcx: &InferCtxt<'tcx>,
166 root_obligation: PredicateObligation<'tcx>,
167) -> FulfillmentError<'tcx> {
168 FulfillmentError {
169 obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
170 code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
171 root_obligation,
172 }
173}
174
175{}
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/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(175u32),
::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.resolve_vars_if_possible(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/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:175",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(175u32),
::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)]
176fn find_best_leaf_obligation<'tcx>(
177 infcx: &InferCtxt<'tcx>,
178 obligation: &PredicateObligation<'tcx>,
179 consider_ambiguities: bool,
180) -> PredicateObligation<'tcx> {
181 let obligation = infcx.resolve_vars_if_possible(obligation.clone());
182 let obligation = infcx
188 .fudge_inference_if_ok(|| {
189 infcx
190 .visit_proof_tree(
191 obligation.as_goal(),
192 &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
193 )
194 .break_value()
195 .ok_or(())
196 .map(|o| (o.cause.clone(), o))
199 })
200 .map(|(cause, o)| PredicateObligation { cause, ..o })
201 .unwrap_or(obligation);
202 deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
203}
204
205struct BestObligation<'tcx> {
206 obligation: PredicateObligation<'tcx>,
207 consider_ambiguities: bool,
208}
209
210impl<'tcx> BestObligation<'tcx> {
211 fn with_derived_obligation(
212 &mut self,
213 derived_obligation: PredicateObligation<'tcx>,
214 and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
215 ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
216 let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
217 let res = and_then(self);
218 self.obligation = old_obligation;
219 res
220 }
221
222 fn non_trivial_candidates<'a>(
227 &self,
228 goal: &'a inspect::InspectGoal<'a, 'tcx>,
229 ) -> Vec<inspect::InspectCandidate<'a, 'tcx>> {
230 let mut candidates = goal.candidates();
231 match self.consider_ambiguities {
232 true => {
233 candidates.retain(|candidate| candidate.result().is_ok());
237 }
238 false => {
239 candidates.retain(|c| !#[allow(non_exhaustive_omitted_patterns)] match c.kind() {
inspect::ProbeKind::RigidAlias { .. } => true,
_ => false,
}matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
242 if candidates.len() > 1 {
246 candidates.retain(|candidate| {
247 goal.infcx().probe(|_| {
248 candidate.instantiate_nested_goals(self.span()).iter().any(
249 |nested_goal| {
250 #[allow(non_exhaustive_omitted_patterns)] match nested_goal.source() {
GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition |
GoalSource::AliasWellFormed => true,
_ => false,
}matches!(
251 nested_goal.source(),
252 GoalSource::ImplWhereBound
253 | GoalSource::AliasBoundConstCondition
254 | GoalSource::AliasWellFormed
255 ) && nested_goal.result().is_err()
256 },
257 )
258 })
259 });
260 }
261 }
262 }
263
264 candidates
265 }
266
267 fn visit_well_formed_goal(
271 &mut self,
272 candidate: &inspect::InspectCandidate<'_, 'tcx>,
273 term: ty::Term<'tcx>,
274 ) -> ControlFlow<PredicateObligation<'tcx>> {
275 let infcx = candidate.goal().infcx();
276 let param_env = candidate.goal().goal().param_env;
277 let body_def_id = self.obligation.cause.body_def_id;
278
279 for obligation in
280 wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_def_id)
281 .into_flat_iter()
282 {
283 let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
284 GoalSource::Misc,
285 obligation.as_goal(),
286 self.span(),
287 );
288 match (self.consider_ambiguities, nested_goal.result()) {
290 (
291 true,
292 Ok(Certainty::Maybe(MaybeInfo {
293 cause: MaybeCause::Ambiguity,
294 opaque_types_jank: _,
295 stalled_on_coroutines: _,
296 })),
297 )
298 | (false, Err(_)) => {}
299 _ => continue,
300 }
301
302 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
303 }
304
305 ControlFlow::Break(self.obligation.clone())
306 }
307
308 fn detect_error_in_self_ty_normalization(
312 &mut self,
313 goal: &inspect::InspectGoal<'_, 'tcx>,
314 self_ty: Ty<'tcx>,
315 ) -> ControlFlow<PredicateObligation<'tcx>> {
316 if !!self.consider_ambiguities {
::core::panicking::panic("assertion failed: !self.consider_ambiguities")
};assert!(!self.consider_ambiguities);
317 let tcx = goal.infcx().tcx;
318 if let ty::Alias(_, alias) = *self_ty.kind() {
319 let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span);
320 let pred =
321 ty::ProjectionClause { projection_term: alias.into(), term: infer_term.into() };
322 let obligation =
323 Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
324 self.with_derived_obligation(obligation, |this| {
325 goal.infcx().visit_proof_tree_at_depth(
326 goal.goal().with(tcx, pred),
327 goal.depth() + 1,
328 this,
329 )
330 })
331 } else {
332 ControlFlow::Continue(())
333 }
334 }
335
336 fn detect_trait_error_in_higher_ranked_projection(
344 &mut self,
345 goal: &inspect::InspectGoal<'_, 'tcx>,
346 ) -> ControlFlow<PredicateObligation<'tcx>> {
347 let tcx = goal.infcx().tcx;
348 if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
349 && !projection_clause.bound_vars().is_empty()
350 {
351 let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
352 let obligation = Obligation::new(
353 tcx,
354 self.obligation.cause.clone(),
355 goal.goal().param_env,
356 deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
357 );
358 self.with_derived_obligation(obligation, |this| {
359 goal.infcx().visit_proof_tree_at_depth(
360 goal.goal().with(tcx, pred),
361 goal.depth() + 1,
362 this,
363 )
364 })
365 } else {
366 ControlFlow::Continue(())
367 }
368 }
369
370 fn detect_non_well_formed_assoc_item(
377 &mut self,
378 goal: &inspect::InspectGoal<'_, 'tcx>,
379 alias: ty::AliasTerm<'tcx>,
380 ) -> ControlFlow<PredicateObligation<'tcx>> {
381 let tcx = goal.infcx().tcx;
382 let obligation = Obligation::new(
383 tcx,
384 self.obligation.cause.clone(),
385 goal.goal().param_env,
386 alias.trait_ref(tcx),
387 );
388 self.with_derived_obligation(obligation, |this| {
389 goal.infcx().visit_proof_tree_at_depth(
390 goal.goal().with(tcx, alias.trait_ref(tcx)),
391 goal.depth() + 1,
392 this,
393 )
394 })
395 }
396
397 fn detect_error_from_empty_candidates(
400 &mut self,
401 goal: &inspect::InspectGoal<'_, 'tcx>,
402 ) -> ControlFlow<PredicateObligation<'tcx>> {
403 let pred_kind = goal.goal().predicate.kind();
404
405 match pred_kind.no_bound_vars() {
406 Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) => {
407 self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
408 }
409 Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)))
410 if pred.projection_term.kind.is_trait_projection() =>
411 {
412 self.detect_error_in_self_ty_normalization(goal, pred.projection_term.self_ty())?;
413 self.detect_non_well_formed_assoc_item(goal, pred.projection_term)?;
414 }
415 Some(_) | None => {}
416 }
417
418 ControlFlow::Break(self.obligation.clone())
419 }
420}
421
422impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
423 type Result = ControlFlow<PredicateObligation<'tcx>>;
424
425 fn span(&self) -> rustc_span::Span {
426 self.obligation.cause.span
427 }
428
429 {}
#[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/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(429u32),
::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/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:462",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(462u32),
::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/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:509",
"rustc_trait_selection::solve::fulfill::derive_errors",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
::tracing_core::__macro_support::Option::Some(509u32),
::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::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_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()))]
430 fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
431 let tcx = goal.infcx().tcx;
432 match (self.consider_ambiguities, goal.result()) {
434 (
435 true,
436 Ok(Certainty::Maybe(MaybeInfo {
437 cause: MaybeCause::Ambiguity,
438 opaque_types_jank: _,
439 stalled_on_coroutines: _,
440 })),
441 )
442 | (false, Err(_)) => {}
443 _ => return ControlFlow::Continue(()),
444 }
445
446 let pred = goal.goal().predicate;
447
448 let candidates = self.non_trivial_candidates(goal);
449 let candidate = match candidates.as_slice() {
450 [candidate] => candidate,
451 [] => return self.detect_error_from_empty_candidates(goal),
452 _ => return ControlFlow::Break(self.obligation.clone()),
453 };
454
455 if let inspect::ProbeKind::TraitCandidate {
457 source: CandidateSource::Impl(impl_def_id),
458 result: _,
459 } = candidate.kind()
460 && tcx.do_not_recommend_impl(impl_def_id)
461 {
462 trace!("#[diagnostic::do_not_recommend] -> exit");
463 return ControlFlow::Break(self.obligation.clone());
464 }
465
466 let child_mode = match pred.kind().skip_binder() {
469 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
470 ChildMode::Trait(pred.kind().rebind(trait_pred))
471 }
472 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_clause)) => {
473 ChildMode::Host(pred.kind().rebind(host_clause))
474 }
475 ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection))
476 if projection.projection_term.kind.is_trait_projection() =>
477 {
478 ChildMode::Trait(pred.kind().rebind(ty::TraitClause {
479 trait_ref: projection.projection_term.trait_ref(tcx),
480 polarity: ty::ClausePolarity::Positive,
481 }))
482 }
483 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
484 return self.visit_well_formed_goal(candidate, term);
485 }
486 _ => ChildMode::PassThrough,
487 };
488
489 let nested_goals = candidate.instantiate_nested_goals(self.span());
490
491 for nested_goal in &nested_goals {
499 if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
500 && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
501 && let Err(NoSolution) = nested_goal.result()
502 {
503 return ControlFlow::Break(self.obligation.clone());
504 }
505 }
506
507 let mut impl_where_bound_count = 0;
508 for nested_goal in nested_goals {
509 trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
510
511 let nested_pred = nested_goal.goal().predicate;
512
513 let make_obligation = |cause| Obligation {
514 cause,
515 param_env: nested_goal.goal().param_env,
516 predicate: nested_pred,
517 recursion_depth: self.obligation.recursion_depth + 1,
518 };
519
520 let obligation;
521 match (child_mode, nested_goal.source()) {
522 (
523 ChildMode::Trait(_) | ChildMode::Host(_),
524 GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
525 ) => {
526 continue;
527 }
528 (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
529 obligation = make_obligation(derive_cause(
530 tcx,
531 candidate.kind(),
532 self.obligation.cause.clone(),
533 impl_where_bound_count,
534 parent_trait_pred,
535 ));
536 impl_where_bound_count += 1;
537 }
538 (
539 ChildMode::Host(parent_host_clause),
540 GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
541 ) => {
542 obligation = make_obligation(derive_host_cause(
543 tcx,
544 candidate.kind(),
545 self.obligation.cause.clone(),
546 impl_where_bound_count,
547 parent_host_clause,
548 ));
549 impl_where_bound_count += 1;
550 }
551 (ChildMode::PassThrough, _)
552 | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
553 obligation = make_obligation(self.obligation.cause.clone());
554 }
555 }
556
557 self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
558 }
559
560 self.detect_trait_error_in_higher_ranked_projection(goal)?;
561
562 ControlFlow::Break(self.obligation.clone())
563 }
564}
565
566#[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]
#[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) -> ChildMode<'tcx> {
let _: ::core::clone::AssertParamIsClone<ty::PolyTraitClause<'tcx>>;
let _:
::core::clone::AssertParamIsClone<ty::Binder<'tcx,
ty::HostEffectClause<'tcx>>>;
*self
}
}Clone)]
567enum ChildMode<'tcx> {
568 Trait(ty::PolyTraitClause<'tcx>),
572 Host(ty::Binder<'tcx, ty::HostEffectClause<'tcx>>),
576 PassThrough,
580}
581
582fn derive_cause<'tcx>(
583 tcx: TyCtxt<'tcx>,
584 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
585 mut cause: ObligationCause<'tcx>,
586 idx: usize,
587 parent_trait_pred: ty::PolyTraitClause<'tcx>,
588) -> ObligationCause<'tcx> {
589 match candidate_kind {
590 inspect::ProbeKind::TraitCandidate {
591 source: CandidateSource::Impl(impl_def_id),
592 result: _,
593 } => {
594 if let Some((_, span)) =
595 tcx.clauses_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
596 {
597 cause = cause.derived_cause(parent_trait_pred, |derived| {
598 ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
599 derived,
600 impl_or_alias_def_id: impl_def_id,
601 impl_def_clause_index: Some(idx),
602 span,
603 }))
604 })
605 }
606 }
607 inspect::ProbeKind::TraitCandidate {
608 source: CandidateSource::BuiltinImpl(..),
609 result: _,
610 } => {
611 cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived);
612 }
613 _ => {}
614 };
615 cause
616}
617
618fn derive_host_cause<'tcx>(
619 tcx: TyCtxt<'tcx>,
620 candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
621 mut cause: ObligationCause<'tcx>,
622 idx: usize,
623 parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>,
624) -> ObligationCause<'tcx> {
625 match candidate_kind {
626 inspect::ProbeKind::TraitCandidate {
627 source: CandidateSource::Impl(impl_def_id),
628 result: _,
629 } => {
630 if let Some((_, span)) = tcx
631 .clauses_of(impl_def_id)
632 .instantiate_identity(tcx)
633 .into_iter()
634 .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
635 |(trait_ref, span)| {
636 (
637 trait_ref.to_host_effect_clause(
638 tcx,
639 parent_host_clause.skip_binder().constness,
640 ),
641 span,
642 )
643 },
644 ))
645 .nth(idx)
646 {
647 cause =
648 cause.derived_host_cause(parent_host_clause, |derived| {
649 ObligationCauseCode::ImplDerivedHost(Box::new(
650 traits::ImplDerivedHostCause { derived, impl_def_id, span },
651 ))
652 })
653 }
654 }
655 inspect::ProbeKind::TraitCandidate {
656 source: CandidateSource::BuiltinImpl(..),
657 result: _,
658 } => {
659 cause = cause
660 .derived_host_cause(parent_host_clause, ObligationCauseCode::BuiltinDerivedHost);
661 }
662 _ => {}
663 };
664 cause
665}