rustc_trait_selection/traits/
fulfill.rs

1use std::marker::PhantomData;
2
3use rustc_data_structures::obligation_forest::{
4    Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult,
5};
6use rustc_hir::def_id::LocalDefId;
7use rustc_infer::infer::DefineOpaqueTypes;
8use rustc_infer::traits::{
9    FromSolverError, PolyTraitObligation, PredicateObligations, ProjectionCacheKey, SelectionError,
10    TraitEngine,
11};
12use rustc_middle::bug;
13use rustc_middle::ty::abstract_const::NotConstEvaluatable;
14use rustc_middle::ty::error::{ExpectedFound, TypeError};
15use rustc_middle::ty::{
16    self, Binder, Const, GenericArgsRef, TypeVisitable, TypeVisitableExt, TypingMode,
17    may_use_unstable_feature,
18};
19use rustc_span::DUMMY_SP;
20use thin_vec::{ThinVec, thin_vec};
21use tracing::{debug, debug_span, instrument};
22
23use super::effects::{self, HostEffectObligation};
24use super::project::{self, ProjectAndUnifyResult};
25use super::select::SelectionContext;
26use super::{
27    EvaluationResult, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
28    ScrubbedTraitError, const_evaluatable, wf,
29};
30use crate::error_reporting::InferCtxtErrorExt;
31use crate::infer::{InferCtxt, TyOrConstInferVar};
32use crate::solve::StalledOnCoroutines;
33use crate::traits::normalize::normalize_with_depth_to;
34use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
35use crate::traits::query::evaluate_obligation::InferCtxtExt;
36use crate::traits::{EvaluateConstErr, sizedness_fast_path};
37
38pub(crate) type PendingPredicateObligations<'tcx> = ThinVec<PendingPredicateObligation<'tcx>>;
39
40impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
41    /// Note that we include both the `ParamEnv` and the `Predicate`,
42    /// as the `ParamEnv` can influence whether fulfillment succeeds
43    /// or fails.
44    type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
45
46    fn as_cache_key(&self) -> Self::CacheKey {
47        self.obligation.param_env.and(self.obligation.predicate)
48    }
49}
50
51/// The fulfillment context is used to drive trait resolution. It
52/// consists of a list of obligations that must be (eventually)
53/// satisfied. The job is to track which are satisfied, which yielded
54/// errors, and which are still pending. At any point, users can call
55/// `select_where_possible`, and the fulfillment context will try to do
56/// selection, retaining only those obligations that remain
57/// ambiguous. This may be helpful in pushing type inference
58/// along. Once all type inference constraints have been generated, the
59/// method `select_all_or_error` can be used to report any remaining
60/// ambiguous cases as errors.
61pub struct FulfillmentContext<'tcx, E: 'tcx> {
62    /// A list of all obligations that have been registered with this
63    /// fulfillment context.
64    predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
65
66    /// The snapshot in which this context was created. Using the context
67    /// outside of this snapshot leads to subtle bugs if the snapshot
68    /// gets rolled back. Because of this we explicitly check that we only
69    /// use the context in exactly this snapshot.
70    usable_in_snapshot: usize,
71
72    _errors: PhantomData<E>,
73}
74
75#[derive(Clone, Debug)]
76pub struct PendingPredicateObligation<'tcx> {
77    pub obligation: PredicateObligation<'tcx>,
78    // This is far more often read than modified, meaning that we
79    // should mostly optimize for reading speed, while modifying is not as relevant.
80    //
81    // For whatever reason using a boxed slice is slower than using a `Vec` here.
82    pub stalled_on: Vec<TyOrConstInferVar>,
83}
84
85// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
86#[cfg(target_pointer_width = "64")]
87rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
88
89impl<'tcx, E> FulfillmentContext<'tcx, E>
90where
91    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
92{
93    /// Creates a new fulfillment context.
94    pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
95        assert!(
96            !infcx.next_trait_solver(),
97            "old trait solver fulfillment context created when \
98            infcx is set up for new trait solver"
99        );
100        FulfillmentContext {
101            predicates: ObligationForest::new(),
102            usable_in_snapshot: infcx.num_open_snapshots(),
103            _errors: PhantomData,
104        }
105    }
106
107    /// Attempts to select obligations using `selcx`.
108    fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<E> {
109        let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
110        let _enter = span.enter();
111        let infcx = selcx.infcx;
112
113        // Process pending obligations.
114        let outcome: Outcome<_, _> =
115            self.predicates.process_obligations(&mut FulfillProcessor { selcx });
116
117        // FIXME: if we kept the original cache key, we could mark projection
118        // obligations as complete for the projection cache here.
119
120        let errors: Vec<E> = outcome
121            .errors
122            .into_iter()
123            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
124            .collect();
125
126        debug!(
127            "select({} predicates remaining, {} errors) done",
128            self.predicates.len(),
129            errors.len()
130        );
131
132        errors
133    }
134}
135
136impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E>
137where
138    E: FromSolverError<'tcx, OldSolverError<'tcx>>,
139{
140    #[inline]
141    fn register_predicate_obligation(
142        &mut self,
143        infcx: &InferCtxt<'tcx>,
144        mut obligation: PredicateObligation<'tcx>,
145    ) {
146        assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
147        // this helps to reduce duplicate errors, as well as making
148        // debug output much nicer to read and so on.
149        debug_assert!(!obligation.param_env.has_non_region_infer());
150        obligation.predicate = infcx.resolve_vars_if_possible(obligation.predicate);
151
152        debug!(?obligation, "register_predicate_obligation");
153
154        self.predicates
155            .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
156    }
157
158    fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
159        self.predicates
160            .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
161            .into_iter()
162            .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
163            .collect()
164    }
165
166    fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
167        let selcx = SelectionContext::new(infcx);
168        self.select(selcx)
169    }
170
171    fn drain_stalled_obligations_for_coroutines(
172        &mut self,
173        infcx: &InferCtxt<'tcx>,
174    ) -> PredicateObligations<'tcx> {
175        let stalled_coroutines = match infcx.typing_mode() {
176            TypingMode::Analysis { defining_opaque_types_and_generators } => {
177                defining_opaque_types_and_generators
178            }
179            TypingMode::Coherence
180            | TypingMode::Borrowck { defining_opaque_types: _ }
181            | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
182            | TypingMode::PostAnalysis => return Default::default(),
183        };
184
185        if stalled_coroutines.is_empty() {
186            return Default::default();
187        }
188
189        let mut processor = DrainProcessor {
190            infcx,
191            removed_predicates: PredicateObligations::new(),
192            stalled_coroutines,
193        };
194        let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor);
195        assert!(outcome.errors.is_empty());
196        return processor.removed_predicates;
197
198        struct DrainProcessor<'a, 'tcx> {
199            infcx: &'a InferCtxt<'tcx>,
200            removed_predicates: PredicateObligations<'tcx>,
201            stalled_coroutines: &'tcx ty::List<LocalDefId>,
202        }
203
204        impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> {
205            type Obligation = PendingPredicateObligation<'tcx>;
206            type Error = !;
207            type OUT = Outcome<Self::Obligation, Self::Error>;
208
209            fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
210                self.infcx
211                    .resolve_vars_if_possible(pending_obligation.obligation.predicate)
212                    .visit_with(&mut StalledOnCoroutines {
213                        stalled_coroutines: self.stalled_coroutines,
214                        span: DUMMY_SP,
215                        cache: Default::default(),
216                    })
217                    .is_break()
218            }
219
220            fn process_obligation(
221                &mut self,
222                pending_obligation: &mut PendingPredicateObligation<'tcx>,
223            ) -> ProcessResult<PendingPredicateObligation<'tcx>, !> {
224                assert!(self.needs_process_obligation(pending_obligation));
225                self.removed_predicates.push(pending_obligation.obligation.clone());
226                ProcessResult::Changed(Default::default())
227            }
228
229            fn process_backedge<'c, I>(
230                &mut self,
231                cycle: I,
232                _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
233            ) -> Result<(), !>
234            where
235                I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
236            {
237                self.removed_predicates.extend(cycle.map(|c| c.obligation.clone()));
238                Ok(())
239            }
240        }
241    }
242
243    fn has_pending_obligations(&self) -> bool {
244        self.predicates.has_pending_obligations()
245    }
246
247    fn pending_obligations(&self) -> PredicateObligations<'tcx> {
248        self.predicates.map_pending_obligations(|o| o.obligation.clone())
249    }
250}
251
252struct FulfillProcessor<'a, 'tcx> {
253    selcx: SelectionContext<'a, 'tcx>,
254}
255
256fn mk_pending<'tcx>(
257    parent: &PredicateObligation<'tcx>,
258    os: PredicateObligations<'tcx>,
259) -> PendingPredicateObligations<'tcx> {
260    os.into_iter()
261        .map(|mut o| {
262            o.set_depth_from_parent(parent.recursion_depth);
263            PendingPredicateObligation { obligation: o, stalled_on: vec![] }
264        })
265        .collect()
266}
267
268impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
269    type Obligation = PendingPredicateObligation<'tcx>;
270    type Error = FulfillmentErrorCode<'tcx>;
271    type OUT = Outcome<Self::Obligation, Self::Error>;
272
273    /// Compared to `needs_process_obligation` this and its callees
274    /// contain some optimizations that come at the price of false negatives.
275    ///
276    /// They
277    /// - reduce branching by covering only the most common case
278    /// - take a read-only view of the unification tables which allows skipping undo_log
279    ///   construction.
280    /// - bail out on value-cache misses in ena to avoid pointer chasing
281    /// - hoist RefCell locking out of the loop
282    #[inline]
283    fn skippable_obligations<'b>(
284        &'b self,
285        it: impl Iterator<Item = &'b Self::Obligation>,
286    ) -> usize {
287        let is_unchanged = self.selcx.infcx.is_ty_infer_var_definitely_unchanged();
288
289        it.take_while(|o| match o.stalled_on.as_slice() {
290            [o] => is_unchanged(*o),
291            _ => false,
292        })
293        .count()
294    }
295
296    /// Identifies whether a predicate obligation needs processing.
297    ///
298    /// This is always inlined because it has a single callsite and it is
299    /// called *very* frequently. Be careful modifying this code! Several
300    /// compile-time benchmarks are very sensitive to even small changes.
301    #[inline(always)]
302    fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
303        // If we were stalled on some unresolved variables, first check whether
304        // any of them have been resolved; if not, don't bother doing more work
305        // yet.
306        let stalled_on = &pending_obligation.stalled_on;
307        match stalled_on.len() {
308            // This case is the hottest most of the time, being hit up to 99%
309            // of the time. `keccak` and `cranelift-codegen-0.82.1` are
310            // benchmarks that particularly stress this path.
311            1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
312
313            // In this case we haven't changed, but wish to make a change. Note
314            // that this is a special case, and is not equivalent to the `_`
315            // case below, which would return `false` for an empty `stalled_on`
316            // vector.
317            //
318            // This case is usually hit only 1% of the time or less, though it
319            // reaches 20% in `wasmparser-0.101.0`.
320            0 => true,
321
322            // This case is usually hit only 1% of the time or less, though it
323            // reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
324            // `inflate-0.4.5`.
325            //
326            // The obvious way of writing this, with a call to `any()` and no
327            // closure, is currently slower than this version.
328            _ => (|| {
329                for &infer_var in stalled_on {
330                    if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
331                        return true;
332                    }
333                }
334                false
335            })(),
336        }
337    }
338
339    /// Processes a predicate obligation and returns either:
340    /// - `Changed(v)` if the predicate is true, presuming that `v` are also true
341    /// - `Unchanged` if we don't have enough info to be sure
342    /// - `Error(e)` if the predicate does not hold
343    ///
344    /// This is called much less often than `needs_process_obligation`, so we
345    /// never inline it.
346    #[inline(never)]
347    #[instrument(level = "debug", skip(self, pending_obligation))]
348    fn process_obligation(
349        &mut self,
350        pending_obligation: &mut PendingPredicateObligation<'tcx>,
351    ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
352        pending_obligation.stalled_on.truncate(0);
353
354        let obligation = &mut pending_obligation.obligation;
355
356        debug!(?obligation, "pre-resolve");
357
358        if obligation.predicate.has_non_region_infer() {
359            obligation.predicate = self.selcx.infcx.resolve_vars_if_possible(obligation.predicate);
360        }
361
362        let obligation = &pending_obligation.obligation;
363
364        let infcx = self.selcx.infcx;
365
366        if sizedness_fast_path(infcx.tcx, obligation.predicate) {
367            return ProcessResult::Changed(thin_vec![]);
368        }
369
370        if obligation.predicate.has_aliases() {
371            let mut obligations = PredicateObligations::new();
372            let predicate = normalize_with_depth_to(
373                &mut self.selcx,
374                obligation.param_env,
375                obligation.cause.clone(),
376                obligation.recursion_depth + 1,
377                obligation.predicate,
378                &mut obligations,
379            );
380            if predicate != obligation.predicate {
381                obligations.push(obligation.with(infcx.tcx, predicate));
382                return ProcessResult::Changed(mk_pending(obligation, obligations));
383            }
384        }
385        let binder = obligation.predicate.kind();
386        match binder.no_bound_vars() {
387            None => match binder.skip_binder() {
388                // Evaluation will discard candidates using the leak check.
389                // This means we need to pass it the bound version of our
390                // predicate.
391                ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) => {
392                    let trait_obligation = obligation.with(infcx.tcx, binder.rebind(trait_ref));
393
394                    self.process_trait_obligation(
395                        obligation,
396                        trait_obligation,
397                        &mut pending_obligation.stalled_on,
398                    )
399                }
400                ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
401                    let project_obligation = obligation.with(infcx.tcx, binder.rebind(data));
402
403                    self.process_projection_obligation(
404                        obligation,
405                        project_obligation,
406                        &mut pending_obligation.stalled_on,
407                    )
408                }
409                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
410                | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
411                | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
412                | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
413                | ty::PredicateKind::DynCompatible(_)
414                | ty::PredicateKind::Subtype(_)
415                | ty::PredicateKind::Coerce(_)
416                | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
417                | ty::PredicateKind::ConstEquate(..)
418                // FIXME(const_trait_impl): We may need to do this using the higher-ranked
419                // pred instead of just instantiating it with placeholders b/c of
420                // higher-ranked implied bound issues in the old solver.
421                | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
422                    let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
423                    let mut obligations = PredicateObligations::with_capacity(1);
424                    obligations.push(obligation.with(infcx.tcx, pred));
425
426                    ProcessResult::Changed(mk_pending(obligation, obligations))
427                }
428                ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
429                ty::PredicateKind::NormalizesTo(..) => {
430                    bug!("NormalizesTo is only used by the new solver")
431                }
432                ty::PredicateKind::AliasRelate(..) => {
433                    bug!("AliasRelate is only used by the new solver")
434                }
435                ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => {
436                   unreachable!("unexpected higher ranked `UnstableFeature` goal")
437                }
438            },
439            Some(pred) => match pred {
440                ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
441                    let trait_obligation = obligation.with(infcx.tcx, Binder::dummy(data));
442
443                    self.process_trait_obligation(
444                        obligation,
445                        trait_obligation,
446                        &mut pending_obligation.stalled_on,
447                    )
448                }
449
450                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => {
451                    let host_obligation = obligation.with(infcx.tcx, data);
452
453                    self.process_host_obligation(
454                        obligation,
455                        host_obligation,
456                        &mut pending_obligation.stalled_on,
457                    )
458                }
459
460                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
461                    if infcx.considering_regions {
462                        infcx.register_region_outlives_constraint(data, &obligation.cause);
463                    }
464
465                    ProcessResult::Changed(Default::default())
466                }
467
468                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
469                    t_a,
470                    r_b,
471                ))) => {
472                    if infcx.considering_regions {
473                        infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause);
474                    }
475                    ProcessResult::Changed(Default::default())
476                }
477
478                ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => {
479                    let project_obligation = obligation.with(infcx.tcx, Binder::dummy(*data));
480
481                    self.process_projection_obligation(
482                        obligation,
483                        project_obligation,
484                        &mut pending_obligation.stalled_on,
485                    )
486                }
487
488                ty::PredicateKind::DynCompatible(trait_def_id) => {
489                    if !self.selcx.tcx().is_dyn_compatible(trait_def_id) {
490                        ProcessResult::Error(FulfillmentErrorCode::Select(
491                            SelectionError::Unimplemented,
492                        ))
493                    } else {
494                        ProcessResult::Changed(Default::default())
495                    }
496                }
497
498                ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
499                ty::PredicateKind::NormalizesTo(..) => {
500                    bug!("NormalizesTo is only used by the new solver")
501                }
502                ty::PredicateKind::AliasRelate(..) => {
503                    bug!("AliasRelate is only used by the new solver")
504                }
505                // Compute `ConstArgHasType` above the overflow check below.
506                // This is because this is not ever a useful obligation to report
507                // as the cause of an overflow.
508                ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
509                    let ct = infcx.shallow_resolve_const(ct);
510                    let ct_ty = match ct.kind() {
511                        ty::ConstKind::Infer(var) => {
512                            let var = match var {
513                                ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
514                                ty::InferConst::Fresh(_) => {
515                                    bug!("encountered fresh const in fulfill")
516                                }
517                            };
518                            pending_obligation.stalled_on.clear();
519                            pending_obligation.stalled_on.extend([var]);
520                            return ProcessResult::Unchanged;
521                        }
522                        ty::ConstKind::Error(_) => {
523                            return ProcessResult::Changed(PendingPredicateObligations::new());
524                        }
525                        ty::ConstKind::Value(cv) => cv.ty,
526                        ty::ConstKind::Unevaluated(uv) => {
527                            infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
528                        }
529                        // FIXME(generic_const_exprs): we should construct an alias like
530                        // `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
531                        // `lhs + rhs`.
532                        ty::ConstKind::Expr(_) => {
533                            return ProcessResult::Changed(mk_pending(
534                                obligation,
535                                PredicateObligations::new(),
536                            ));
537                        }
538                        ty::ConstKind::Placeholder(_) => {
539                            bug!("placeholder const {:?} in old solver", ct)
540                        }
541                        ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
542                        ty::ConstKind::Param(param_ct) => {
543                            param_ct.find_const_ty_from_env(obligation.param_env)
544                        }
545                    };
546
547                    match infcx.at(&obligation.cause, obligation.param_env).eq(
548                        // Only really exercised by generic_const_exprs
549                        DefineOpaqueTypes::Yes,
550                        ct_ty,
551                        ty,
552                    ) {
553                        Ok(inf_ok) => ProcessResult::Changed(mk_pending(
554                            obligation,
555                            inf_ok.into_obligations(),
556                        )),
557                        Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
558                            SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
559                        )),
560                    }
561                }
562
563                // General case overflow check. Allow `process_trait_obligation`
564                // and `process_projection_obligation` to handle checking for
565                // the recursion limit themselves. Also don't check some
566                // predicate kinds that don't give further obligations.
567                _ if !self
568                    .selcx
569                    .tcx()
570                    .recursion_limit()
571                    .value_within_limit(obligation.recursion_depth) =>
572                {
573                    self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false);
574                }
575
576                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
577                    if term.is_trivially_wf(self.selcx.tcx()) {
578                        return ProcessResult::Changed(thin_vec![]);
579                    }
580
581                    match wf::obligations(
582                        self.selcx.infcx,
583                        obligation.param_env,
584                        obligation.cause.body_id,
585                        obligation.recursion_depth + 1,
586                        term,
587                        obligation.cause.span,
588                    ) {
589                        None => {
590                            pending_obligation.stalled_on =
591                                vec![TyOrConstInferVar::maybe_from_term(term).unwrap()];
592                            ProcessResult::Unchanged
593                        }
594                        Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
595                    }
596                }
597
598                ty::PredicateKind::Subtype(subtype) => {
599                    match self.selcx.infcx.subtype_predicate(
600                        &obligation.cause,
601                        obligation.param_env,
602                        Binder::dummy(subtype),
603                    ) {
604                        Err((a, b)) => {
605                            // None means that both are unresolved.
606                            pending_obligation.stalled_on =
607                                vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
608                            ProcessResult::Unchanged
609                        }
610                        Ok(Ok(ok)) => {
611                            ProcessResult::Changed(mk_pending(obligation, ok.obligations))
612                        }
613                        Ok(Err(err)) => {
614                            let expected_found = if subtype.a_is_expected {
615                                ExpectedFound::new(subtype.a, subtype.b)
616                            } else {
617                                ExpectedFound::new(subtype.b, subtype.a)
618                            };
619                            ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
620                        }
621                    }
622                }
623
624                ty::PredicateKind::Coerce(coerce) => {
625                    match self.selcx.infcx.coerce_predicate(
626                        &obligation.cause,
627                        obligation.param_env,
628                        Binder::dummy(coerce),
629                    ) {
630                        Err((a, b)) => {
631                            // None means that both are unresolved.
632                            pending_obligation.stalled_on =
633                                vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
634                            ProcessResult::Unchanged
635                        }
636                        Ok(Ok(ok)) => {
637                            ProcessResult::Changed(mk_pending(obligation, ok.obligations))
638                        }
639                        Ok(Err(err)) => {
640                            let expected_found = ExpectedFound::new(coerce.b, coerce.a);
641                            ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
642                        }
643                    }
644                }
645
646                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
647                    match const_evaluatable::is_const_evaluatable(
648                        self.selcx.infcx,
649                        uv,
650                        obligation.param_env,
651                        obligation.cause.span,
652                    ) {
653                        Ok(()) => ProcessResult::Changed(Default::default()),
654                        Err(NotConstEvaluatable::MentionsInfer) => {
655                            pending_obligation.stalled_on.clear();
656                            pending_obligation.stalled_on.extend(
657                                uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
658                            );
659                            ProcessResult::Unchanged
660                        }
661                        Err(
662                            e @ NotConstEvaluatable::MentionsParam
663                            | e @ NotConstEvaluatable::Error(_),
664                        ) => ProcessResult::Error(FulfillmentErrorCode::Select(
665                            SelectionError::NotConstEvaluatable(e),
666                        )),
667                    }
668                }
669
670                ty::PredicateKind::ConstEquate(c1, c2) => {
671                    let tcx = self.selcx.tcx();
672                    assert!(
673                        tcx.features().generic_const_exprs(),
674                        "`ConstEquate` without a feature gate: {c1:?} {c2:?}",
675                    );
676                    // FIXME: we probably should only try to unify abstract constants
677                    // if the constants depend on generic parameters.
678                    //
679                    // Let's just see where this breaks :shrug:
680                    {
681                        let c1 = tcx.expand_abstract_consts(c1);
682                        let c2 = tcx.expand_abstract_consts(c2);
683                        debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
684
685                        use rustc_hir::def::DefKind;
686                        match (c1.kind(), c2.kind()) {
687                            (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
688                                if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
689                            {
690                                if let Ok(new_obligations) = infcx
691                                    .at(&obligation.cause, obligation.param_env)
692                                    // Can define opaque types as this is only reachable with
693                                    // `generic_const_exprs`
694                                    .eq(
695                                        DefineOpaqueTypes::Yes,
696                                        ty::AliasTerm::from(a),
697                                        ty::AliasTerm::from(b),
698                                    )
699                                {
700                                    return ProcessResult::Changed(mk_pending(
701                                        obligation,
702                                        new_obligations.into_obligations(),
703                                    ));
704                                }
705                            }
706                            (_, ty::ConstKind::Unevaluated(_))
707                            | (ty::ConstKind::Unevaluated(_), _) => (),
708                            (_, _) => {
709                                if let Ok(new_obligations) = infcx
710                                    .at(&obligation.cause, obligation.param_env)
711                                    // Can define opaque types as this is only reachable with
712                                    // `generic_const_exprs`
713                                    .eq(DefineOpaqueTypes::Yes, c1, c2)
714                                {
715                                    return ProcessResult::Changed(mk_pending(
716                                        obligation,
717                                        new_obligations.into_obligations(),
718                                    ));
719                                }
720                            }
721                        }
722                    }
723
724                    let stalled_on = &mut pending_obligation.stalled_on;
725
726                    let mut evaluate = |c: Const<'tcx>| {
727                        if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
728                            match super::try_evaluate_const(
729                                self.selcx.infcx,
730                                c,
731                                obligation.param_env,
732                            ) {
733                                Ok(val) => Ok(val),
734                                e @ Err(EvaluateConstErr::HasGenericsOrInfers) => {
735                                    stalled_on.extend(
736                                        unevaluated
737                                            .args
738                                            .iter()
739                                            .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
740                                    );
741                                    e
742                                }
743                                e @ Err(
744                                    EvaluateConstErr::EvaluationFailure(_)
745                                    | EvaluateConstErr::InvalidConstParamTy(_),
746                                ) => e,
747                            }
748                        } else {
749                            Ok(c)
750                        }
751                    };
752
753                    match (evaluate(c1), evaluate(c2)) {
754                        (Ok(c1), Ok(c2)) => {
755                            match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
756                                // Can define opaque types as this is only reachable with
757                                // `generic_const_exprs`
758                                DefineOpaqueTypes::Yes,
759                                c1,
760                                c2,
761                            ) {
762                                Ok(inf_ok) => ProcessResult::Changed(mk_pending(
763                                    obligation,
764                                    inf_ok.into_obligations(),
765                                )),
766                                Err(err) => {
767                                    ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
768                                        ExpectedFound::new(c1, c2),
769                                        err,
770                                    ))
771                                }
772                            }
773                        }
774                        (Err(EvaluateConstErr::InvalidConstParamTy(e)), _)
775                        | (_, Err(EvaluateConstErr::InvalidConstParamTy(e))) => {
776                            ProcessResult::Error(FulfillmentErrorCode::Select(
777                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e)),
778                            ))
779                        }
780                        (Err(EvaluateConstErr::EvaluationFailure(e)), _)
781                        | (_, Err(EvaluateConstErr::EvaluationFailure(e))) => {
782                            ProcessResult::Error(FulfillmentErrorCode::Select(
783                                SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e)),
784                            ))
785                        }
786                        (Err(EvaluateConstErr::HasGenericsOrInfers), _)
787                        | (_, Err(EvaluateConstErr::HasGenericsOrInfers)) => {
788                            if c1.has_non_region_infer() || c2.has_non_region_infer() {
789                                ProcessResult::Unchanged
790                            } else {
791                                // Two different constants using generic parameters ~> error.
792                                let expected_found = ExpectedFound::new(c1, c2);
793                                ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
794                                    expected_found,
795                                    TypeError::ConstMismatch(expected_found),
796                                ))
797                            }
798                        }
799                    }
800                }
801                ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
802                    if may_use_unstable_feature(self.selcx.infcx, obligation.param_env, symbol) {
803                        ProcessResult::Changed(Default::default())
804                    } else {
805                        ProcessResult::Unchanged
806                    }
807                }
808            },
809        }
810    }
811
812    #[inline(never)]
813    fn process_backedge<'c, I>(
814        &mut self,
815        cycle: I,
816        _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
817    ) -> Result<(), FulfillmentErrorCode<'tcx>>
818    where
819        I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
820    {
821        if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
822            debug!("process_child_obligations: coinductive match");
823            Ok(())
824        } else {
825            let cycle = cycle.map(|c| c.obligation.clone()).collect();
826            Err(FulfillmentErrorCode::Cycle(cycle))
827        }
828    }
829}
830
831impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
832    #[instrument(level = "debug", skip(self, obligation, stalled_on))]
833    fn process_trait_obligation(
834        &mut self,
835        obligation: &PredicateObligation<'tcx>,
836        trait_obligation: PolyTraitObligation<'tcx>,
837        stalled_on: &mut Vec<TyOrConstInferVar>,
838    ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
839        let infcx = self.selcx.infcx;
840        if obligation.predicate.is_global() && !matches!(infcx.typing_mode(), TypingMode::Coherence)
841        {
842            // no type variables present, can use evaluation for better caching.
843            // FIXME: consider caching errors too.
844            if infcx.predicate_must_hold_considering_regions(obligation) {
845                debug!(
846                    "selecting trait at depth {} evaluated to holds",
847                    obligation.recursion_depth
848                );
849                return ProcessResult::Changed(Default::default());
850            }
851        }
852
853        match self.selcx.poly_select(&trait_obligation) {
854            Ok(Some(impl_source)) => {
855                debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
856                ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations()))
857            }
858            Ok(None) => {
859                debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth);
860
861                // This is a bit subtle: for the most part, the
862                // only reason we can fail to make progress on
863                // trait selection is because we don't have enough
864                // information about the types in the trait.
865                stalled_on.clear();
866                stalled_on.extend(args_infer_vars(
867                    &self.selcx,
868                    trait_obligation.predicate.map_bound(|pred| pred.trait_ref.args),
869                ));
870
871                debug!(
872                    "process_predicate: pending obligation {:?} now stalled on {:?}",
873                    infcx.resolve_vars_if_possible(obligation.clone()),
874                    stalled_on
875                );
876
877                ProcessResult::Unchanged
878            }
879            Err(selection_err) => {
880                debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth);
881
882                ProcessResult::Error(FulfillmentErrorCode::Select(selection_err))
883            }
884        }
885    }
886
887    fn process_projection_obligation(
888        &mut self,
889        obligation: &PredicateObligation<'tcx>,
890        project_obligation: PolyProjectionObligation<'tcx>,
891        stalled_on: &mut Vec<TyOrConstInferVar>,
892    ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
893        let tcx = self.selcx.tcx();
894        let infcx = self.selcx.infcx;
895        if obligation.predicate.is_global() && !matches!(infcx.typing_mode(), TypingMode::Coherence)
896        {
897            // no type variables present, can use evaluation for better caching.
898            // FIXME: consider caching errors too.
899            if infcx.predicate_must_hold_considering_regions(obligation) {
900                if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
901                    &mut self.selcx,
902                    &project_obligation,
903                ) {
904                    // If `predicate_must_hold_considering_regions` succeeds, then we've
905                    // evaluated all sub-obligations. We can therefore mark the 'root'
906                    // obligation as complete, and skip evaluating sub-obligations.
907                    infcx
908                        .inner
909                        .borrow_mut()
910                        .projection_cache()
911                        .complete(key, EvaluationResult::EvaluatedToOk);
912                }
913                return ProcessResult::Changed(Default::default());
914            } else {
915                debug!("Does NOT hold: {:?}", obligation);
916            }
917        }
918
919        match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
920            ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)),
921            ProjectAndUnifyResult::FailedNormalization => {
922                stalled_on.clear();
923                stalled_on.extend(args_infer_vars(
924                    &self.selcx,
925                    project_obligation.predicate.map_bound(|pred| pred.projection_term.args),
926                ));
927                ProcessResult::Unchanged
928            }
929            // Let the caller handle the recursion
930            ProjectAndUnifyResult::Recursive => {
931                let mut obligations = PredicateObligations::with_capacity(1);
932                obligations.push(project_obligation.with(tcx, project_obligation.predicate));
933
934                ProcessResult::Changed(mk_pending(obligation, obligations))
935            }
936            ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
937                ProcessResult::Error(FulfillmentErrorCode::Project(e))
938            }
939        }
940    }
941
942    fn process_host_obligation(
943        &mut self,
944        obligation: &PredicateObligation<'tcx>,
945        host_obligation: HostEffectObligation<'tcx>,
946        stalled_on: &mut Vec<TyOrConstInferVar>,
947    ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
948        match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
949            Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)),
950            Err(effects::EvaluationFailure::Ambiguous) => {
951                stalled_on.clear();
952                stalled_on.extend(args_infer_vars(
953                    &self.selcx,
954                    ty::Binder::dummy(host_obligation.predicate.trait_ref.args),
955                ));
956                ProcessResult::Unchanged
957            }
958            Err(effects::EvaluationFailure::NoSolution) => {
959                ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::Unimplemented))
960            }
961        }
962    }
963}
964
965/// Returns the set of inference variables contained in `args`.
966fn args_infer_vars<'tcx>(
967    selcx: &SelectionContext<'_, 'tcx>,
968    args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
969) -> impl Iterator<Item = TyOrConstInferVar> {
970    selcx
971        .infcx
972        .resolve_vars_if_possible(args)
973        .skip_binder() // ok because this check doesn't care about regions
974        .iter()
975        .filter(|arg| arg.has_non_region_infer())
976        .flat_map(|arg| {
977            let mut walker = arg.walk();
978            while let Some(c) = walker.next() {
979                if !c.has_non_region_infer() {
980                    walker.visited.remove(&c);
981                    walker.skip_current_subtree();
982                }
983            }
984            walker.visited.into_iter()
985        })
986        .filter_map(TyOrConstInferVar::maybe_from_generic_arg)
987}
988
989#[derive(Debug)]
990pub struct OldSolverError<'tcx>(
991    Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
992);
993
994impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
995    fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
996        let mut iter = error.0.backtrace.into_iter();
997        let obligation = iter.next().unwrap().obligation;
998        // The root obligation is the last item in the backtrace - if there's only
999        // one item, then it's the same as the main obligation
1000        let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
1001        FulfillmentError::new(obligation, error.0.error, root_obligation)
1002    }
1003}
1004
1005impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
1006    fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
1007        match error.0.error {
1008            FulfillmentErrorCode::Select(_)
1009            | FulfillmentErrorCode::Project(_)
1010            | FulfillmentErrorCode::Subtype(_, _)
1011            | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError,
1012            FulfillmentErrorCode::Ambiguity { overflow: _ } => ScrubbedTraitError::Ambiguity,
1013            FulfillmentErrorCode::Cycle(cycle) => ScrubbedTraitError::Cycle(cycle),
1014        }
1015    }
1016}