Skip to main content

rustc_trait_selection/solve/fulfill/
derive_errors.rs

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 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                // FIXME: This could be a `Sorts` if the term is a type
33                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_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!(
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_span::macros::bug_impl(None,
    format_args!("unexpected goal: {0:?}", obligation), Location::caller())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                // Don't look into overflows because we treat overflows weirdly anyways.
132                // We discard the inference constraints from overflowing goals, so
133                // recomputing the goal again during `find_best_leaf_obligation` may apply
134                // inference guidance that makes other goals go from ambig -> pass, for example.
135                //
136                // FIXME: We should probably just look into overflows here.
137                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.deeply_resolve_ignoring_regions(root_obligation.predicate)))
    })format!(
143                        "did not expect successful goal when collecting ambiguity errors for `{:?}`",
144                        infcx.deeply_resolve_ignoring_regions(root_obligation.predicate),
145                    ),
146                );
147                None
148            },
149            Err(_) => {
150                ::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!(
151                    root_obligation.cause.span,
152                    "did not expect selection error when collecting ambiguity errors for `{:?}`",
153                    infcx.deeply_resolve_ignoring_regions(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
164{}
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/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
                                ::tracing_core::__macro_support::Option::Some(164u32),
                                ::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/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:164",
                        "rustc_trait_selection::solve::fulfill::derive_errors",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
                        ::tracing_core::__macro_support::Option::Some(164u32),
                        ::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)]
165fn find_best_leaf_obligation<'tcx>(
166    infcx: &InferCtxt<'tcx>,
167    obligation: &PredicateObligation<'tcx>,
168    consider_ambiguities: bool,
169) -> PredicateObligation<'tcx> {
170    let obligation = infcx.deeply_resolve_ignoring_regions(obligation.clone());
171    // FIXME: we use a probe here as the `BestObligation` visitor does not
172    // check whether it uses candidates which get shadowed by where-bounds.
173    //
174    // We should probably fix the visitor to not do so instead, as this also
175    // means the leaf obligation may be incorrect.
176    let obligation = infcx
177        .fudge_inference_if_ok(|| {
178            infcx
179                .visit_proof_tree(
180                    obligation.as_goal(),
181                    &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
182                )
183                .break_value()
184                .ok_or(())
185                // walk around the fact that the cause in `Obligation` is ignored by folders so that
186                // we can properly fudge the infer vars in cause code.
187                .map(|o| (o.cause.clone(), o))
188        })
189        .map(|(cause, o)| PredicateObligation { cause, ..o })
190        .unwrap_or(obligation);
191    deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
192}
193
194struct BestObligation<'tcx> {
195    obligation: PredicateObligation<'tcx>,
196    consider_ambiguities: bool,
197}
198
199impl<'tcx> BestObligation<'tcx> {
200    fn with_derived_obligation(
201        &mut self,
202        derived_obligation: PredicateObligation<'tcx>,
203        and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
204    ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
205        let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
206        let res = and_then(self);
207        self.obligation = old_obligation;
208        res
209    }
210
211    /// Filter out the candidates that aren't interesting to visit for the
212    /// purposes of reporting errors. For ambiguities, we only consider
213    /// candidates that may hold. For errors, we only consider candidates that
214    /// *don't* hold and which have impl-where clauses that also don't hold.
215    fn non_trivial_candidates<'a>(
216        &self,
217        goal: &'a inspect::InspectGoal<'a, 'tcx>,
218    ) -> Vec<inspect::InspectCandidate<'a, 'tcx>> {
219        let mut candidates = goal.candidates();
220        match self.consider_ambiguities {
221            true => {
222                // If we have an ambiguous obligation, we must consider *all* candidates
223                // that hold, or else we may guide inference causing other goals to go
224                // from ambig -> pass/fail.
225                candidates.retain(|candidate| candidate.result().is_ok());
226            }
227            false => {
228                // We always handle rigid alias candidates separately as we may not add them for
229                // aliases whose trait bound doesn't hold.
230                candidates.retain(|c| !#[allow(non_exhaustive_omitted_patterns)] match c.kind() {
    inspect::ProbeKind::RigidAlias { .. } => true,
    _ => false,
}matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
231                // If we have >1 candidate, one may still be due to "boring" reasons, like
232                // an alias-relate that failed to hold when deeply evaluated. We really
233                // don't care about reasons like this.
234                if candidates.len() > 1 {
235                    candidates.retain(|candidate| {
236                        goal.infcx().probe(|_| {
237                            candidate.instantiate_nested_goals(self.span()).iter().any(
238                                |nested_goal| {
239                                    #[allow(non_exhaustive_omitted_patterns)] match nested_goal.source() {
    GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition |
        GoalSource::AliasWellFormed => true,
    _ => false,
}matches!(
240                                        nested_goal.source(),
241                                        GoalSource::ImplWhereBound
242                                            | GoalSource::AliasBoundConstCondition
243                                            | GoalSource::AliasWellFormed
244                                    ) && nested_goal.result().is_err()
245                                },
246                            )
247                        })
248                    });
249                }
250            }
251        }
252
253        candidates
254    }
255
256    /// HACK: We walk the nested obligations for a well-formed arg manually,
257    /// since there's nontrivial logic in `wf.rs` to set up an obligation cause.
258    /// Ideally we'd be able to track this better.
259    fn visit_well_formed_goal(
260        &mut self,
261        candidate: &inspect::InspectCandidate<'_, 'tcx>,
262        term: ty::Term<'tcx>,
263    ) -> ControlFlow<PredicateObligation<'tcx>> {
264        let infcx = candidate.goal().infcx();
265        let param_env = candidate.goal().goal().param_env;
266        let body_def_id = self.obligation.cause.body_def_id;
267
268        for obligation in
269            wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_def_id)
270                .into_flat_iter()
271        {
272            let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
273                GoalSource::Misc,
274                obligation.as_goal(),
275                self.span(),
276            );
277            // Skip nested goals that aren't the *reason* for our goal's failure.
278            match (self.consider_ambiguities, nested_goal.result()) {
279                (
280                    true,
281                    Ok(Certainty::Maybe(MaybeInfo {
282                        cause: MaybeCause::Ambiguity,
283                        opaque_types_jank: _,
284                        stalled_on_coroutines: _,
285                    })),
286                )
287                | (false, Err(_)) => {}
288                _ => continue,
289            }
290
291            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
292        }
293
294        ControlFlow::Break(self.obligation.clone())
295    }
296
297    /// If a normalization of an associated item or a trait goal fails without trying any
298    /// candidates it's likely that normalizing its self type failed. We manually detect
299    /// such cases here.
300    fn detect_error_in_self_ty_normalization(
301        &mut self,
302        goal: &inspect::InspectGoal<'_, 'tcx>,
303        self_ty: Ty<'tcx>,
304    ) -> ControlFlow<PredicateObligation<'tcx>> {
305        if !!self.consider_ambiguities {
    ::core::panicking::panic("assertion failed: !self.consider_ambiguities")
};assert!(!self.consider_ambiguities);
306        let tcx = goal.infcx().tcx;
307        if let ty::Alias(_, alias) = *self_ty.kind() {
308            let infer_term = goal.infcx().next_ty_var(self.obligation.cause.span);
309            let pred =
310                ty::ProjectionClause { projection_term: alias.into(), term: infer_term.into() };
311            let obligation =
312                Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
313            self.with_derived_obligation(obligation, |this| {
314                goal.infcx().visit_proof_tree_at_depth(
315                    goal.goal().with(tcx, pred),
316                    goal.depth() + 1,
317                    this,
318                )
319            })
320        } else {
321            ControlFlow::Continue(())
322        }
323    }
324
325    /// When a higher-ranked projection goal fails, check that the corresponding
326    /// higher-ranked trait goal holds or not. This is because the process of
327    /// instantiating and then re-canonicalizing the binder of the projection goal
328    /// forces us to be unable to see that the leak check failed in the nested
329    /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
330    /// that should catch when a projection goal fails due to an unsatisfied trait
331    /// goal.
332    fn detect_trait_error_in_higher_ranked_projection(
333        &mut self,
334        goal: &inspect::InspectGoal<'_, 'tcx>,
335    ) -> ControlFlow<PredicateObligation<'tcx>> {
336        let tcx = goal.infcx().tcx;
337        if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
338            && !projection_clause.bound_vars().is_empty()
339        {
340            let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
341            let obligation = Obligation::new(
342                tcx,
343                self.obligation.cause.clone(),
344                goal.goal().param_env,
345                deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
346            );
347            self.with_derived_obligation(obligation, |this| {
348                goal.infcx().visit_proof_tree_at_depth(
349                    goal.goal().with(tcx, pred),
350                    goal.depth() + 1,
351                    this,
352                )
353            })
354        } else {
355            ControlFlow::Continue(())
356        }
357    }
358
359    /// It is likely that `NormalizesTo` failed without any applicable candidates
360    /// because the alias is not well-formed.
361    ///
362    /// As we only enter `RigidAlias` candidates if the trait bound of the associated type
363    /// holds, we discard these candidates in `non_trivial_candidates` and always manually
364    /// check this here.
365    fn detect_non_well_formed_assoc_item(
366        &mut self,
367        goal: &inspect::InspectGoal<'_, 'tcx>,
368        alias: ty::AliasTerm<'tcx>,
369    ) -> ControlFlow<PredicateObligation<'tcx>> {
370        let tcx = goal.infcx().tcx;
371        let obligation = Obligation::new(
372            tcx,
373            self.obligation.cause.clone(),
374            goal.goal().param_env,
375            alias.trait_ref(tcx),
376        );
377        self.with_derived_obligation(obligation, |this| {
378            goal.infcx().visit_proof_tree_at_depth(
379                goal.goal().with(tcx, alias.trait_ref(tcx)),
380                goal.depth() + 1,
381                this,
382            )
383        })
384    }
385
386    /// If we have no candidates, then it's likely that there is a
387    /// non-well-formed alias in the goal.
388    fn detect_error_from_empty_candidates(
389        &mut self,
390        goal: &inspect::InspectGoal<'_, 'tcx>,
391    ) -> ControlFlow<PredicateObligation<'tcx>> {
392        let pred_kind = goal.goal().predicate.kind();
393
394        match pred_kind.no_bound_vars() {
395            Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) => {
396                self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
397            }
398            Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)))
399                if pred.projection_term.kind.is_trait_projection() =>
400            {
401                self.detect_error_in_self_ty_normalization(goal, pred.projection_term.self_ty())?;
402                self.detect_non_well_formed_assoc_item(goal, pred.projection_term)?;
403            }
404            Some(_) | None => {}
405        }
406
407        ControlFlow::Break(self.obligation.clone())
408    }
409}
410
411impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
412    type Result = ControlFlow<PredicateObligation<'tcx>>;
413
414    fn span(&self) -> rustc_span::Span {
415        self.obligation.cause.span
416    }
417
418    {}
#[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/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
                                    ::tracing_core::__macro_support::Option::Some(418u32),
                                    ::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/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:451",
                                        "rustc_trait_selection::solve::fulfill::derive_errors",
                                        ::tracing::Level::TRACE,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
                                        ::tracing_core::__macro_support::Option::Some(451u32),
                                        ::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/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs:498",
                                        "rustc_trait_selection::solve::fulfill::derive_errors",
                                        ::tracing::Level::TRACE,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs"),
                                        ::tracing_core::__macro_support::Option::Some(498u32),
                                        ::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()))]
419    fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
420        let tcx = goal.infcx().tcx;
421        // Skip goals that aren't the *reason* for our goal's failure.
422        match (self.consider_ambiguities, goal.result()) {
423            (
424                true,
425                Ok(Certainty::Maybe(MaybeInfo {
426                    cause: MaybeCause::Ambiguity,
427                    opaque_types_jank: _,
428                    stalled_on_coroutines: _,
429                })),
430            )
431            | (false, Err(_)) => {}
432            _ => return ControlFlow::Continue(()),
433        }
434
435        let pred = goal.goal().predicate;
436
437        let candidates = self.non_trivial_candidates(goal);
438        let candidate = match candidates.as_slice() {
439            [candidate] => candidate,
440            [] => return self.detect_error_from_empty_candidates(goal),
441            _ => return ControlFlow::Break(self.obligation.clone()),
442        };
443
444        // Don't walk into impls that have `do_not_recommend`.
445        if let inspect::ProbeKind::TraitCandidate {
446            source: CandidateSource::Impl(impl_def_id),
447            result: _,
448        } = candidate.kind()
449            && tcx.do_not_recommend_impl(impl_def_id)
450        {
451            trace!("#[diagnostic::do_not_recommend] -> exit");
452            return ControlFlow::Break(self.obligation.clone());
453        }
454
455        // FIXME: Also, what about considering >1 layer up the stack? May be necessary
456        // for normalizes-to.
457        let child_mode = match pred.kind().skip_binder() {
458            ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
459                ChildMode::Trait(pred.kind().rebind(trait_pred))
460            }
461            ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_clause)) => {
462                ChildMode::Host(pred.kind().rebind(host_clause))
463            }
464            ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection))
465                if projection.projection_term.kind.is_trait_projection() =>
466            {
467                ChildMode::Trait(pred.kind().rebind(ty::TraitClause {
468                    trait_ref: projection.projection_term.trait_ref(tcx),
469                    polarity: ty::ClausePolarity::Positive,
470                }))
471            }
472            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
473                return self.visit_well_formed_goal(candidate, term);
474            }
475            _ => ChildMode::PassThrough,
476        };
477
478        let nested_goals = candidate.instantiate_nested_goals(self.span());
479
480        // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as
481        // an actual candidate, instead we should treat them as if the impl was never considered to
482        // have potentially applied. As if `impl<A, R> Trait for for<..> fn(..A) -> R` was written
483        // instead of `impl<T: FnPtr> Trait for T`.
484        //
485        // We do this as a separate loop so that we do not choose to tell the user about some nested
486        // goal before we encounter a `T: FnPtr` nested goal.
487        for nested_goal in &nested_goals {
488            if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
489                && tcx.is_lang_item(poly_trait_pred.def_id(), LangItem::FnPtrTrait)
490                && let Err(NoSolution) = nested_goal.result()
491            {
492                return ControlFlow::Break(self.obligation.clone());
493            }
494        }
495
496        let mut impl_where_bound_count = 0;
497        for nested_goal in nested_goals {
498            trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
499
500            let nested_pred = nested_goal.goal().predicate;
501
502            let make_obligation = |cause| Obligation {
503                cause,
504                param_env: nested_goal.goal().param_env,
505                predicate: nested_pred,
506                recursion_depth: self.obligation.recursion_depth + 1,
507            };
508
509            let obligation;
510            match (child_mode, nested_goal.source()) {
511                (
512                    ChildMode::Trait(_) | ChildMode::Host(_),
513                    GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
514                ) => {
515                    continue;
516                }
517                (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
518                    obligation = make_obligation(derive_cause(
519                        tcx,
520                        candidate.kind(),
521                        self.obligation.cause.clone(),
522                        impl_where_bound_count,
523                        parent_trait_pred,
524                    ));
525                    impl_where_bound_count += 1;
526                }
527                (
528                    ChildMode::Host(parent_host_clause),
529                    GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
530                ) => {
531                    obligation = make_obligation(derive_host_cause(
532                        tcx,
533                        candidate.kind(),
534                        self.obligation.cause.clone(),
535                        impl_where_bound_count,
536                        parent_host_clause,
537                    ));
538                    impl_where_bound_count += 1;
539                }
540                (ChildMode::PassThrough, _)
541                | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
542                    obligation = make_obligation(self.obligation.cause.clone());
543                }
544            }
545
546            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
547        }
548
549        self.detect_trait_error_in_higher_ranked_projection(goal)?;
550
551        ControlFlow::Break(self.obligation.clone())
552    }
553}
554
555#[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)]
556enum ChildMode<'tcx> {
557    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
558    // and skip all `GoalSource::Misc`, which represent useless obligations
559    // such as alias-eq which may not hold.
560    Trait(ty::PolyTraitClause<'tcx>),
561    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
562    // and skip all `GoalSource::Misc`, which represent useless obligations
563    // such as alias-eq which may not hold.
564    Host(ty::Binder<'tcx, ty::HostEffectClause<'tcx>>),
565    // Skip trying to derive an `ObligationCause` from this obligation, and
566    // report *all* sub-obligations as if they came directly from the parent
567    // obligation.
568    PassThrough,
569}
570
571fn derive_cause<'tcx>(
572    tcx: TyCtxt<'tcx>,
573    candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
574    mut cause: ObligationCause<'tcx>,
575    idx: usize,
576    parent_trait_pred: ty::PolyTraitClause<'tcx>,
577) -> ObligationCause<'tcx> {
578    match candidate_kind {
579        inspect::ProbeKind::TraitCandidate {
580            source: CandidateSource::Impl(impl_def_id),
581            result: _,
582        } => {
583            if let Some((_, span)) =
584                tcx.clauses_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
585            {
586                cause = cause.derived_cause(parent_trait_pred, |derived| {
587                    ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
588                        derived,
589                        impl_or_alias_def_id: impl_def_id,
590                        impl_def_clause_index: Some(idx),
591                        span,
592                    }))
593                })
594            }
595        }
596        inspect::ProbeKind::TraitCandidate {
597            source: CandidateSource::BuiltinImpl(..),
598            result: _,
599        } => {
600            cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived);
601        }
602        _ => {}
603    };
604    cause
605}
606
607fn derive_host_cause<'tcx>(
608    tcx: TyCtxt<'tcx>,
609    candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
610    mut cause: ObligationCause<'tcx>,
611    idx: usize,
612    parent_host_clause: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>,
613) -> ObligationCause<'tcx> {
614    match candidate_kind {
615        inspect::ProbeKind::TraitCandidate {
616            source: CandidateSource::Impl(impl_def_id),
617            result: _,
618        } => {
619            if let Some((_, span)) = tcx
620                .clauses_of(impl_def_id)
621                .instantiate_identity(tcx)
622                .into_iter()
623                .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
624                    |(trait_ref, span)| {
625                        (
626                            trait_ref.to_host_effect_clause(
627                                tcx,
628                                parent_host_clause.skip_binder().constness,
629                            ),
630                            span,
631                        )
632                    },
633                ))
634                .nth(idx)
635            {
636                cause =
637                    cause.derived_host_cause(parent_host_clause, |derived| {
638                        ObligationCauseCode::ImplDerivedHost(Box::new(
639                            traits::ImplDerivedHostCause { derived, impl_def_id, span },
640                        ))
641                    })
642            }
643        }
644        inspect::ProbeKind::TraitCandidate {
645            source: CandidateSource::BuiltinImpl(..),
646            result: _,
647        } => {
648            cause = cause
649                .derived_host_cause(parent_host_clause, ObligationCauseCode::BuiltinDerivedHost);
650        }
651        _ => {}
652    };
653    cause
654}