hir_ty/next_solver/fulfill/
errors.rs

1//! Trait solving error diagnosis and reporting.
2//!
3//! This code isn't used by rust-analyzer (it should, but then it'll probably be better to re-port it from rustc).
4//! It's only there because without it, debugging trait solver errors is a nightmare.
5
6use std::{fmt::Debug, ops::ControlFlow};
7
8use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt};
9use rustc_type_ir::{
10    AliasRelationDirection, AliasTermKind, HostEffectPredicate, Interner, PredicatePolarity,
11    error::ExpectedFound,
12    inherent::{IntoKind, SliceLike, Span as _},
13    lang_items::SolverTraitLangItem,
14    solve::{Certainty, GoalSource, MaybeCause, NoSolution},
15};
16use tracing::{instrument, trace};
17
18use crate::next_solver::{
19    AliasTerm, Binder, ClauseKind, Const, ConstKind, DbInterner, PolyTraitPredicate, PredicateKind,
20    SolverContext, Span, Term, TraitPredicate, Ty, TyKind, TypeError,
21    fulfill::NextSolverError,
22    infer::{
23        InferCtxt,
24        select::SelectionError,
25        traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations},
26    },
27    inspect::{self, ProofTreeVisitor},
28    normalize::deeply_normalize_for_diagnostics,
29};
30
31#[derive(Debug)]
32pub struct FulfillmentError<'db> {
33    pub obligation: PredicateObligation<'db>,
34    pub code: FulfillmentErrorCode<'db>,
35    /// Diagnostics only: the 'root' obligation which resulted in
36    /// the failure to process `obligation`. This is the obligation
37    /// that was initially passed to `register_predicate_obligation`
38    pub root_obligation: PredicateObligation<'db>,
39}
40
41impl<'db> FulfillmentError<'db> {
42    pub fn new(
43        obligation: PredicateObligation<'db>,
44        code: FulfillmentErrorCode<'db>,
45        root_obligation: PredicateObligation<'db>,
46    ) -> FulfillmentError<'db> {
47        FulfillmentError { obligation, code, root_obligation }
48    }
49
50    pub fn is_true_error(&self) -> bool {
51        match self.code {
52            FulfillmentErrorCode::Select(_)
53            | FulfillmentErrorCode::Project(_)
54            | FulfillmentErrorCode::Subtype(_, _)
55            | FulfillmentErrorCode::ConstEquate(_, _) => true,
56            FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
57                false
58            }
59        }
60    }
61}
62
63#[derive(Debug, Clone)]
64pub enum FulfillmentErrorCode<'db> {
65    /// Inherently impossible to fulfill; this trait is implemented if and only
66    /// if it is already implemented.
67    Cycle(PredicateObligations<'db>),
68    Select(SelectionError<'db>),
69    Project(MismatchedProjectionTypes<'db>),
70    Subtype(ExpectedFound<Ty<'db>>, TypeError<'db>), // always comes from a SubtypePredicate
71    ConstEquate(ExpectedFound<Const<'db>>, TypeError<'db>),
72    Ambiguity {
73        /// Overflow is only `Some(suggest_recursion_limit)` when using the next generation
74        /// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by
75        /// emitting a fatal error instead.
76        overflow: Option<bool>,
77    },
78}
79
80#[derive(Debug, Clone)]
81pub struct MismatchedProjectionTypes<'db> {
82    pub err: TypeError<'db>,
83}
84
85pub(super) fn fulfillment_error_for_no_solution<'db>(
86    infcx: &InferCtxt<'db>,
87    root_obligation: PredicateObligation<'db>,
88) -> FulfillmentError<'db> {
89    let obligation = find_best_leaf_obligation(infcx, &root_obligation, false);
90
91    let code = match obligation.predicate.kind().skip_binder() {
92        PredicateKind::Clause(ClauseKind::Projection(_)) => {
93            FulfillmentErrorCode::Project(
94                // FIXME: This could be a `Sorts` if the term is a type
95                MismatchedProjectionTypes { err: TypeError::Mismatch },
96            )
97        }
98        PredicateKind::Clause(ClauseKind::ConstArgHasType(ct, expected_ty)) => {
99            let ct_ty = match ct.kind() {
100                ConstKind::Unevaluated(uv) => {
101                    infcx.interner.type_of(uv.def.into()).instantiate(infcx.interner, uv.args)
102                }
103                ConstKind::Param(param_ct) => param_ct.find_const_ty_from_env(obligation.param_env),
104                ConstKind::Value(cv) => cv.ty,
105                kind => panic!(
106                    "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}"
107                ),
108            };
109            FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType {
110                ct,
111                ct_ty,
112                expected_ty,
113            })
114        }
115        PredicateKind::NormalizesTo(..) => {
116            FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
117        }
118        PredicateKind::AliasRelate(_, _, _) => {
119            FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch })
120        }
121        PredicateKind::Subtype(pred) => {
122            let (a, b) = infcx.enter_forall_and_leak_universe(
123                obligation.predicate.kind().rebind((pred.a, pred.b)),
124            );
125            let expected_found = ExpectedFound::new(a, b);
126            FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
127        }
128        PredicateKind::Coerce(pred) => {
129            let (a, b) = infcx.enter_forall_and_leak_universe(
130                obligation.predicate.kind().rebind((pred.a, pred.b)),
131            );
132            let expected_found = ExpectedFound::new(b, a);
133            FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found))
134        }
135        PredicateKind::Clause(_) | PredicateKind::DynCompatible(_) | PredicateKind::Ambiguous => {
136            FulfillmentErrorCode::Select(SelectionError::Unimplemented)
137        }
138        PredicateKind::ConstEquate(..) => {
139            panic!("unexpected goal: {obligation:?}")
140        }
141    };
142
143    FulfillmentError { obligation, code, root_obligation }
144}
145
146pub(super) fn fulfillment_error_for_stalled<'db>(
147    infcx: &InferCtxt<'db>,
148    root_obligation: PredicateObligation<'db>,
149) -> FulfillmentError<'db> {
150    let (code, refine_obligation) = infcx.probe(|_| {
151        match <&SolverContext<'db>>::from(infcx).evaluate_root_goal(
152            root_obligation.as_goal(),
153            Span::dummy(),
154            None,
155        ) {
156            Ok(GoalEvaluation {
157                certainty: Certainty::Maybe { cause: MaybeCause::Ambiguity, .. },
158                ..
159            }) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true),
160            Ok(GoalEvaluation {
161                certainty:
162                    Certainty::Maybe {
163                        cause:
164                            MaybeCause::Overflow { suggest_increasing_limit, keep_constraints: _ },
165                        ..
166                    },
167                ..
168            }) => (
169                FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) },
170                // Don't look into overflows because we treat overflows weirdly anyways.
171                // We discard the inference constraints from overflowing goals, so
172                // recomputing the goal again during `find_best_leaf_obligation` may apply
173                // inference guidance that makes other goals go from ambig -> pass, for example.
174                //
175                // FIXME: We should probably just look into overflows here.
176                false,
177            ),
178            Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => {
179                panic!(
180                    "did not expect successful goal when collecting ambiguity errors for `{:?}`",
181                    infcx.resolve_vars_if_possible(root_obligation.predicate),
182                )
183            }
184            Err(_) => {
185                panic!(
186                    "did not expect selection error when collecting ambiguity errors for `{:?}`",
187                    infcx.resolve_vars_if_possible(root_obligation.predicate),
188                )
189            }
190        }
191    });
192
193    FulfillmentError {
194        obligation: if refine_obligation {
195            find_best_leaf_obligation(infcx, &root_obligation, true)
196        } else {
197            root_obligation.clone()
198        },
199        code,
200        root_obligation,
201    }
202}
203
204pub(super) fn fulfillment_error_for_overflow<'db>(
205    infcx: &InferCtxt<'db>,
206    root_obligation: PredicateObligation<'db>,
207) -> FulfillmentError<'db> {
208    FulfillmentError {
209        obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
210        code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
211        root_obligation,
212    }
213}
214
215#[instrument(level = "debug", skip(infcx), ret)]
216fn find_best_leaf_obligation<'db>(
217    infcx: &InferCtxt<'db>,
218    obligation: &PredicateObligation<'db>,
219    consider_ambiguities: bool,
220) -> PredicateObligation<'db> {
221    let obligation = infcx.resolve_vars_if_possible(obligation.clone());
222    // FIXME: we use a probe here as the `BestObligation` visitor does not
223    // check whether it uses candidates which get shadowed by where-bounds.
224    //
225    // We should probably fix the visitor to not do so instead, as this also
226    // means the leaf obligation may be incorrect.
227    let obligation = infcx
228        .fudge_inference_if_ok(|| {
229            infcx
230                .visit_proof_tree(
231                    obligation.as_goal(),
232                    &mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
233                )
234                .break_value()
235                .ok_or(())
236        })
237        .unwrap_or(obligation);
238    deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
239}
240
241struct BestObligation<'db> {
242    obligation: PredicateObligation<'db>,
243    consider_ambiguities: bool,
244}
245
246impl<'db> BestObligation<'db> {
247    fn with_derived_obligation(
248        &mut self,
249        derived_obligation: PredicateObligation<'db>,
250        and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'db>>::Result,
251    ) -> <Self as ProofTreeVisitor<'db>>::Result {
252        let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
253        let res = and_then(self);
254        self.obligation = old_obligation;
255        res
256    }
257
258    /// Filter out the candidates that aren't interesting to visit for the
259    /// purposes of reporting errors. For ambiguities, we only consider
260    /// candidates that may hold. For errors, we only consider candidates that
261    /// *don't* hold and which have impl-where clauses that also don't hold.
262    fn non_trivial_candidates<'a>(
263        &self,
264        goal: &'a inspect::InspectGoal<'a, 'db>,
265    ) -> Vec<inspect::InspectCandidate<'a, 'db>> {
266        let mut candidates = goal.candidates();
267        match self.consider_ambiguities {
268            true => {
269                // If we have an ambiguous obligation, we must consider *all* candidates
270                // that hold, or else we may guide inference causing other goals to go
271                // from ambig -> pass/fail.
272                candidates.retain(|candidate| candidate.result().is_ok());
273            }
274            false => {
275                // We always handle rigid alias candidates separately as we may not add them for
276                // aliases whose trait bound doesn't hold.
277                candidates.retain(|c| !matches!(c.kind(), inspect::ProbeKind::RigidAlias { .. }));
278                // If we have >1 candidate, one may still be due to "boring" reasons, like
279                // an alias-relate that failed to hold when deeply evaluated. We really
280                // don't care about reasons like this.
281                if candidates.len() > 1 {
282                    candidates.retain(|candidate| {
283                        goal.infcx().probe(|_| {
284                            candidate.instantiate_nested_goals().iter().any(|nested_goal| {
285                                matches!(
286                                    nested_goal.source(),
287                                    GoalSource::ImplWhereBound
288                                        | GoalSource::AliasBoundConstCondition
289                                        | GoalSource::AliasWellFormed
290                                ) && nested_goal.result().is_err()
291                            })
292                        })
293                    });
294                }
295            }
296        }
297
298        candidates
299    }
300
301    /// HACK: We walk the nested obligations for a well-formed arg manually,
302    /// since there's nontrivial logic in `wf.rs` to set up an obligation cause.
303    /// Ideally we'd be able to track this better.
304    fn visit_well_formed_goal(
305        &mut self,
306        candidate: &inspect::InspectCandidate<'_, 'db>,
307        term: Term<'db>,
308    ) -> ControlFlow<PredicateObligation<'db>> {
309        let infcx = candidate.goal().infcx();
310        let param_env = candidate.goal().goal().param_env;
311
312        for obligation in wf::unnormalized_obligations(infcx, param_env, term).into_iter().flatten()
313        {
314            let nested_goal = candidate
315                .instantiate_proof_tree_for_nested_goal(GoalSource::Misc, obligation.as_goal());
316            // Skip nested goals that aren't the *reason* for our goal's failure.
317            match (self.consider_ambiguities, nested_goal.result()) {
318                (true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. }))
319                | (false, Err(_)) => {}
320                _ => continue,
321            }
322
323            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
324        }
325
326        ControlFlow::Break(self.obligation.clone())
327    }
328
329    /// If a normalization of an associated item or a trait goal fails without trying any
330    /// candidates it's likely that normalizing its self type failed. We manually detect
331    /// such cases here.
332    fn detect_error_in_self_ty_normalization(
333        &mut self,
334        goal: &inspect::InspectGoal<'_, 'db>,
335        self_ty: Ty<'db>,
336    ) -> ControlFlow<PredicateObligation<'db>> {
337        assert!(!self.consider_ambiguities);
338        let interner = goal.infcx().interner;
339        if let TyKind::Alias(..) = self_ty.kind() {
340            let infer_term = goal.infcx().next_ty_var();
341            let pred = PredicateKind::AliasRelate(
342                self_ty.into(),
343                infer_term.into(),
344                AliasRelationDirection::Equate,
345            );
346            let obligation = Obligation::new(
347                interner,
348                self.obligation.cause.clone(),
349                goal.goal().param_env,
350                pred,
351            );
352            self.with_derived_obligation(obligation, |this| {
353                goal.infcx().visit_proof_tree_at_depth(
354                    goal.goal().with(interner, pred),
355                    goal.depth() + 1,
356                    this,
357                )
358            })
359        } else {
360            ControlFlow::Continue(())
361        }
362    }
363
364    /// When a higher-ranked projection goal fails, check that the corresponding
365    /// higher-ranked trait goal holds or not. This is because the process of
366    /// instantiating and then re-canonicalizing the binder of the projection goal
367    /// forces us to be unable to see that the leak check failed in the nested
368    /// `NormalizesTo` goal, so we don't fall back to the rigid projection check
369    /// that should catch when a projection goal fails due to an unsatisfied trait
370    /// goal.
371    fn detect_trait_error_in_higher_ranked_projection(
372        &mut self,
373        goal: &inspect::InspectGoal<'_, 'db>,
374    ) -> ControlFlow<PredicateObligation<'db>> {
375        let interner = goal.infcx().interner;
376        if let Some(projection_clause) = goal.goal().predicate.as_projection_clause()
377            && !projection_clause.bound_vars().is_empty()
378        {
379            let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(interner));
380            let obligation = Obligation::new(
381                interner,
382                self.obligation.cause.clone(),
383                goal.goal().param_env,
384                deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
385            );
386            self.with_derived_obligation(obligation, |this| {
387                goal.infcx().visit_proof_tree_at_depth(
388                    goal.goal().with(interner, pred),
389                    goal.depth() + 1,
390                    this,
391                )
392            })
393        } else {
394            ControlFlow::Continue(())
395        }
396    }
397
398    /// It is likely that `NormalizesTo` failed without any applicable candidates
399    /// because the alias is not well-formed.
400    ///
401    /// As we only enter `RigidAlias` candidates if the trait bound of the associated type
402    /// holds, we discard these candidates in `non_trivial_candidates` and always manually
403    /// check this here.
404    fn detect_non_well_formed_assoc_item(
405        &mut self,
406        goal: &inspect::InspectGoal<'_, 'db>,
407        alias: AliasTerm<'db>,
408    ) -> ControlFlow<PredicateObligation<'db>> {
409        let interner = goal.infcx().interner;
410        let obligation = Obligation::new(
411            interner,
412            self.obligation.cause.clone(),
413            goal.goal().param_env,
414            alias.trait_ref(interner),
415        );
416        self.with_derived_obligation(obligation, |this| {
417            goal.infcx().visit_proof_tree_at_depth(
418                goal.goal().with(interner, alias.trait_ref(interner)),
419                goal.depth() + 1,
420                this,
421            )
422        })
423    }
424
425    /// If we have no candidates, then it's likely that there is a
426    /// non-well-formed alias in the goal.
427    fn detect_error_from_empty_candidates(
428        &mut self,
429        goal: &inspect::InspectGoal<'_, 'db>,
430    ) -> ControlFlow<PredicateObligation<'db>> {
431        let interner = goal.infcx().interner;
432        let pred_kind = goal.goal().predicate.kind();
433
434        match pred_kind.no_bound_vars() {
435            Some(PredicateKind::Clause(ClauseKind::Trait(pred))) => {
436                self.detect_error_in_self_ty_normalization(goal, pred.self_ty())?;
437            }
438            Some(PredicateKind::NormalizesTo(pred)) => {
439                if let AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst =
440                    pred.alias.kind(interner)
441                {
442                    self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?;
443                    self.detect_non_well_formed_assoc_item(goal, pred.alias)?;
444                }
445            }
446            Some(_) | None => {}
447        }
448
449        ControlFlow::Break(self.obligation.clone())
450    }
451}
452
453impl<'db> ProofTreeVisitor<'db> for BestObligation<'db> {
454    type Result = ControlFlow<PredicateObligation<'db>>;
455
456    #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))]
457    fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'db>) -> Self::Result {
458        let interner = goal.infcx().interner;
459        // Skip goals that aren't the *reason* for our goal's failure.
460        match (self.consider_ambiguities, goal.result()) {
461            (true, Ok(Certainty::Maybe { cause: MaybeCause::Ambiguity, .. })) | (false, Err(_)) => {
462            }
463            _ => return ControlFlow::Continue(()),
464        }
465
466        let pred = goal.goal().predicate;
467
468        let candidates = self.non_trivial_candidates(goal);
469        let candidate = match candidates.as_slice() {
470            [candidate] => candidate,
471            [] => return self.detect_error_from_empty_candidates(goal),
472            _ => return ControlFlow::Break(self.obligation.clone()),
473        };
474
475        // // Don't walk into impls that have `do_not_recommend`.
476        // if let inspect::ProbeKind::TraitCandidate {
477        //     source: CandidateSource::Impl(impl_def_id),
478        //     result: _,
479        // } = candidate.kind()
480        //     && interner.do_not_recommend_impl(impl_def_id)
481        // {
482        //     trace!("#[do_not_recommend] -> exit");
483        //     return ControlFlow::Break(self.obligation.clone());
484        // }
485
486        // FIXME: Also, what about considering >1 layer up the stack? May be necessary
487        // for normalizes-to.
488        let child_mode = match pred.kind().skip_binder() {
489            PredicateKind::Clause(ClauseKind::Trait(trait_pred)) => {
490                ChildMode::Trait(pred.kind().rebind(trait_pred))
491            }
492            PredicateKind::Clause(ClauseKind::HostEffect(host_pred)) => {
493                ChildMode::Host(pred.kind().rebind(host_pred))
494            }
495            PredicateKind::NormalizesTo(normalizes_to)
496                if matches!(
497                    normalizes_to.alias.kind(interner),
498                    AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
499                ) =>
500            {
501                ChildMode::Trait(pred.kind().rebind(TraitPredicate {
502                    trait_ref: normalizes_to.alias.trait_ref(interner),
503                    polarity: PredicatePolarity::Positive,
504                }))
505            }
506            PredicateKind::Clause(ClauseKind::WellFormed(term)) => {
507                return self.visit_well_formed_goal(candidate, term);
508            }
509            _ => ChildMode::PassThrough,
510        };
511
512        let nested_goals = candidate.instantiate_nested_goals();
513
514        // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as
515        // an actual candidate, instead we should treat them as if the impl was never considered to
516        // have potentially applied. As if `impl<A, R> Trait for for<..> fn(..A) -> R` was written
517        // instead of `impl<T: FnPtr> Trait for T`.
518        //
519        // We do this as a separate loop so that we do not choose to tell the user about some nested
520        // goal before we encounter a `T: FnPtr` nested goal.
521        for nested_goal in &nested_goals {
522            if let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
523                && interner
524                    .is_trait_lang_item(poly_trait_pred.def_id(), SolverTraitLangItem::FnPtrTrait)
525                && let Err(NoSolution) = nested_goal.result()
526            {
527                return ControlFlow::Break(self.obligation.clone());
528            }
529        }
530
531        for nested_goal in nested_goals {
532            trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
533
534            let nested_pred = nested_goal.goal().predicate;
535
536            let make_obligation = || Obligation {
537                cause: ObligationCause::dummy(),
538                param_env: nested_goal.goal().param_env,
539                predicate: nested_pred,
540                recursion_depth: self.obligation.recursion_depth + 1,
541            };
542
543            let obligation = match (child_mode, nested_goal.source()) {
544                (
545                    ChildMode::Trait(_) | ChildMode::Host(_),
546                    GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
547                ) => {
548                    continue;
549                }
550                (ChildMode::Trait(_parent_trait_pred), GoalSource::ImplWhereBound) => {
551                    make_obligation()
552                }
553                (
554                    ChildMode::Host(_parent_host_pred),
555                    GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
556                ) => make_obligation(),
557                (ChildMode::PassThrough, _)
558                | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
559                    make_obligation()
560                }
561            };
562
563            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
564        }
565
566        // alias-relate may fail because the lhs or rhs can't be normalized,
567        // and therefore is treated as rigid.
568        if let Some(PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() {
569            goal.infcx().visit_proof_tree_at_depth(
570                goal.goal().with(interner, ClauseKind::WellFormed(lhs)),
571                goal.depth() + 1,
572                self,
573            )?;
574            goal.infcx().visit_proof_tree_at_depth(
575                goal.goal().with(interner, ClauseKind::WellFormed(rhs)),
576                goal.depth() + 1,
577                self,
578            )?;
579        }
580
581        self.detect_trait_error_in_higher_ranked_projection(goal)?;
582
583        ControlFlow::Break(self.obligation.clone())
584    }
585}
586
587#[derive(Debug, Copy, Clone)]
588enum ChildMode<'db> {
589    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
590    // and skip all `GoalSource::Misc`, which represent useless obligations
591    // such as alias-eq which may not hold.
592    Trait(PolyTraitPredicate<'db>),
593    // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
594    // and skip all `GoalSource::Misc`, which represent useless obligations
595    // such as alias-eq which may not hold.
596    Host(Binder<'db, HostEffectPredicate<DbInterner<'db>>>),
597    // Skip trying to derive an `ObligationCause` from this obligation, and
598    // report *all* sub-obligations as if they came directly from the parent
599    // obligation.
600    PassThrough,
601}
602
603impl<'db> NextSolverError<'db> {
604    pub fn to_debuggable_error(&self, infcx: &InferCtxt<'db>) -> FulfillmentError<'db> {
605        match self {
606            NextSolverError::TrueError(obligation) => {
607                fulfillment_error_for_no_solution(infcx, obligation.clone())
608            }
609            NextSolverError::Ambiguity(obligation) => {
610                fulfillment_error_for_stalled(infcx, obligation.clone())
611            }
612            NextSolverError::Overflow(obligation) => {
613                fulfillment_error_for_overflow(infcx, obligation.clone())
614            }
615        }
616    }
617}
618
619mod wf {
620    use hir_def::{GeneralConstId, ItemContainerId};
621    use rustc_type_ir::inherent::{
622        AdtDef, BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Term as _,
623        Ty as _,
624    };
625    use rustc_type_ir::lang_items::SolverTraitLangItem;
626    use rustc_type_ir::{
627        Interner, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
628    };
629    use tracing::{debug, instrument};
630
631    use crate::next_solver::infer::InferCtxt;
632    use crate::next_solver::infer::traits::{Obligation, ObligationCause, PredicateObligations};
633    use crate::next_solver::{
634        Binder, ClauseKind, Const, ConstKind, Ctor, DbInterner, ExistentialPredicate, GenericArgs,
635        ParamEnv, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty, TyKind,
636    };
637
638    /// Compute the predicates that are required for a type to be well-formed.
639    ///
640    /// This is only intended to be used in the new solver, since it does not
641    /// take into account recursion depth or proper error-reporting spans.
642    pub(crate) fn unnormalized_obligations<'db>(
643        infcx: &InferCtxt<'db>,
644        param_env: ParamEnv<'db>,
645        term: Term<'db>,
646    ) -> Option<PredicateObligations<'db>> {
647        debug_assert_eq!(term, infcx.resolve_vars_if_possible(term));
648
649        // However, if `arg` IS an unresolved inference variable, returns `None`,
650        // because we are not able to make any progress at all. This is to prevent
651        // cycles where we say "?0 is WF if ?0 is WF".
652        if term.is_infer() {
653            return None;
654        }
655
656        let mut wf =
657            WfPredicates { infcx, param_env, out: PredicateObligations::new(), recursion_depth: 0 };
658        wf.add_wf_preds_for_term(term);
659        Some(wf.out)
660    }
661
662    struct WfPredicates<'a, 'db> {
663        infcx: &'a InferCtxt<'db>,
664        param_env: ParamEnv<'db>,
665        out: PredicateObligations<'db>,
666        recursion_depth: usize,
667    }
668
669    impl<'a, 'db> WfPredicates<'a, 'db> {
670        fn interner(&self) -> DbInterner<'db> {
671            self.infcx.interner
672        }
673
674        fn require_sized(&mut self, subty: Ty<'db>) {
675            if !subty.has_escaping_bound_vars() {
676                let cause = ObligationCause::new();
677                let trait_ref = TraitRef::new(
678                    self.interner(),
679                    self.interner().require_trait_lang_item(SolverTraitLangItem::Sized),
680                    [subty],
681                );
682                self.out.push(Obligation::with_depth(
683                    self.interner(),
684                    cause,
685                    self.recursion_depth,
686                    self.param_env,
687                    Binder::dummy(trait_ref),
688                ));
689            }
690        }
691
692        /// Pushes all the predicates needed to validate that `term` is WF into `out`.
693        #[instrument(level = "debug", skip(self))]
694        fn add_wf_preds_for_term(&mut self, term: Term<'db>) {
695            term.visit_with(self);
696            debug!(?self.out);
697        }
698
699        #[instrument(level = "debug", skip(self))]
700        fn nominal_obligations(
701            &mut self,
702            def_id: SolverDefId,
703            args: GenericArgs<'db>,
704        ) -> PredicateObligations<'db> {
705            // PERF: `Sized`'s predicates include `MetaSized`, but both are compiler implemented marker
706            // traits, so `MetaSized` will always be WF if `Sized` is WF and vice-versa. Determining
707            // the nominal obligations of `Sized` would in-effect just elaborate `MetaSized` and make
708            // the compiler do a bunch of work needlessly.
709            if let SolverDefId::TraitId(def_id) = def_id
710                && self.interner().is_trait_lang_item(def_id.into(), SolverTraitLangItem::Sized)
711            {
712                return Default::default();
713            }
714
715            self.interner()
716                .predicates_of(def_id)
717                .iter_instantiated(self.interner(), args)
718                .map(|pred| {
719                    let cause = ObligationCause::new();
720                    Obligation::with_depth(
721                        self.interner(),
722                        cause,
723                        self.recursion_depth,
724                        self.param_env,
725                        pred,
726                    )
727                })
728                .filter(|pred| !pred.has_escaping_bound_vars())
729                .collect()
730        }
731
732        fn add_wf_preds_for_dyn_ty(
733            &mut self,
734            _ty: Ty<'db>,
735            data: &[Binder<'db, ExistentialPredicate<'db>>],
736            region: Region<'db>,
737        ) {
738            // Imagine a type like this:
739            //
740            //     trait Foo { }
741            //     trait Bar<'c> : 'c { }
742            //
743            //     &'b (Foo+'c+Bar<'d>)
744            //         ^
745            //
746            // In this case, the following relationships must hold:
747            //
748            //     'b <= 'c
749            //     'd <= 'c
750            //
751            // The first conditions is due to the normal region pointer
752            // rules, which say that a reference cannot outlive its
753            // referent.
754            //
755            // The final condition may be a bit surprising. In particular,
756            // you may expect that it would have been `'c <= 'd`, since
757            // usually lifetimes of outer things are conservative
758            // approximations for inner things. However, it works somewhat
759            // differently with trait objects: here the idea is that if the
760            // user specifies a region bound (`'c`, in this case) it is the
761            // "master bound" that *implies* that bounds from other traits are
762            // all met. (Remember that *all bounds* in a type like
763            // `Foo+Bar+Zed` must be met, not just one, hence if we write
764            // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
765            // 'y.)
766            //
767            // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
768            // am looking forward to the future here.
769            if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
770                let implicit_bounds = object_region_bounds(self.interner(), data);
771
772                let explicit_bound = region;
773
774                self.out.reserve(implicit_bounds.len());
775                for implicit_bound in implicit_bounds {
776                    let cause = ObligationCause::new();
777                    let outlives = Binder::dummy(rustc_type_ir::OutlivesPredicate(
778                        explicit_bound,
779                        implicit_bound,
780                    ));
781                    self.out.push(Obligation::with_depth(
782                        self.interner(),
783                        cause,
784                        self.recursion_depth,
785                        self.param_env,
786                        outlives,
787                    ));
788                }
789
790                // We don't add any wf predicates corresponding to the trait ref's generic arguments
791                // which allows code like this to compile:
792                // ```rust
793                // trait Trait<T: Sized> {}
794                // fn foo(_: &dyn Trait<[u32]>) {}
795                // ```
796            }
797        }
798    }
799
800    impl<'a, 'db> TypeVisitor<DbInterner<'db>> for WfPredicates<'a, 'db> {
801        type Result = ();
802
803        fn visit_ty(&mut self, t: Ty<'db>) -> Self::Result {
804            debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
805
806            let tcx = self.interner();
807
808            match t.kind() {
809                TyKind::Bool
810                | TyKind::Char
811                | TyKind::Int(..)
812                | TyKind::Uint(..)
813                | TyKind::Float(..)
814                | TyKind::Error(_)
815                | TyKind::Str
816                | TyKind::CoroutineWitness(..)
817                | TyKind::Never
818                | TyKind::Param(_)
819                | TyKind::Bound(..)
820                | TyKind::Placeholder(..)
821                | TyKind::Foreign(..) => {
822                    // WfScalar, WfParameter, etc
823                }
824
825                // Can only infer to `TyKind::Int(_) | TyKind::Uint(_)`.
826                TyKind::Infer(rustc_type_ir::IntVar(_)) => {}
827
828                // Can only infer to `TyKind::Float(_)`.
829                TyKind::Infer(rustc_type_ir::FloatVar(_)) => {}
830
831                TyKind::Slice(subty) => {
832                    self.require_sized(subty);
833                }
834
835                TyKind::Array(subty, len) => {
836                    self.require_sized(subty);
837                    // Note that the len being WF is implicitly checked while visiting.
838                    // Here we just check that it's of type usize.
839                    let cause = ObligationCause::new();
840                    self.out.push(Obligation::with_depth(
841                        tcx,
842                        cause,
843                        self.recursion_depth,
844                        self.param_env,
845                        Binder::dummy(PredicateKind::Clause(ClauseKind::ConstArgHasType(
846                            len,
847                            Ty::new_unit(self.interner()),
848                        ))),
849                    ));
850                }
851
852                TyKind::Pat(base_ty, _pat) => {
853                    self.require_sized(base_ty);
854                }
855
856                TyKind::Tuple(tys) => {
857                    if let Some((_last, rest)) = tys.split_last() {
858                        for &elem in rest {
859                            self.require_sized(elem);
860                        }
861                    }
862                }
863
864                TyKind::RawPtr(_, _) => {
865                    // Simple cases that are WF if their type args are WF.
866                }
867
868                TyKind::Alias(
869                    rustc_type_ir::Projection | rustc_type_ir::Opaque | rustc_type_ir::Free,
870                    data,
871                ) => {
872                    let obligations = self.nominal_obligations(data.def_id, data.args);
873                    self.out.extend(obligations);
874                }
875                TyKind::Alias(rustc_type_ir::Inherent, _data) => {
876                    return;
877                }
878
879                TyKind::Adt(def, args) => {
880                    // WfNominalType
881                    let obligations = self.nominal_obligations(def.def_id().0.into(), args);
882                    self.out.extend(obligations);
883                }
884
885                TyKind::FnDef(did, args) => {
886                    // HACK: Check the return type of function definitions for
887                    // well-formedness to mostly fix #84533. This is still not
888                    // perfect and there may be ways to abuse the fact that we
889                    // ignore requirements with escaping bound vars. That's a
890                    // more general issue however.
891                    let fn_sig = tcx.fn_sig(did).instantiate(tcx, args);
892                    fn_sig.output().skip_binder().visit_with(self);
893
894                    let did = match did.0 {
895                        hir_def::CallableDefId::FunctionId(id) => id.into(),
896                        hir_def::CallableDefId::StructId(id) => SolverDefId::Ctor(Ctor::Struct(id)),
897                        hir_def::CallableDefId::EnumVariantId(id) => {
898                            SolverDefId::Ctor(Ctor::Enum(id))
899                        }
900                    };
901                    let obligations = self.nominal_obligations(did, args);
902                    self.out.extend(obligations);
903                }
904
905                TyKind::Ref(r, rty, _) => {
906                    // WfReference
907                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
908                        let cause = ObligationCause::new();
909                        self.out.push(Obligation::with_depth(
910                            tcx,
911                            cause,
912                            self.recursion_depth,
913                            self.param_env,
914                            Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(
915                                rustc_type_ir::OutlivesPredicate(rty, r),
916                            ))),
917                        ));
918                    }
919                }
920
921                TyKind::Coroutine(did, args, ..) => {
922                    // Walk ALL the types in the coroutine: this will
923                    // include the upvar types as well as the yield
924                    // type. Note that this is mildly distinct from
925                    // the closure case, where we have to be careful
926                    // about the signature of the closure. We don't
927                    // have the problem of implied bounds here since
928                    // coroutines don't take arguments.
929                    let obligations = self.nominal_obligations(did.0.into(), args);
930                    self.out.extend(obligations);
931                }
932
933                TyKind::Closure(did, args) => {
934                    // Note that we cannot skip the generic types
935                    // types. Normally, within the fn
936                    // body where they are created, the generics will
937                    // always be WF, and outside of that fn body we
938                    // are not directly inspecting closure types
939                    // anyway, except via auto trait matching (which
940                    // only inspects the upvar types).
941                    // But when a closure is part of a type-alias-impl-trait
942                    // then the function that created the defining site may
943                    // have had more bounds available than the type alias
944                    // specifies. This may cause us to have a closure in the
945                    // hidden type that is not actually well formed and
946                    // can cause compiler crashes when the user abuses unsafe
947                    // code to procure such a closure.
948                    // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
949                    let obligations = self.nominal_obligations(did.0.into(), args);
950                    self.out.extend(obligations);
951                    // Only check the upvar types for WF, not the rest
952                    // of the types within. This is needed because we
953                    // capture the signature and it may not be WF
954                    // without the implied bounds. Consider a closure
955                    // like `|x: &'a T|` -- it may be that `T: 'a` is
956                    // not known to hold in the creator's context (and
957                    // indeed the closure may not be invoked by its
958                    // creator, but rather turned to someone who *can*
959                    // verify that).
960                    //
961                    // The special treatment of closures here really
962                    // ought not to be necessary either; the problem
963                    // is related to #25860 -- there is no way for us
964                    // to express a fn type complete with the implied
965                    // bounds that it is assuming. I think in reality
966                    // the WF rules around fn are a bit messed up, and
967                    // that is the rot problem: `fn(&'a T)` should
968                    // probably always be WF, because it should be
969                    // shorthand for something like `where(T: 'a) {
970                    // fn(&'a T) }`, as discussed in #25860.
971                    let upvars = args.as_closure().tupled_upvars_ty();
972                    return upvars.visit_with(self);
973                }
974
975                TyKind::CoroutineClosure(did, args) => {
976                    // See the above comments. The same apply to coroutine-closures.
977                    let obligations = self.nominal_obligations(did.0.into(), args);
978                    self.out.extend(obligations);
979                    let upvars = args.as_coroutine_closure().tupled_upvars_ty();
980                    return upvars.visit_with(self);
981                }
982
983                TyKind::FnPtr(..) => {
984                    // Let the visitor iterate into the argument/return
985                    // types appearing in the fn signature.
986                }
987                TyKind::UnsafeBinder(_ty) => {}
988
989                TyKind::Dynamic(data, r) => {
990                    // WfObject
991                    //
992                    // Here, we defer WF checking due to higher-ranked
993                    // regions. This is perhaps not ideal.
994                    self.add_wf_preds_for_dyn_ty(t, data.as_slice(), r);
995
996                    // FIXME(#27579) RFC also considers adding trait
997                    // obligations that don't refer to Self and
998                    // checking those
999                    if let Some(principal) = data.principal_def_id() {
1000                        self.out.push(Obligation::with_depth(
1001                            tcx,
1002                            ObligationCause::new(),
1003                            self.recursion_depth,
1004                            self.param_env,
1005                            Binder::dummy(PredicateKind::DynCompatible(principal)),
1006                        ));
1007                    }
1008                }
1009
1010                // Inference variables are the complicated case, since we don't
1011                // know what type they are. We do two things:
1012                //
1013                // 1. Check if they have been resolved, and if so proceed with
1014                //    THAT type.
1015                // 2. If not, we've at least simplified things (e.g., we went
1016                //    from `Vec?0>: WF` to `?0: WF`), so we can
1017                //    register a pending obligation and keep
1018                //    moving. (Goal is that an "inductive hypothesis"
1019                //    is satisfied to ensure termination.)
1020                // See also the comment on `fn obligations`, describing cycle
1021                // prevention, which happens before this can be reached.
1022                TyKind::Infer(_) => {
1023                    let cause = ObligationCause::new();
1024                    self.out.push(Obligation::with_depth(
1025                        tcx,
1026                        cause,
1027                        self.recursion_depth,
1028                        self.param_env,
1029                        Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(t.into()))),
1030                    ));
1031                }
1032            }
1033
1034            t.super_visit_with(self)
1035        }
1036
1037        fn visit_const(&mut self, c: Const<'db>) -> Self::Result {
1038            let tcx = self.interner();
1039
1040            match c.kind() {
1041                ConstKind::Unevaluated(uv) => {
1042                    if !c.has_escaping_bound_vars() {
1043                        let predicate =
1044                            Binder::dummy(PredicateKind::Clause(ClauseKind::ConstEvaluatable(c)));
1045                        let cause = ObligationCause::new();
1046                        self.out.push(Obligation::with_depth(
1047                            tcx,
1048                            cause,
1049                            self.recursion_depth,
1050                            self.param_env,
1051                            predicate,
1052                        ));
1053
1054                        if let GeneralConstId::ConstId(uv_def) = uv.def.0
1055                            && let ItemContainerId::ImplId(impl_) =
1056                                uv_def.loc(self.interner().db).container
1057                            && self.interner().db.impl_signature(impl_).target_trait.is_none()
1058                        {
1059                            return; // Subtree is handled by above function
1060                        } else {
1061                            let obligations = self.nominal_obligations(uv.def.into(), uv.args);
1062                            self.out.extend(obligations);
1063                        }
1064                    }
1065                }
1066                ConstKind::Infer(_) => {
1067                    let cause = ObligationCause::new();
1068
1069                    self.out.push(Obligation::with_depth(
1070                        tcx,
1071                        cause,
1072                        self.recursion_depth,
1073                        self.param_env,
1074                        Binder::dummy(PredicateKind::Clause(ClauseKind::WellFormed(c.into()))),
1075                    ));
1076                }
1077                ConstKind::Expr(_) => {
1078                    // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
1079                    // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
1080                    // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
1081                    // which means that the `DefId` would have been typeck'd elsewhere. However in
1082                    // the future we may allow directly lowering to `ConstKind::Expr` in which case
1083                    // we would not be proving bounds we should.
1084
1085                    let predicate =
1086                        Binder::dummy(PredicateKind::Clause(ClauseKind::ConstEvaluatable(c)));
1087                    let cause = ObligationCause::new();
1088                    self.out.push(Obligation::with_depth(
1089                        tcx,
1090                        cause,
1091                        self.recursion_depth,
1092                        self.param_env,
1093                        predicate,
1094                    ));
1095                }
1096
1097                ConstKind::Error(_)
1098                | ConstKind::Param(_)
1099                | ConstKind::Bound(..)
1100                | ConstKind::Placeholder(..) => {
1101                    // These variants are trivially WF, so nothing to do here.
1102                }
1103                ConstKind::Value(..) => {
1104                    // FIXME: Enforce that values are structurally-matchable.
1105                }
1106            }
1107
1108            c.super_visit_with(self)
1109        }
1110
1111        fn visit_predicate(&mut self, _p: Predicate<'db>) -> Self::Result {
1112            panic!("predicate should not be checked for well-formedness");
1113        }
1114    }
1115
1116    /// Given an object type like `SomeTrait + Send`, computes the lifetime
1117    /// bounds that must hold on the elided self type. These are derived
1118    /// from the declarations of `SomeTrait`, `Send`, and friends -- if
1119    /// they declare `trait SomeTrait : 'static`, for example, then
1120    /// `'static` would appear in the list.
1121    ///
1122    /// N.B., in some cases, particularly around higher-ranked bounds,
1123    /// this function returns a kind of conservative approximation.
1124    /// That is, all regions returned by this function are definitely
1125    /// required, but there may be other region bounds that are not
1126    /// returned, as well as requirements like `for<'a> T: 'a`.
1127    ///
1128    /// Requires that trait definitions have been processed so that we can
1129    /// elaborate predicates and walk supertraits.
1130    pub(crate) fn object_region_bounds<'db>(
1131        interner: DbInterner<'db>,
1132        existential_predicates: &[Binder<'db, ExistentialPredicate<'db>>],
1133    ) -> Vec<Region<'db>> {
1134        let erased_self_ty = Ty::new_unit(interner);
1135
1136        let predicates = existential_predicates
1137            .iter()
1138            .map(|predicate| predicate.with_self_ty(interner, erased_self_ty));
1139
1140        rustc_type_ir::elaborate::elaborate(interner, predicates)
1141            .filter_map(|pred| {
1142                debug!(?pred);
1143                match pred.kind().skip_binder() {
1144                    ClauseKind::TypeOutlives(rustc_type_ir::OutlivesPredicate(ref t, ref r)) => {
1145                        // Search for a bound of the form `erased_self_ty
1146                        // : 'a`, but be wary of something like `for<'a>
1147                        // erased_self_ty : 'a` (we interpret a
1148                        // higher-ranked bound like that as 'static,
1149                        // though at present the code in `fulfill.rs`
1150                        // considers such bounds to be unsatisfiable, so
1151                        // it's kind of a moot point since you could never
1152                        // construct such an object, but this seems
1153                        // correct even if that code changes).
1154                        if t == &erased_self_ty && !r.has_escaping_bound_vars() {
1155                            Some(*r)
1156                        } else {
1157                            None
1158                        }
1159                    }
1160                    ClauseKind::Trait(_)
1161                    | ClauseKind::HostEffect(..)
1162                    | ClauseKind::RegionOutlives(_)
1163                    | ClauseKind::Projection(_)
1164                    | ClauseKind::ConstArgHasType(_, _)
1165                    | ClauseKind::WellFormed(_)
1166                    | ClauseKind::UnstableFeature(_)
1167                    | ClauseKind::ConstEvaluatable(_) => None,
1168                }
1169            })
1170            .collect()
1171    }
1172}