compiler/rustc_trait_selection/src/traits/select/mod.rs RUST 3,234 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,234.
1//! Candidate selection. See the [rustc dev guide] for more information on how this works.2//!3//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection45use std::cell::{Cell, RefCell};6use std::cmp;7use std::fmt::{self, Display};8use std::ops::ControlFlow;910use hir::def::DefKind;11use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};12use rustc_data_structures::stack::ensure_sufficient_stack;13use rustc_errors::{Diag, EmissionGuarantee};14use rustc_hir::def_id::DefId;15use rustc_hir::{self as hir, LangItem, find_attr};16use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType};17use rustc_infer::infer::DefineOpaqueTypes;18use rustc_infer::infer::at::ToTrace;19use rustc_infer::infer::relate::TypeRelation;20use rustc_infer::traits::{PredicateObligations, TraitObligation};21use rustc_macros::{TypeFoldable, TypeVisitable};22use rustc_middle::bug;23use rustc_middle::dep_graph::{DepKind, DepNodeIndex};24pub use rustc_middle::traits::select::*;25use rustc_middle::ty::abstract_const::NotConstEvaluatable;26use rustc_middle::ty::error::TypeErrorToStringExt;27use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};28use rustc_middle::ty::{29    self, CandidatePreferenceMode, CantBeErased, DeepRejectCtxt, GenericArgsRef,30    PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,31    TypingMode, Unnormalized, Upcast, elaborate, may_use_unstable_feature,32};33use rustc_next_trait_solver::solve::AliasBoundKind;34use rustc_span::Symbol;35use tracing::{debug, instrument, trace};3637use self::EvaluationResult::*;38use self::SelectionCandidate::*;39use super::coherence::{self, Conflict};40use super::project::ProjectionTermObligation;41use super::util::closure_trait_ref_and_return_type;42use super::{43    ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode,44    PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult,45    TraitQueryMode, const_evaluatable, project, util, wf,46};47use crate::error_reporting::InferCtxtErrorExt;48use crate::infer::{InferCtxt, InferOk, TypeFreshener};49use crate::solve::InferCtxtSelectExt as _;50use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};51use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};52use crate::traits::{EvaluateConstErr, ProjectionCacheKey, effects, sizedness_fast_path};5354mod _match;55mod candidate_assembly;56mod confirmation;5758#[derive(Clone, Debug, Eq, PartialEq, Hash)]59pub enum IntercrateAmbiguityCause<'tcx> {60    DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },61    UpstreamCrateUpdate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> },62    ReservationImpl { message: Symbol },63}6465impl<'tcx> IntercrateAmbiguityCause<'tcx> {66    /// Emits notes when the overlap is caused by complex intercrate ambiguities.67    /// See #23980 for details.68    pub fn add_intercrate_ambiguity_hint<G: EmissionGuarantee>(&self, err: &mut Diag<'_, G>) {69        err.note(self.intercrate_ambiguity_hint());70    }7172    pub fn intercrate_ambiguity_hint(&self) -> String {73        with_no_trimmed_paths!(match self {74            IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } => {75                format!(76                    "downstream crates may implement trait `{trait_desc}`{self_desc}",77                    trait_desc = trait_ref.print_trait_sugared(),78                    self_desc = if let Some(self_ty) = self_ty {79                        format!(" for type `{self_ty}`")80                    } else {81                        String::new()82                    }83                )84            }85            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } => {86                format!(87                    "upstream crates may add a new impl of trait `{trait_desc}`{self_desc} \88                in future versions",89                    trait_desc = trait_ref.print_trait_sugared(),90                    self_desc = if let Some(self_ty) = self_ty {91                        format!(" for type `{self_ty}`")92                    } else {93                        String::new()94                    }95                )96            }97            IntercrateAmbiguityCause::ReservationImpl { message } => message.to_string(),98        })99    }100}101102pub struct SelectionContext<'cx, 'tcx> {103    pub infcx: &'cx InferCtxt<'tcx>,104105    /// Freshener used specifically for entries on the obligation106    /// stack. This ensures that all entries on the stack at one time107    /// will have the same set of placeholder entries, which is108    /// important for checking for trait bounds that recursively109    /// require themselves.110    freshener: TypeFreshener<'cx, 'tcx>,111112    /// If `intercrate` is set, we remember predicates which were113    /// considered ambiguous because of impls potentially added in other crates.114    /// This is used in coherence to give improved diagnostics.115    /// We don't do his until we detect a coherence error because it can116    /// lead to false overflow results (#47139) and because always117    /// computing it may negatively impact performance.118    intercrate_ambiguity_causes: Option<FxIndexSet<IntercrateAmbiguityCause<'tcx>>>,119120    /// The mode that trait queries run in, which informs our error handling121    /// policy. In essence, canonicalized queries need their errors propagated122    /// rather than immediately reported because we do not have accurate spans.123    query_mode: TraitQueryMode,124}125126// A stack that walks back up the stack frame.127struct TraitObligationStack<'prev, 'tcx> {128    obligation: &'prev PolyTraitObligation<'tcx>,129130    /// The trait predicate from `obligation` but "freshened" with the131    /// selection-context's freshener. Used to check for recursion.132    fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,133134    /// Starts out equal to `depth` -- if, during evaluation, we135    /// encounter a cycle, then we will set this flag to the minimum136    /// depth of that cycle for all participants in the cycle. These137    /// participants will then forego caching their results. This is138    /// not the most efficient solution, but it addresses #60010. The139    /// problem we are trying to prevent:140    ///141    /// - If you have `A: AutoTrait` requires `B: AutoTrait` and `C: NonAutoTrait`142    /// - `B: AutoTrait` requires `A: AutoTrait` (coinductive cycle, ok)143    /// - `C: NonAutoTrait` requires `A: AutoTrait` (non-coinductive cycle, not ok)144    ///145    /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`146    /// is `EvaluatedToOk`; this is because they were only considered147    /// ok on the premise that if `A: AutoTrait` held, but we indeed148    /// encountered a problem (later on) with `A: AutoTrait`. So we149    /// currently set a flag on the stack node for `B: AutoTrait` (as150    /// well as the second instance of `A: AutoTrait`) to suppress151    /// caching.152    ///153    /// This is a simple, targeted fix. A more-performant fix requires154    /// deeper changes, but would permit more caching: we could155    /// basically defer caching until we have fully evaluated the156    /// tree, and then cache the entire tree at once. In any case, the157    /// performance impact here shouldn't be so horrible: every time158    /// this is hit, we do cache at least one trait, so we only159    /// evaluate each member of a cycle up to N times, where N is the160    /// length of the cycle. This means the performance impact is161    /// bounded and we shouldn't have any terrible worst-cases.162    reached_depth: Cell<usize>,163164    previous: TraitObligationStackList<'prev, 'tcx>,165166    /// The number of parent frames plus one (thus, the topmost frame has depth 1).167    depth: usize,168169    /// The depth-first number of this node in the search graph -- a170    /// pre-order index. Basically, a freshly incremented counter.171    dfn: usize,172}173174struct SelectionCandidateSet<'tcx> {175    /// A list of candidates that definitely apply to the current176    /// obligation (meaning: types unify).177    vec: Vec<SelectionCandidate<'tcx>>,178179    /// If `true`, then there were candidates that might or might180    /// not have applied, but we couldn't tell. This occurs when some181    /// of the input types are type variables, in which case there are182    /// various "builtin" rules that might or might not trigger.183    ambiguous: bool,184}185186#[derive(PartialEq, Eq, Debug, Clone)]187struct EvaluatedCandidate<'tcx> {188    candidate: SelectionCandidate<'tcx>,189    evaluation: EvaluationResult,190}191192impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {193    pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {194        SelectionContext {195            infcx,196            freshener: TypeFreshener::new(infcx),197            intercrate_ambiguity_causes: None,198            query_mode: TraitQueryMode::Standard,199        }200    }201202    pub fn typing_mode(&self) -> TypingMode<'tcx, CantBeErased> {203        self.infcx.typing_mode_raw().assert_not_erased()204    }205206    pub fn with_query_mode(207        infcx: &'cx InferCtxt<'tcx>,208        query_mode: TraitQueryMode,209    ) -> SelectionContext<'cx, 'tcx> {210        debug!(?query_mode, "with_query_mode");211        SelectionContext { query_mode, ..SelectionContext::new(infcx) }212    }213214    /// Enables tracking of intercrate ambiguity causes. See215    /// the documentation of [`Self::intercrate_ambiguity_causes`] for more.216    pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {217        assert!(self.typing_mode().is_coherence());218        assert!(self.intercrate_ambiguity_causes.is_none());219220        self.intercrate_ambiguity_causes = Some(FxIndexSet::default());221        debug!("selcx: enable_tracking_intercrate_ambiguity_causes");222    }223224    /// Gets the intercrate ambiguity causes collected since tracking225    /// was enabled and disables tracking at the same time. If226    /// tracking is not enabled, just returns an empty vector.227    pub fn take_intercrate_ambiguity_causes(228        &mut self,229    ) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {230        assert!(self.typing_mode().is_coherence());231232        self.intercrate_ambiguity_causes.take().unwrap_or_default()233    }234235    pub fn tcx(&self) -> TyCtxt<'tcx> {236        self.infcx.tcx237    }238239    ///////////////////////////////////////////////////////////////////////////240    // Selection241    //242    // The selection phase tries to identify *how* an obligation will243    // be resolved. For example, it will identify which impl or244    // parameter bound is to be used. The process can be inconclusive245    // if the self type in the obligation is not fully inferred. Selection246    // can result in an error in one of two ways:247    //248    // 1. If no applicable impl or parameter bound can be found.249    // 2. If the output type parameters in the obligation do not match250    //    those specified by the impl/bound. For example, if the obligation251    //    is `Vec<Foo>: Iterable<Bar>`, but the impl specifies252    //    `impl<T> Iterable<T> for Vec<T>`, than an error would result.253254    /// Attempts to satisfy the obligation. If successful, this will affect the surrounding255    /// type environment by performing unification.256    #[instrument(level = "debug", skip(self), ret)]257    pub fn poly_select(258        &mut self,259        obligation: &PolyTraitObligation<'tcx>,260    ) -> SelectionResult<'tcx, Selection<'tcx>> {261        assert!(!self.infcx.next_trait_solver());262263        let candidate = match self.select_from_obligation(obligation) {264            Err(SelectionError::Overflow(OverflowError::Canonical)) => {265                // In standard mode, overflow must have been caught and reported266                // earlier.267                assert!(self.query_mode == TraitQueryMode::Canonical);268                return Err(SelectionError::Overflow(OverflowError::Canonical));269            }270            Err(e) => {271                return Err(e);272            }273            Ok(None) => {274                return Ok(None);275            }276            Ok(Some(candidate)) => candidate,277        };278279        match self.confirm_candidate(obligation, candidate) {280            Err(SelectionError::Overflow(OverflowError::Canonical)) => {281                assert!(self.query_mode == TraitQueryMode::Canonical);282                Err(SelectionError::Overflow(OverflowError::Canonical))283            }284            Err(e) => Err(e),285            Ok(candidate) => Ok(Some(candidate)),286        }287    }288289    pub fn select(290        &mut self,291        obligation: &TraitObligation<'tcx>,292    ) -> SelectionResult<'tcx, Selection<'tcx>> {293        if self.infcx.next_trait_solver() {294            return self.infcx.select_in_new_trait_solver(obligation);295        }296297        self.poly_select(&Obligation {298            cause: obligation.cause.clone(),299            param_env: obligation.param_env,300            predicate: ty::Binder::dummy(obligation.predicate),301            recursion_depth: obligation.recursion_depth,302        })303    }304305    fn select_from_obligation(306        &mut self,307        obligation: &PolyTraitObligation<'tcx>,308    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {309        debug_assert!(!obligation.predicate.has_escaping_bound_vars());310311        let pec = &ProvisionalEvaluationCache::default();312        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);313314        self.candidate_from_obligation(&stack)315    }316317    #[instrument(level = "debug", skip(self), ret)]318    fn candidate_from_obligation<'o>(319        &mut self,320        stack: &TraitObligationStack<'o, 'tcx>,321    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {322        debug_assert!(!self.infcx.next_trait_solver());323        // Watch out for overflow. This intentionally bypasses (and does324        // not update) the cache.325        self.check_recursion_limit(stack.obligation, stack.obligation)?;326327        // Check the cache. Note that we freshen the trait-ref328        // separately rather than using `stack.fresh_trait_pred` --329        // this is because we want the unbound variables to be330        // replaced with fresh types starting from index 0.331        let cache_fresh_trait_pred =332            stack.obligation.predicate.fold_with(&mut TypeFreshener::new(self.infcx));333        debug!(?cache_fresh_trait_pred);334        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());335336        if let Some(c) =337            self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred)338        {339            debug!("CACHE HIT");340            return c;341        }342343        // If no match, compute result and insert into cache.344        //345        // FIXME(nikomatsakis) -- this cache is not taking into346        // account cycles that may have occurred in forming the347        // candidate. I don't know of any specific problems that348        // result but it seems awfully suspicious.349        let (candidate, dep_node) =350            self.in_task(|this| this.candidate_from_obligation_no_cache(stack));351352        debug!("CACHE MISS");353        self.insert_candidate_cache(354            stack.obligation.param_env,355            cache_fresh_trait_pred,356            dep_node,357            candidate.clone(),358        );359        candidate360    }361362    fn candidate_from_obligation_no_cache<'o>(363        &mut self,364        stack: &TraitObligationStack<'o, 'tcx>,365    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {366        if let Err(conflict) = self.is_knowable(stack) {367            debug!("coherence stage: not knowable");368            if self.intercrate_ambiguity_causes.is_some() {369                debug!("evaluate_stack: intercrate_ambiguity_causes is some");370                // Heuristics: show the diagnostics when there are no candidates in crate.371                if let Ok(candidate_set) = self.assemble_candidates(stack) {372                    let mut no_candidates_apply = true;373374                    for c in candidate_set.vec.iter() {375                        if self.evaluate_candidate(stack, c)?.may_apply() {376                            no_candidates_apply = false;377                            break;378                        }379                    }380381                    if !candidate_set.ambiguous && no_candidates_apply {382                        let trait_ref = self.infcx.resolve_vars_if_possible(383                            stack.obligation.predicate.skip_binder().trait_ref,384                        );385                        if !trait_ref.references_error() {386                            let self_ty = trait_ref.self_ty();387                            let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);388                            let cause = if let Conflict::Upstream = conflict {389                                IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty }390                            } else {391                                IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty }392                            };393                            debug!(?cause, "evaluate_stack: pushing cause");394                            self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);395                        }396                    }397                }398            }399            return Ok(None);400        }401402        let candidate_set = self.assemble_candidates(stack)?;403404        if candidate_set.ambiguous {405            debug!("candidate set contains ambig");406            return Ok(None);407        }408409        let candidates = candidate_set.vec;410411        debug!(?stack, ?candidates, "assembled {} candidates", candidates.len());412413        // At this point, we know that each of the entries in the414        // candidate set is *individually* applicable. Now we have to415        // figure out if they contain mutual incompatibilities. This416        // frequently arises if we have an unconstrained input type --417        // for example, we are looking for `$0: Eq` where `$0` is some418        // unconstrained type variable. In that case, we'll get a419        // candidate which assumes $0 == int, one that assumes `$0 ==420        // usize`, etc. This spells an ambiguity.421422        let mut candidates = self.filter_impls(candidates, stack.obligation);423424        // If there is more than one candidate, first winnow them down425        // by considering extra conditions (nested obligations and so426        // forth). We don't winnow if there is exactly one427        // candidate. This is a relatively minor distinction but it428        // can lead to better inference and error-reporting. An429        // example would be if there was an impl:430        //431        //     impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }432        //433        // and we were to see some code `foo.push_clone()` where `boo`434        // is a `Vec<Bar>` and `Bar` does not implement `Clone`. If435        // we were to winnow, we'd wind up with zero candidates.436        // Instead, we select the right impl now but report "`Bar` does437        // not implement `Clone`".438        if candidates.len() == 1 {439            return self.filter_reservation_impls(candidates.pop().unwrap());440        }441442        // Winnow, but record the exact outcome of evaluation, which443        // is needed for specialization. Propagate overflow if it occurs.444        let candidates = candidates445            .into_iter()446            .map(|c| match self.evaluate_candidate(stack, &c) {447                Ok(eval) if eval.may_apply() => {448                    Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval }))449                }450                Ok(_) => Ok(None),451                Err(OverflowError::Canonical) => {452                    Err(SelectionError::Overflow(OverflowError::Canonical))453                }454                Err(OverflowError::Error(e)) => {455                    Err(SelectionError::Overflow(OverflowError::Error(e)))456                }457            })458            .flat_map(Result::transpose)459            .collect::<Result<Vec<_>, _>>()?;460461        debug!(?stack, ?candidates, "{} potentially applicable candidates", candidates.len());462        // If there are *NO* candidates, then there are no impls --463        // that we know of, anyway. Note that in the case where there464        // are unbound type variables within the obligation, it might465        // be the case that you could still satisfy the obligation466        // from another crate by instantiating the type variables with467        // a type from another crate that does have an impl. This case468        // is checked for in `evaluate_stack` (and hence users469        // who might care about this case, like coherence, should use470        // that function).471        if candidates.is_empty() {472            // If there's an error type, 'downgrade' our result from473            // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid474            // emitting additional spurious errors, since we're guaranteed475            // to have emitted at least one.476            if stack.obligation.predicate.references_error() {477                debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous");478                Ok(None)479            } else {480                Err(SelectionError::Unimplemented)481            }482        } else {483            let has_non_region_infer = stack.obligation.predicate.has_non_region_infer();484            let candidate_preference_mode =485                CandidatePreferenceMode::compute(self.tcx(), stack.obligation.predicate.def_id());486            if let Some(candidate) =487                self.winnow_candidates(has_non_region_infer, candidate_preference_mode, candidates)488            {489                self.filter_reservation_impls(candidate)490            } else {491                Ok(None)492            }493        }494    }495496    ///////////////////////////////////////////////////////////////////////////497    // EVALUATION498    //499    // Tests whether an obligation can be selected or whether an impl500    // can be applied to particular types. It skips the "confirmation"501    // step and hence completely ignores output type parameters.502    //503    // The result is "true" if the obligation *may* hold and "false" if504    // we can be sure it does not.505506    /// Evaluates whether the obligation `obligation` can be satisfied507    /// and returns an `EvaluationResult`. This is meant for the508    /// *initial* call.509    ///510    /// Do not use this directly, use `infcx.evaluate_obligation` instead.511    pub fn evaluate_root_obligation(512        &mut self,513        obligation: &PredicateObligation<'tcx>,514    ) -> Result<EvaluationResult, OverflowError> {515        debug_assert!(!self.infcx.next_trait_solver());516        self.evaluation_probe(|this| {517            let goal =518                this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));519            let mut result = this.evaluate_predicate_recursively(520                TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),521                obligation.clone(),522            )?;523            // If the predicate has done any inference, then downgrade the524            // result to ambiguous.525            if this.infcx.resolve_vars_if_possible(goal) != goal {526                result = result.max(EvaluatedToAmbig);527            }528            Ok(result)529        })530    }531532    /// Computes the evaluation result of `op`, discarding any constraints.533    ///534    /// This also runs for leak check to allow higher ranked region errors to impact535    /// selection. By default it checks for leaks from all universes created inside of536    /// `op`, but this can be overwritten if necessary.537    fn evaluation_probe(538        &mut self,539        op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,540    ) -> Result<EvaluationResult, OverflowError> {541        self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {542            let outer_universe = self.infcx.universe();543            let result = op(self)?;544545            match self.infcx.leak_check(outer_universe, Some(snapshot)) {546                Ok(()) => {}547                Err(_) => return Ok(EvaluatedToErr),548            }549550            if self.infcx.opaque_types_added_in_snapshot(snapshot) {551                return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));552            }553554            if self.infcx.region_constraints_added_in_snapshot(snapshot) {555                Ok(result.max(EvaluatedToOkModuloRegions))556            } else {557                Ok(result)558            }559        })560    }561562    /// Evaluates the predicates in `predicates` recursively. This may563    /// guide inference. If this is not desired, run it inside of a564    /// is run within an inference probe.565    /// `probe`.566    #[instrument(skip(self, stack), level = "debug")]567    fn evaluate_predicates_recursively<'o, I>(568        &mut self,569        stack: TraitObligationStackList<'o, 'tcx>,570        predicates: I,571    ) -> Result<EvaluationResult, OverflowError>572    where573        I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,574    {575        let mut result = EvaluatedToOk;576        for mut obligation in predicates {577            obligation.set_depth_from_parent(stack.depth());578            let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;579            if let EvaluatedToErr = eval {580                // fast-path - EvaluatedToErr is the top of the lattice,581                // so we don't need to look on the other predicates.582                return Ok(EvaluatedToErr);583            } else {584                result = cmp::max(result, eval);585            }586        }587        Ok(result)588    }589590    #[instrument(591        level = "debug",592        skip(self, previous_stack),593        fields(previous_stack = ?previous_stack.head())594        ret,595    )]596    fn evaluate_predicate_recursively<'o>(597        &mut self,598        previous_stack: TraitObligationStackList<'o, 'tcx>,599        obligation: PredicateObligation<'tcx>,600    ) -> Result<EvaluationResult, OverflowError> {601        debug_assert!(!self.infcx.next_trait_solver());602        // `previous_stack` stores a `PolyTraitObligation`, while `obligation` is603        // a `PredicateObligation`. These are distinct types, so we can't604        // use any `Option` combinator method that would force them to be605        // the same.606        match previous_stack.head() {607            Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,608            None => self.check_recursion_limit(&obligation, &obligation)?,609        }610611        if !self.infcx.disable_trait_solver_fast_paths()612            && sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env)613        {614            return Ok(EvaluatedToOk);615        }616617        ensure_sufficient_stack(|| {618            let bound_predicate = obligation.predicate.kind();619            match bound_predicate.skip_binder() {620                ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {621                    let t = bound_predicate.rebind(t);622                    debug_assert!(!t.has_escaping_bound_vars());623                    let obligation = obligation.with(self.tcx(), t);624                    self.evaluate_trait_predicate_recursively(previous_stack, obligation)625                }626627                ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => {628                    self.infcx.enter_forall(bound_predicate.rebind(data), |data| {629                        match effects::evaluate_host_effect_obligation(630                            self,631                            &obligation.with(self.tcx(), data),632                        ) {633                            Ok(nested) => {634                                self.evaluate_predicates_recursively(previous_stack, nested)635                            }636                            Err(effects::EvaluationFailure::Ambiguous) => Ok(EvaluatedToAmbig),637                            Err(effects::EvaluationFailure::NoSolution) => Ok(EvaluatedToErr),638                        }639                    })640                }641642                ty::PredicateKind::Subtype(p) => {643                    let p = bound_predicate.rebind(p);644                    // Does this code ever run?645                    match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {646                        Ok(Ok(InferOk { obligations, .. })) => {647                            self.evaluate_predicates_recursively(previous_stack, obligations)648                        }649                        Ok(Err(_)) => Ok(EvaluatedToErr),650                        Err(..) => Ok(EvaluatedToAmbig),651                    }652                }653654                ty::PredicateKind::Coerce(p) => {655                    let p = bound_predicate.rebind(p);656                    // Does this code ever run?657                    match self.infcx.coerce_predicate(&obligation.cause, obligation.param_env, p) {658                        Ok(Ok(InferOk { obligations, .. })) => {659                            self.evaluate_predicates_recursively(previous_stack, obligations)660                        }661                        Ok(Err(_)) => Ok(EvaluatedToErr),662                        Err(..) => Ok(EvaluatedToAmbig),663                    }664                }665666                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {667                    if term.is_trivially_wf(self.tcx()) {668                        return Ok(EvaluatedToOk);669                    }670671                    // So, there is a bit going on here. First, `WellFormed` predicates672                    // are coinductive, like trait predicates with auto traits.673                    // This means that we need to detect if we have recursively674                    // evaluated `WellFormed(X)`. Otherwise, we would run into675                    // a "natural" overflow error.676                    //677                    // Now, the next question is whether we need to do anything678                    // special with caching. Considering the following tree:679                    // - `WF(Foo<T>)`680                    //   - `Bar<T>: Send`681                    //     - `WF(Foo<T>)`682                    //   - `Foo<T>: Trait`683                    // In this case, the innermost `WF(Foo<T>)` should return684                    // `EvaluatedToOk`, since it's coinductive. Then if685                    // `Bar<T>: Send` is resolved to `EvaluatedToOk`, it can be686                    // inserted into a cache (because without thinking about `WF`687                    // goals, it isn't in a cycle). If `Foo<T>: Trait` later doesn't688                    // hold, then `Bar<T>: Send` shouldn't hold. Therefore, we689                    // *do* need to keep track of coinductive cycles.690691                    let cache = previous_stack.cache;692                    let dfn = cache.next_dfn();693694                    for stack_term in previous_stack.cache.wf_args.borrow().iter().rev() {695                        if stack_term.0 != term {696                            continue;697                        }698                        debug!("WellFormed({:?}) on stack", term);699                        if let Some(stack) = previous_stack.head {700                            // Okay, let's imagine we have two different stacks:701                            //   `T: NonAutoTrait -> WF(T) -> T: NonAutoTrait`702                            //   `WF(T) -> T: NonAutoTrait -> WF(T)`703                            // Because of this, we need to check that all704                            // predicates between the WF goals are coinductive.705                            // Otherwise, we can say that `T: NonAutoTrait` is706                            // true.707                            // Let's imagine we have a predicate stack like708                            //         `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto`709                            // depth   ^1                    ^2                 ^3710                            // and the current predicate is `WF(T)`. `wf_args`711                            // would contain `(T, 1)`. We want to check all712                            // trait predicates greater than `1`. The previous713                            // stack would be `T: Auto`.714                            let cycle = stack.iter().take_while(|s| s.depth > stack_term.1);715                            let tcx = self.tcx();716                            let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx));717                            if self.coinductive_match(cycle) {718                                stack.update_reached_depth(stack_term.1);719                                return Ok(EvaluatedToOk);720                            } else {721                                return Ok(EvaluatedToAmbigStackDependent);722                            }723                        }724                        return Ok(EvaluatedToOk);725                    }726727                    match wf::obligations(728                        self.infcx,729                        obligation.param_env,730                        obligation.cause.body_id,731                        obligation.recursion_depth + 1,732                        term,733                        obligation.cause.span,734                    ) {735                        Some(obligations) => {736                            cache.wf_args.borrow_mut().push((term, previous_stack.depth()));737                            let result =738                                self.evaluate_predicates_recursively(previous_stack, obligations);739                            cache.wf_args.borrow_mut().pop();740741                            let result = result?;742743                            if !result.must_apply_modulo_regions() {744                                cache.on_failure(dfn);745                            }746747                            cache.on_completion(dfn);748749                            Ok(result)750                        }751                        None => Ok(EvaluatedToAmbig),752                    }753                }754755                ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(pred)) => {756                    // A global type with no free lifetimes or generic parameters757                    // outlives anything.758                    if pred.0.has_free_regions()759                        || pred.0.has_bound_regions()760                        || pred.0.has_non_region_infer()761                        || pred.0.has_non_region_param()762                    {763                        Ok(EvaluatedToOkModuloRegions)764                    } else {765                        Ok(EvaluatedToOk)766                    }767                }768769                ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {770                    // We do not consider region relationships when evaluating trait matches.771                    Ok(EvaluatedToOkModuloRegions)772                }773774                ty::PredicateKind::DynCompatible(trait_def_id) => {775                    if self.tcx().is_dyn_compatible(trait_def_id) {776                        Ok(EvaluatedToOk)777                    } else {778                        Ok(EvaluatedToErr)779                    }780                }781782                ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {783                    let data = bound_predicate.rebind(data);784                    let project_obligation = obligation.with(self.tcx(), data);785                    match project::poly_project_and_unify_term(self, &project_obligation) {786                        ProjectAndUnifyResult::Holds(mut subobligations) => {787                            'compute_res: {788                                // If we've previously marked this projection as 'complete', then789                                // use the final cached result (either `EvaluatedToOk` or790                                // `EvaluatedToOkModuloRegions`), and skip re-evaluating the791                                // sub-obligations.792                                if let Some(key) =793                                    ProjectionCacheKey::from_poly_projection_obligation(794                                        self,795                                        &project_obligation,796                                    )797                                    && let Some(cached_res) = self798                                        .infcx799                                        .inner800                                        .borrow_mut()801                                        .projection_cache()802                                        .is_complete(key)803                                {804                                    break 'compute_res Ok(cached_res);805                                }806807                                // Need to explicitly set the depth of nested goals here as808                                // projection obligations can cycle by themselves and in809                                // `evaluate_predicates_recursively` we only add the depth810                                // for parent trait goals because only these get added to the811                                // `TraitObligationStackList`.812                                for subobligation in subobligations.iter_mut() {813                                    subobligation.set_depth_from_parent(obligation.recursion_depth);814                                }815                                let res = self.evaluate_predicates_recursively(816                                    previous_stack,817                                    subobligations,818                                );819                                if let Ok(eval_rslt) = res820                                    && (eval_rslt == EvaluatedToOk821                                        || eval_rslt == EvaluatedToOkModuloRegions)822                                    && let Some(key) =823                                        ProjectionCacheKey::from_poly_projection_obligation(824                                            self,825                                            &project_obligation,826                                        )827                                {828                                    // If the result is something that we can cache, then mark this829                                    // entry as 'complete'. This will allow us to skip evaluating the830                                    // subobligations at all the next time we evaluate the projection831                                    // predicate.832                                    self.infcx833                                        .inner834                                        .borrow_mut()835                                        .projection_cache()836                                        .complete(key, eval_rslt);837                                }838                                res839                            }840                        }841                        ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig),842                        ProjectAndUnifyResult::Recursive => Ok(EvaluatedToAmbigStackDependent),843                        ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr),844                    }845                }846847                ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {848                    if may_use_unstable_feature(self.infcx, obligation.param_env, symbol) {849                        Ok(EvaluatedToOk)850                    } else {851                        Ok(EvaluatedToAmbig)852                    }853                }854855                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {856                    match const_evaluatable::is_const_evaluatable(857                        self.infcx,858                        uv,859                        obligation.param_env,860                        obligation.cause.span,861                    ) {862                        Ok(()) => Ok(EvaluatedToOk),863                        Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig),864                        Err(NotConstEvaluatable::MentionsParam) => Ok(EvaluatedToErr),865                        Err(_) => Ok(EvaluatedToErr),866                    }867                }868869                ty::PredicateKind::ConstEquate(c1, c2) => {870                    let tcx = self.tcx();871                    assert!(872                        tcx.features().generic_const_exprs(),873                        "`ConstEquate` without a feature gate: {c1:?} {c2:?}",874                    );875876                    {877                        let c1 = tcx.expand_abstract_consts(c1);878                        let c2 = tcx.expand_abstract_consts(c2);879                        debug!(880                            "evaluate_predicate_recursively: equating consts:\nc1= {:?}\nc2= {:?}",881                            c1, c2882                        );883884                        match (c1.kind(), c2.kind()) {885                            (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))886                                if a.kind == b.kind887                                    && matches!(888                                        a.kind,889                                        ty::UnevaluatedConstKind::Projection { .. }890                                            | ty::UnevaluatedConstKind::Inherent { .. }891                                    ) =>892                            {893                                if let Ok(InferOk { obligations, value: () }) = self894                                    .infcx895                                    .at(&obligation.cause, obligation.param_env)896                                    // Can define opaque types as this is only reachable with897                                    // `generic_const_exprs`898                                    .eq(899                                        DefineOpaqueTypes::Yes,900                                        ty::AliasTerm::from(a),901                                        ty::AliasTerm::from(b),902                                    )903                                {904                                    return self.evaluate_predicates_recursively(905                                        previous_stack,906                                        obligations,907                                    );908                                }909                            }910                            (_, ty::ConstKind::Unevaluated(_))911                            | (ty::ConstKind::Unevaluated(_), _) => (),912                            (_, _) => {913                                if let Ok(InferOk { obligations, value: () }) = self914                                    .infcx915                                    .at(&obligation.cause, obligation.param_env)916                                    // Can define opaque types as this is only reachable with917                                    // `generic_const_exprs`918                                    .eq(DefineOpaqueTypes::Yes, c1, c2)919                                {920                                    return self.evaluate_predicates_recursively(921                                        previous_stack,922                                        obligations,923                                    );924                                }925                            }926                        }927                    }928929                    let evaluate = |c: ty::Const<'tcx>| {930                        if let ty::ConstKind::Unevaluated(_) = c.kind() {931                            match crate::traits::try_evaluate_const(932                                self.infcx,933                                c,934                                obligation.param_env,935                            ) {936                                Ok(val) => Ok(val),937                                Err(e) => Err(e),938                            }939                        } else {940                            Ok(c)941                        }942                    };943944                    match (evaluate(c1), evaluate(c2)) {945                        (Ok(c1), Ok(c2)) => {946                            match self.infcx.at(&obligation.cause, obligation.param_env).eq(947                                // Can define opaque types as this is only reachable with948                                // `generic_const_exprs`949                                DefineOpaqueTypes::Yes,950                                c1,951                                c2,952                            ) {953                                Ok(inf_ok) => self.evaluate_predicates_recursively(954                                    previous_stack,955                                    inf_ok.into_obligations(),956                                ),957                                Err(_) => Ok(EvaluatedToErr),958                            }959                        }960                        (Err(EvaluateConstErr::InvalidConstParamTy(..)), _)961                        | (_, Err(EvaluateConstErr::InvalidConstParamTy(..))) => Ok(EvaluatedToErr),962                        (Err(EvaluateConstErr::EvaluationFailure(..)), _)963                        | (_, Err(EvaluateConstErr::EvaluationFailure(..))) => Ok(EvaluatedToErr),964                        (Err(EvaluateConstErr::HasGenericsOrInfers), _)965                        | (_, Err(EvaluateConstErr::HasGenericsOrInfers)) => {966                            if c1.has_non_region_infer() || c2.has_non_region_infer() {967                                Ok(EvaluatedToAmbig)968                            } else {969                                // Two different constants using generic parameters ~> error.970                                Ok(EvaluatedToErr)971                            }972                        }973                    }974                }975                ty::PredicateKind::NormalizesTo(..) => {976                    bug!("NormalizesTo is only used by the new solver")977                }978                ty::PredicateKind::AliasRelate(..) => {979                    bug!("AliasRelate is only used by the new solver")980                }981                ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),982                ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {983                    let ct = self.infcx.shallow_resolve_const(ct);984                    let ct_ty = match ct.kind() {985                        ty::ConstKind::Infer(_) => {986                            return Ok(EvaluatedToAmbig);987                        }988                        ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),989                        ty::ConstKind::Value(cv) => cv.ty,990                        ty::ConstKind::Unevaluated(uv) => uv.type_of(self.tcx()).skip_norm_wip(),991                        // FIXME(generic_const_exprs): See comment in `fulfill.rs`992                        ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk),993                        ty::ConstKind::Placeholder(_) => {994                            bug!("placeholder const {:?} in old solver", ct)995                        }996                        ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),997                        ty::ConstKind::Param(param_ct) => {998                            param_ct.find_const_ty_from_env(obligation.param_env)999                        }1000                    };10011002                    match self.infcx.at(&obligation.cause, obligation.param_env).eq(1003                        // Only really exercised by generic_const_exprs1004                        DefineOpaqueTypes::Yes,1005                        ct_ty,1006                        ty,1007                    ) {1008                        Ok(inf_ok) => self.evaluate_predicates_recursively(1009                            previous_stack,1010                            inf_ok.into_obligations(),1011                        ),1012                        Err(_) => Ok(EvaluatedToErr),1013                    }1014                }1015            }1016        })1017    }10181019    #[instrument(skip(self, previous_stack), level = "debug", ret)]1020    fn evaluate_trait_predicate_recursively<'o>(1021        &mut self,1022        previous_stack: TraitObligationStackList<'o, 'tcx>,1023        mut obligation: PolyTraitObligation<'tcx>,1024    ) -> Result<EvaluationResult, OverflowError> {1025        if !self.typing_mode().is_coherence()1026            && obligation.is_global()1027            && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())1028        {1029            // If a param env has no global bounds, global obligations do not1030            // depend on its particular value in order to work, so we can clear1031            // out the param env and get better caching.1032            debug!("in global");1033            obligation.param_env = ty::ParamEnv::empty();1034        }10351036        let stack = self.push_stack(previous_stack, &obligation);1037        let fresh_trait_pred = stack.fresh_trait_pred;1038        let param_env = obligation.param_env;10391040        debug!(?fresh_trait_pred);10411042        // If a trait predicate is in the (local or global) evaluation cache,1043        // then we know it holds without cycles.1044        if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) {1045            debug!("CACHE HIT");1046            return Ok(result);1047        }10481049        if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) {1050            debug!("PROVISIONAL CACHE HIT");1051            stack.update_reached_depth(result.reached_depth);1052            return Ok(result.result);1053        }10541055        // Check if this is a match for something already on the1056        // stack. If so, we don't want to insert the result into the1057        // main cache (it is cycle dependent) nor the provisional1058        // cache (which is meant for things that have completed but1059        // for a "backedge" -- this result *is* the backedge).1060        if let Some(cycle_result) = self.check_evaluation_cycle(&stack) {1061            return Ok(cycle_result);1062        }10631064        let (result, dep_node) = self.in_task(|this| {1065            let mut result = this.evaluate_stack(&stack)?;10661067            // fix issue #103563, we don't normalize1068            // nested obligations which produced by `TraitDef` candidate1069            // (i.e. using bounds on assoc items as assumptions).1070            // because we don't have enough information to1071            // normalize these obligations before evaluating.1072            // so we will try to normalize the obligation and evaluate again.1073            // we will replace it with new solver in the future.1074            if EvaluationResult::EvaluatedToErr == result1075                && fresh_trait_pred.has_aliases()1076                && fresh_trait_pred.is_global()1077            {1078                let mut nested_obligations = PredicateObligations::new();1079                let predicate = normalize_with_depth_to(1080                    this,1081                    param_env,1082                    obligation.cause.clone(),1083                    obligation.recursion_depth + 1,1084                    obligation.predicate,1085                    &mut nested_obligations,1086                );1087                if predicate != obligation.predicate {1088                    let mut nested_result = EvaluationResult::EvaluatedToOk;1089                    for obligation in nested_obligations {1090                        nested_result = cmp::max(1091                            this.evaluate_predicate_recursively(previous_stack, obligation)?,1092                            nested_result,1093                        );1094                    }10951096                    if nested_result.must_apply_modulo_regions() {1097                        let obligation = obligation.with(this.tcx(), predicate);1098                        result = cmp::max(1099                            nested_result,1100                            this.evaluate_trait_predicate_recursively(previous_stack, obligation)?,1101                        );1102                    }1103                }1104            }11051106            Ok::<_, OverflowError>(result)1107        });11081109        let result = result?;11101111        if !result.must_apply_modulo_regions() {1112            stack.cache().on_failure(stack.dfn);1113        }11141115        let reached_depth = stack.reached_depth.get();1116        if reached_depth >= stack.depth {1117            debug!("CACHE MISS");1118            self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result);1119            stack.cache().on_completion(stack.dfn);1120        } else if let Some(_guar) = self.infcx.tainted_by_errors() {1121            // When an error has occurred, we allow global caching of results even if they1122            // appear stack-dependent. This prevents exponential re-evaluation of cycles1123            // in the presence of errors, avoiding compiler hangs like #150907.1124            // This is safe because compilation will fail anyway.1125            debug!("CACHE MISS (tainted by errors)");1126            self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result);1127            stack.cache().on_completion(stack.dfn);1128        } else {1129            debug!("PROVISIONAL");1130            debug!(1131                "caching provisionally because {:?} \1132                 is a cycle participant (at depth {}, reached depth {})",1133                fresh_trait_pred, stack.depth, reached_depth,1134            );11351136            stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_pred, result);1137        }11381139        Ok(result)1140    }11411142    /// If there is any previous entry on the stack that precisely1143    /// matches this obligation, then we can assume that the1144    /// obligation is satisfied for now (still all other conditions1145    /// must be met of course). One obvious case this comes up is1146    /// marker traits like `Send`. Think of a linked list:1147    ///1148    ///     struct List<T> { data: T, next: Option<Box<List<T>>> }1149    ///1150    /// `Box<List<T>>` will be `Send` if `T` is `Send` and1151    /// `Option<Box<List<T>>>` is `Send`, and in turn1152    /// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` is1153    /// `Send`.1154    ///1155    /// Note that we do this comparison using the `fresh_trait_pred`1156    /// fields. Because these have all been freshened using1157    /// `self.freshener`, we can be sure that (a) this will not1158    /// affect the inferencer state and (b) that if we see two1159    /// fresh regions with the same index, they refer to the same1160    /// unbound type variable.1161    fn check_evaluation_cycle(1162        &mut self,1163        stack: &TraitObligationStack<'_, 'tcx>,1164    ) -> Option<EvaluationResult> {1165        if let Some(cycle_depth) = stack1166            .iter()1167            .skip(1) // Skip top-most frame.1168            .find(|prev| {1169                stack.obligation.param_env == prev.obligation.param_env1170                    && stack.fresh_trait_pred == prev.fresh_trait_pred1171            })1172            .map(|stack| stack.depth)1173        {1174            debug!("evaluate_stack --> recursive at depth {}", cycle_depth);11751176            // If we have a stack like `A B C D E A`, where the top of1177            // the stack is the final `A`, then this will iterate over1178            // `A, E, D, C, B` -- i.e., all the participants apart1179            // from the cycle head. We mark them as participating in a1180            // cycle. This suppresses caching for those nodes. See1181            // `in_cycle` field for more details.1182            stack.update_reached_depth(cycle_depth);11831184            // Subtle: when checking for a coinductive cycle, we do1185            // not compare using the "freshened trait refs" (which1186            // have erased regions) but rather the fully explicit1187            // trait refs. This is important because it's only a cycle1188            // if the regions match exactly.1189            let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);1190            let tcx = self.tcx();1191            let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx));1192            if self.coinductive_match(cycle) {1193                debug!("evaluate_stack --> recursive, coinductive");1194                Some(EvaluatedToOk)1195            } else {1196                debug!("evaluate_stack --> recursive, inductive");1197                Some(EvaluatedToAmbigStackDependent)1198            }1199        } else {1200            None1201        }1202    }12031204    fn evaluate_stack<'o>(1205        &mut self,1206        stack: &TraitObligationStack<'o, 'tcx>,1207    ) -> Result<EvaluationResult, OverflowError> {1208        debug_assert!(!self.infcx.next_trait_solver());1209        // In intercrate mode, whenever any of the generics are unbound,1210        // there can always be an impl. Even if there are no impls in1211        // this crate, perhaps the type would be unified with1212        // something from another crate that does provide an impl.1213        //1214        // In intra mode, we must still be conservative. The reason is1215        // that we want to avoid cycles. Imagine an impl like:1216        //1217        //     impl<T:Eq> Eq for Vec<T>1218        //1219        // and a trait reference like `$0 : Eq` where `$0` is an1220        // unbound variable. When we evaluate this trait-reference, we1221        // will unify `$0` with `Vec<$1>` (for some fresh variable1222        // `$1`), on the condition that `$1 : Eq`. We will then wind1223        // up with many candidates (since that are other `Eq` impls1224        // that apply) and try to winnow things down. This results in1225        // a recursive evaluation that `$1 : Eq` -- as you can1226        // imagine, this is just where we started. To avoid that, we1227        // check for unbound variables and return an ambiguous (hence possible)1228        // match if we've seen this trait before.1229        //1230        // This suffices to allow chains like `FnMut` implemented in1231        // terms of `Fn` etc, but we could probably make this more1232        // precise still.1233        let unbound_input_types =1234            stack.fresh_trait_pred.skip_binder().trait_ref.args.types().any(|ty| ty.is_fresh());12351236        if unbound_input_types1237            && stack.iter().skip(1).any(|prev| {1238                stack.obligation.param_env == prev.obligation.param_env1239                    && self.match_fresh_trait_preds(stack.fresh_trait_pred, prev.fresh_trait_pred)1240            })1241        {1242            debug!("evaluate_stack --> unbound argument, recursive --> giving up");1243            return Ok(EvaluatedToAmbigStackDependent);1244        }12451246        match self.candidate_from_obligation(stack) {1247            Ok(Some(c)) => self.evaluate_candidate(stack, &c),1248            Ok(None) => Ok(EvaluatedToAmbig),1249            Err(SelectionError::Overflow(OverflowError::Canonical)) => {1250                Err(OverflowError::Canonical)1251            }1252            Err(..) => Ok(EvaluatedToErr),1253        }1254    }12551256    /// For defaulted traits, we use a co-inductive strategy to solve, so1257    /// that recursion is ok. This routine returns `true` if the top of the1258    /// stack (`cycle[0]`):1259    ///1260    /// - is a coinductive trait: an auto-trait or `Sized`,1261    /// - it also appears in the backtrace at some position `X`,1262    /// - all the predicates at positions `X..` between `X` and the top are1263    ///   also coinductive traits.1264    pub(crate) fn coinductive_match<I>(&mut self, mut cycle: I) -> bool1265    where1266        I: Iterator<Item = ty::Predicate<'tcx>>,1267    {1268        cycle.all(|p| match p.kind().skip_binder() {1269            ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {1270                self.infcx.tcx.trait_is_coinductive(data.def_id())1271            }1272            ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {1273                // FIXME(generic_const_exprs): GCE needs well-formedness predicates to be1274                // coinductive, but GCE is on the way out anyways, so this should eventually1275                // be replaced with `false`.1276                self.infcx.tcx.features().generic_const_exprs()1277            }1278            _ => false,1279        })1280    }12811282    /// Further evaluates `candidate` to decide whether all type parameters match and whether nested1283    /// obligations are met. Returns whether `candidate` remains viable after this further1284    /// scrutiny.1285    #[instrument(1286        level = "debug",1287        skip(self, stack),1288        fields(depth = stack.obligation.recursion_depth),1289        ret1290    )]1291    fn evaluate_candidate<'o>(1292        &mut self,1293        stack: &TraitObligationStack<'o, 'tcx>,1294        candidate: &SelectionCandidate<'tcx>,1295    ) -> Result<EvaluationResult, OverflowError> {1296        let mut result = self.evaluation_probe(|this| {1297            match this.confirm_candidate(stack.obligation, candidate.clone()) {1298                Ok(selection) => {1299                    debug!(?selection);1300                    this.evaluate_predicates_recursively(1301                        stack.list(),1302                        selection.nested_obligations().into_iter(),1303                    )1304                }1305                Err(..) => Ok(EvaluatedToErr),1306            }1307        })?;13081309        // If we erased any lifetimes, then we want to use1310        // `EvaluatedToOkModuloRegions` instead of `EvaluatedToOk`1311        // as your final result. The result will be cached using1312        // the freshened trait predicate as a key, so we need1313        // our result to be correct by *any* choice of original lifetimes,1314        // not just the lifetime choice for this particular (non-erased)1315        // predicate.1316        // See issue #806911317        if stack.fresh_trait_pred.has_erased_regions() {1318            result = result.max(EvaluatedToOkModuloRegions);1319        }13201321        Ok(result)1322    }13231324    fn check_evaluation_cache(1325        &self,1326        param_env: ty::ParamEnv<'tcx>,1327        trait_pred: ty::PolyTraitPredicate<'tcx>,1328    ) -> Option<EvaluationResult> {1329        let infcx = self.infcx;1330        let tcx = infcx.tcx;1331        if self.can_use_global_caches(param_env, trait_pred) {1332            let key = (infcx.typing_env(param_env), trait_pred);1333            if let Some(res) = tcx.evaluation_cache.get(&key, tcx) {1334                Some(res)1335            } else {1336                debug_assert_eq!(infcx.evaluation_cache.get(&(param_env, trait_pred), tcx), None);1337                None1338            }1339        } else {1340            self.infcx.evaluation_cache.get(&(param_env, trait_pred), tcx)1341        }1342    }13431344    fn insert_evaluation_cache(1345        &mut self,1346        param_env: ty::ParamEnv<'tcx>,1347        trait_pred: ty::PolyTraitPredicate<'tcx>,1348        dep_node: DepNodeIndex,1349        result: EvaluationResult,1350    ) {1351        // Avoid caching results that depend on more than just the trait-ref1352        // - the stack can create recursion.1353        if result.is_stack_dependent() {1354            return;1355        }13561357        let infcx = self.infcx;1358        let tcx = infcx.tcx;1359        if self.can_use_global_caches(param_env, trait_pred) {1360            debug!(?trait_pred, ?result, "insert_evaluation_cache global");1361            // This may overwrite the cache with the same value1362            tcx.evaluation_cache.insert(1363                (infcx.typing_env(param_env), trait_pred),1364                dep_node,1365                result,1366            );1367            return;1368        } else {1369            debug!(?trait_pred, ?result, "insert_evaluation_cache local");1370            self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);1371        }1372    }13731374    fn check_recursion_depth<T>(1375        &self,1376        depth: usize,1377        error_obligation: &Obligation<'tcx, T>,1378    ) -> Result<(), OverflowError>1379    where1380        T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone,1381    {1382        if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {1383            match self.query_mode {1384                TraitQueryMode::Standard => {1385                    if let Some(e) = self.infcx.tainted_by_errors() {1386                        return Err(OverflowError::Error(e));1387                    }1388                    self.infcx.err_ctxt().report_overflow_obligation(error_obligation, true);1389                }1390                TraitQueryMode::Canonical => {1391                    return Err(OverflowError::Canonical);1392                }1393            }1394        }1395        Ok(())1396    }13971398    /// Checks that the recursion limit has not been exceeded.1399    ///1400    /// The weird return type of this function allows it to be used with the `try` (`?`)1401    /// operator within certain functions.1402    #[inline(always)]1403    fn check_recursion_limit<T: Display + TypeFoldable<TyCtxt<'tcx>>, V>(1404        &self,1405        obligation: &Obligation<'tcx, T>,1406        error_obligation: &Obligation<'tcx, V>,1407    ) -> Result<(), OverflowError>1408    where1409        V: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>> + Clone,1410    {1411        self.check_recursion_depth(obligation.recursion_depth, error_obligation)1412    }14131414    fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)1415    where1416        OP: FnOnce(&mut Self) -> R,1417    {1418        self.tcx().dep_graph.with_anon_task(self.tcx(), DepKind::TraitSelect, || op(self))1419    }14201421    /// filter_impls filters candidates that have a positive impl for a negative1422    /// goal and a negative impl for a positive goal1423    #[instrument(level = "debug", skip(self, candidates))]1424    fn filter_impls(1425        &mut self,1426        candidates: Vec<SelectionCandidate<'tcx>>,1427        obligation: &PolyTraitObligation<'tcx>,1428    ) -> Vec<SelectionCandidate<'tcx>> {1429        trace!("{candidates:#?}");1430        let tcx = self.tcx();1431        let mut result = Vec::with_capacity(candidates.len());14321433        for candidate in candidates {1434            if let ImplCandidate(def_id) = candidate {1435                match (tcx.impl_polarity(def_id), obligation.polarity()) {1436                    (ty::ImplPolarity::Reservation, _)1437                    | (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive)1438                    | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => {1439                        result.push(candidate);1440                    }1441                    _ => {}1442                }1443            } else {1444                result.push(candidate);1445            }1446        }14471448        trace!("{result:#?}");1449        result1450    }14511452    /// filter_reservation_impls filter reservation impl for any goal as ambiguous1453    #[instrument(level = "debug", skip(self))]1454    fn filter_reservation_impls(1455        &mut self,1456        candidate: SelectionCandidate<'tcx>,1457    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {1458        let tcx = self.tcx();1459        // Treat reservation impls as ambiguity.1460        if let ImplCandidate(def_id) = candidate1461            && let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id)1462        {1463            if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes {1464                let message = find_attr!(tcx, def_id, RustcReservationImpl(message) => *message);1465                if let Some(message) = message {1466                    debug!(1467                        "filter_reservation_impls: \1468                                 reservation impl ambiguity on {:?}",1469                        def_id1470                    );1471                    intercrate_ambiguity_clauses1472                        .insert(IntercrateAmbiguityCause::ReservationImpl { message });1473                }1474            }1475            return Ok(None);1476        }1477        Ok(Some(candidate))1478    }14791480    fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {1481        let obligation = &stack.obligation;1482        match self.typing_mode() {1483            TypingMode::Coherence => {}1484            TypingMode::Typeck { .. }1485            | TypingMode::PostTypeckUntilBorrowck { .. }1486            | TypingMode::PostBorrowck { .. }1487            | TypingMode::PostAnalysis1488            | TypingMode::Codegen => return Ok(()),1489        }14901491        debug!("is_knowable()");14921493        let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);14941495        // Okay to skip binder because of the nature of the1496        // trait-ref-is-knowable check, which does not care about1497        // bound regions.1498        let trait_ref = predicate.skip_binder().trait_ref;14991500        coherence::trait_ref_is_knowable(self.infcx, trait_ref, |ty| Ok::<_, !>(ty)).into_ok()1501    }15021503    /// Returns `true` if the global caches can be used.1504    fn can_use_global_caches(1505        &self,1506        param_env: ty::ParamEnv<'tcx>,1507        pred: ty::PolyTraitPredicate<'tcx>,1508    ) -> bool {1509        // If there are any inference variables in the `ParamEnv`, then we1510        // always use a cache local to this particular scope. Otherwise, we1511        // switch to a global cache.1512        if param_env.has_infer() || pred.has_infer() {1513            return false;1514        }15151516        match self.typing_mode() {1517            // Avoid using the global cache during coherence and just rely1518            // on the local cache. It is really just a simplification to1519            // avoid us having to fear that coherence results "pollute"1520            // the master cache. Since coherence executes pretty quickly,1521            // it's not worth going to more trouble to increase the1522            // hit-rate, I don't think.1523            TypingMode::Coherence => false,1524            // Avoid using the global cache when we're defining opaque types1525            // as their hidden type may impact the result of candidate selection.1526            //1527            // HACK: This is still theoretically unsound. Goals can indirectly rely1528            // on opaques in the defining scope, and it's easier to do so with TAIT.1529            // However, if we disqualify *all* goals from being cached, perf suffers.1530            // This is likely fixed by better caching in general in the new solver.1531            // See: <https://github.com/rust-lang/rust/issues/132064>.1532            TypingMode::Typeck { defining_opaque_types_and_generators: defining_opaque_types }1533            | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types } => {1534                defining_opaque_types.is_empty()1535                    || (!pred.has_opaque_types() && !pred.has_coroutines())1536            }1537            // The hidden types of `defined_opaque_types` is not local to the current1538            // inference context, so we can freely move this to the global cache.1539            TypingMode::PostBorrowck { .. } => true,1540            // The global cache is only used if there are no opaque types in1541            // the defining scope or we're outside of analysis.1542            //1543            // FIXME(#132279): This is still incorrect as we treat opaque types1544            // and default associated items differently between these two modes.1545            TypingMode::PostAnalysis | TypingMode::Codegen => true,1546        }1547    }15481549    fn check_candidate_cache(1550        &mut self,1551        param_env: ty::ParamEnv<'tcx>,1552        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,1553    ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {1554        let infcx = self.infcx;1555        let tcx = infcx.tcx;1556        let pred = cache_fresh_trait_pred.skip_binder();15571558        if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {1559            if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) {1560                return Some(res);1561            } else if cfg!(debug_assertions) {1562                match infcx.selection_cache.get(&(param_env, pred), tcx) {1563                    None | Some(Err(SelectionError::Overflow(OverflowError::Canonical))) => {}1564                    res => bug!("unexpected local cache result: {res:?}"),1565                }1566            }1567        }15681569        // Subtle: we need to check the local cache even if we're able to use the1570        // global cache as we don't cache overflow in the global cache but need to1571        // cache it as otherwise rustdoc hangs when compiling diesel.1572        infcx.selection_cache.get(&(param_env, pred), tcx)1573    }15741575    /// Determines whether can we safely cache the result1576    /// of selecting an obligation. This is almost always `true`,1577    /// except when dealing with certain `ParamCandidate`s.1578    ///1579    /// Ordinarily, a `ParamCandidate` will contain no inference variables,1580    /// since it was usually produced directly from a `DefId`. However,1581    /// certain cases (currently only librustdoc's blanket impl finder),1582    /// a `ParamEnv` may be explicitly constructed with inference types.1583    /// When this is the case, we do *not* want to cache the resulting selection1584    /// candidate. This is due to the fact that it might not always be possible1585    /// to equate the obligation's trait ref and the candidate's trait ref,1586    /// if more constraints end up getting added to an inference variable.1587    ///1588    /// Because of this, we always want to re-run the full selection1589    /// process for our obligation the next time we see it, since1590    /// we might end up picking a different `SelectionCandidate` (or none at all).1591    fn can_cache_candidate(1592        &self,1593        result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,1594    ) -> bool {1595        match result {1596            Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),1597            _ => true,1598        }1599    }16001601    #[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]1602    fn insert_candidate_cache(1603        &mut self,1604        param_env: ty::ParamEnv<'tcx>,1605        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,1606        dep_node: DepNodeIndex,1607        candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,1608    ) {1609        let infcx = self.infcx;1610        let tcx = infcx.tcx;1611        let pred = cache_fresh_trait_pred.skip_binder();16121613        if !self.can_cache_candidate(&candidate) {1614            debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");1615            return;1616        }16171618        if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {1619            if let Err(SelectionError::Overflow(OverflowError::Canonical)) = candidate {1620                // Don't cache overflow globally; we only produce this in certain modes.1621            } else {1622                debug!(?pred, ?candidate, "insert_candidate_cache global");1623                debug_assert!(!candidate.has_infer());16241625                // This may overwrite the cache with the same value.1626                tcx.selection_cache.insert(1627                    (infcx.typing_env(param_env), pred),1628                    dep_node,1629                    candidate,1630                );1631                return;1632            }1633        }16341635        debug!(?pred, ?candidate, "insert_candidate_cache local");1636        self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate);1637    }16381639    /// Looks at the item bounds of the projection or opaque type.1640    /// If this is a nested rigid projection, such as1641    /// `<<T as Tr1>::Assoc as Tr2>::Assoc`, consider the item bounds1642    /// on both `Tr1::Assoc` and `Tr2::Assoc`, since we may encounter1643    /// relative bounds on both via the `associated_type_bounds` feature.1644    pub(super) fn for_each_item_bound<T>(1645        &mut self,1646        mut self_ty: Ty<'tcx>,1647        mut for_each: impl FnMut(1648            &mut Self,1649            ty::Clause<'tcx>,1650            usize,1651            AliasBoundKind,1652        ) -> ControlFlow<T, ()>,1653        on_ambiguity: impl FnOnce(),1654    ) -> ControlFlow<T, ()> {1655        let mut idx = 0;1656        let mut alias_bound_kind = AliasBoundKind::SelfBounds;16571658        loop {1659            let (alias_ty, def_id) = match *self_ty.kind() {1660                ty::Alias(1661                    alias_ty @ ty::AliasTy {1662                        kind: ty::Projection { def_id } | ty::Opaque { def_id },1663                        ..1664                    },1665                ) => (alias_ty, def_id),1666                ty::Infer(ty::TyVar(_)) => {1667                    on_ambiguity();1668                    return ControlFlow::Continue(());1669                }1670                _ => return ControlFlow::Continue(()),1671            };16721673            // HACK: On subsequent recursions, we only care about bounds that don't1674            // share the same type as `self_ty`. This is because for truly rigid1675            // projections, we will never be able to equate, e.g. `<T as Tr>::A`1676            // with `<<T as Tr>::A as Tr>::A`.1677            let relevant_bounds = if alias_bound_kind == AliasBoundKind::NonSelfBounds {1678                self.tcx().item_non_self_bounds(def_id)1679            } else {1680                self.tcx().item_self_bounds(def_id)1681            };16821683            for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args).skip_norm_wip() {1684                for_each(self, bound, idx, alias_bound_kind)?;1685                idx += 1;1686            }16871688            if matches!(alias_ty.kind, ty::Projection { .. }) {1689                self_ty = alias_ty.self_ty();1690            } else {1691                return ControlFlow::Continue(());1692            }16931694            alias_bound_kind = AliasBoundKind::NonSelfBounds;1695        }1696    }16971698    /// Equates the trait in `obligation` with trait bound. If the two traits1699    /// can be equated and the normalized trait bound doesn't contain inference1700    /// variables or placeholders, the normalized bound is returned.1701    fn match_normalize_trait_ref(1702        &mut self,1703        obligation: &PolyTraitObligation<'tcx>,1704        placeholder_trait_ref: ty::TraitRef<'tcx>,1705        trait_bound: ty::PolyTraitRef<'tcx>,1706    ) -> Result<Option<ty::TraitRef<'tcx>>, ()> {1707        debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());1708        if placeholder_trait_ref.def_id != trait_bound.def_id() {1709            // Avoid unnecessary normalization1710            return Err(());1711        }17121713        let drcx = DeepRejectCtxt::relate_rigid_rigid(self.infcx.tcx);1714        let obligation_args = obligation.predicate.skip_binder().trait_ref.args;1715        if !drcx.args_may_unify(obligation_args, trait_bound.skip_binder().args) {1716            return Err(());1717        }17181719        let trait_bound = self.infcx.instantiate_binder_with_fresh_vars(1720            obligation.cause.span,1721            HigherRankedType,1722            trait_bound,1723        );1724        let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| {1725            normalize_with_depth(1726                self,1727                obligation.param_env,1728                obligation.cause.clone(),1729                obligation.recursion_depth + 1,1730                trait_bound,1731            )1732        });1733        self.infcx1734            .at(&obligation.cause, obligation.param_env)1735            .eq(DefineOpaqueTypes::No, placeholder_trait_ref, trait_bound)1736            .map(|InferOk { obligations: _, value: () }| {1737                // This method is called within a probe, so we can't have1738                // inference variables and placeholders escape.1739                if !trait_bound.has_infer() && !trait_bound.has_placeholders() {1740                    Some(trait_bound)1741                } else {1742                    None1743                }1744            })1745            .map_err(|_| ())1746    }17471748    fn where_clause_may_apply<'o>(1749        &mut self,1750        stack: &TraitObligationStack<'o, 'tcx>,1751        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,1752    ) -> Result<EvaluationResult, OverflowError> {1753        self.evaluation_probe(|this| {1754            match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {1755                Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),1756                Err(()) => Ok(EvaluatedToErr),1757            }1758        })1759    }17601761    /// Return `Yes` if the obligation's predicate type applies to the env_predicate, and1762    /// `No` if it does not. Return `Ambiguous` in the case that the projection type is a GAT,1763    /// and applying this env_predicate constrains any of the obligation's GAT parameters.1764    ///1765    /// This behavior is a somewhat of a hack to prevent over-constraining inference variables1766    /// in cases like #91762.1767    pub(super) fn match_projection_projections(1768        &mut self,1769        obligation: &ProjectionTermObligation<'tcx>,1770        env_predicate: PolyProjectionPredicate<'tcx>,1771        potentially_unnormalized_candidates: bool,1772    ) -> ProjectionMatchesProjection {1773        let def_id = obligation.predicate.expect_projection_def_id();1774        debug_assert_eq!(def_id, env_predicate.item_def_id());17751776        let mut nested_obligations = PredicateObligations::new();1777        let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars(1778            obligation.cause.span,1779            BoundRegionConversionTime::HigherRankedType,1780            env_predicate,1781        );1782        let infer_projection = if potentially_unnormalized_candidates {1783            ensure_sufficient_stack(|| {1784                normalize_with_depth_to(1785                    self,1786                    obligation.param_env,1787                    obligation.cause.clone(),1788                    obligation.recursion_depth + 1,1789                    infer_predicate.projection_term,1790                    &mut nested_obligations,1791                )1792            })1793        } else {1794            infer_predicate.projection_term1795        };17961797        let is_match = self1798            .infcx1799            .at(&obligation.cause, obligation.param_env)1800            .eq(DefineOpaqueTypes::No, obligation.predicate, infer_projection)1801            .is_ok_and(|InferOk { obligations, value: () }| {1802                self.evaluate_predicates_recursively(1803                    TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),1804                    nested_obligations.into_iter().chain(obligations),1805                )1806                .is_ok_and(|res| res.may_apply())1807            });18081809        if is_match {1810            let generics = self.tcx().generics_of(def_id);1811            // FIXME(generic_associated_types): Addresses aggressive inference in #92917.1812            // If this type is a GAT, and of the GAT args resolve to something new,1813            // that means that we must have newly inferred something about the GAT.1814            // We should give up in that case.1815            //1816            // This only detects one layer of inference, which is probably not what we actually1817            // want, but fixing it causes some ambiguity:1818            // <https://github.com/rust-lang/rust/issues/125196>.1819            if !generics.is_own_empty()1820                && obligation.predicate.args[generics.parent_count..].iter().any(|&p| {1821                    p.has_non_region_infer()1822                        && match p.kind() {1823                            ty::GenericArgKind::Const(ct) => {1824                                self.infcx.shallow_resolve_const(ct) != ct1825                            }1826                            ty::GenericArgKind::Type(ty) => self.infcx.shallow_resolve(ty) != ty,1827                            ty::GenericArgKind::Lifetime(_) => false,1828                        }1829                })1830            {1831                ProjectionMatchesProjection::Ambiguous1832            } else {1833                ProjectionMatchesProjection::Yes1834            }1835        } else {1836            ProjectionMatchesProjection::No1837        }1838    }1839}18401841/// ## Winnowing1842///1843/// Winnowing is the process of attempting to resolve ambiguity by1844/// probing further. During the winnowing process, we unify all1845/// type variables and then we also attempt to evaluate recursive1846/// bounds to see if they are satisfied.1847impl<'tcx> SelectionContext<'_, 'tcx> {1848    /// If there are multiple ways to prove a trait goal, we make some1849    /// *fairly arbitrary* choices about which candidate is actually used.1850    ///1851    /// For more details, look at the implementation of this method :)1852    #[instrument(level = "debug", skip(self), ret)]1853    fn winnow_candidates(1854        &mut self,1855        has_non_region_infer: bool,1856        candidate_preference_mode: CandidatePreferenceMode,1857        mut candidates: Vec<EvaluatedCandidate<'tcx>>,1858    ) -> Option<SelectionCandidate<'tcx>> {1859        if candidates.len() == 1 {1860            return Some(candidates.pop().unwrap().candidate);1861        }18621863        // We prefer `Sized` candidates over everything.1864        let mut sized_candidates =1865            candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate));1866        if let Some(sized_candidate) = sized_candidates.next() {1867            // There should only ever be a single sized candidate1868            // as they would otherwise overlap.1869            debug_assert_eq!(sized_candidates.next(), None);1870            // Only prefer the built-in `Sized` candidate if its nested goals are certain.1871            // Otherwise, we may encounter failure later on if inference causes this candidate1872            // to not hold, but a where clause would've applied instead.1873            if sized_candidate.evaluation.must_apply_modulo_regions() {1874                return Some(sized_candidate.candidate.clone());1875            } else {1876                return None;1877            }1878        }18791880        // Before we consider where-bounds, we have to deduplicate them here and also1881        // drop where-bounds in case the same where-bound exists without bound vars.1882        // This is necessary as elaborating super-trait bounds may result in duplicates.1883        'search_victim: loop {1884            for (i, this) in candidates.iter().enumerate() {1885                let ParamCandidate(this) = this.candidate else { continue };1886                for (j, other) in candidates.iter().enumerate() {1887                    if i == j {1888                        continue;1889                    }18901891                    let ParamCandidate(other) = other.candidate else { continue };1892                    if this == other {1893                        candidates.remove(j);1894                        continue 'search_victim;1895                    }18961897                    if this.skip_binder().trait_ref == other.skip_binder().trait_ref1898                        && this.skip_binder().polarity == other.skip_binder().polarity1899                        && !this.skip_binder().trait_ref.has_escaping_bound_vars()1900                    {1901                        candidates.remove(j);1902                        continue 'search_victim;1903                    }1904                }1905            }19061907            break;1908        }19091910        let mut alias_bounds = candidates.iter().filter_map(|c| {1911            if let ProjectionCandidate { idx, kind } = c.candidate {1912                Some((idx, kind))1913            } else {1914                None1915            }1916        });1917        // Extract non-nested alias bound candidates, will be preferred over where bounds if1918        // we're proving an auto-trait, sizedness trait or default trait.1919        if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) {1920            match alias_bounds1921                .clone()1922                .filter_map(|(idx, kind)| (kind == AliasBoundKind::SelfBounds).then_some(idx))1923                .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) })1924            {1925                Some(Some(idx)) => {1926                    return Some(ProjectionCandidate { idx, kind: AliasBoundKind::SelfBounds });1927                }1928                Some(None) => {}1929                None => return None,1930            }1931        }19321933        // The next highest priority is for non-global where-bounds. However, while we don't1934        // prefer global where-clauses here, we do bail with ambiguity when encountering both1935        // a global and a non-global where-clause.1936        //1937        // Our handling of where-bounds is generally fairly messy but necessary for backwards1938        // compatibility, see #50825 for why we need to handle global where-bounds like this.1939        let is_global = |c: ty::PolyTraitPredicate<'tcx>| c.is_global() && !c.has_bound_vars();1940        let param_candidates = candidates1941            .iter()1942            .filter_map(|c| if let ParamCandidate(p) = c.candidate { Some(p) } else { None });1943        let mut has_global_bounds = false;1944        let mut param_candidate = None;1945        for c in param_candidates {1946            if is_global(c) {1947                has_global_bounds = true;1948            } else if param_candidate.replace(c).is_some() {1949                // Ambiguity, two potentially different where-clauses1950                return None;1951            }1952        }1953        if let Some(predicate) = param_candidate {1954            // Ambiguity, a global and a non-global where-bound.1955            if has_global_bounds {1956                return None;1957            } else {1958                return Some(ParamCandidate(predicate));1959            }1960        }19611962        // Prefer alias-bounds over blanket impls for rigid associated types. This is1963        // fairly arbitrary but once again necessary for backwards compatibility.1964        // If there are multiple applicable candidates which don't affect type inference,1965        // choose the one with the lowest index.1966        match alias_bounds.try_reduce(|(c1, k1), (c2, k2)| {1967            if has_non_region_infer {1968                None1969            } else if c1 < c2 {1970                Some((c1, k1))1971            } else {1972                Some((c2, k2))1973            }1974        }) {1975            Some(Some((idx, kind))) => return Some(ProjectionCandidate { idx, kind }),1976            Some(None) => {}1977            None => return None,1978        }19791980        // Need to prioritize builtin trait object impls as `<dyn Any as Any>::type_id`1981        // should use the vtable method and not the method provided by the user-defined1982        // impl `impl<T: ?Sized> Any for T { .. }`. This really shouldn't exist but is1983        // necessary due to #57893. We again arbitrarily prefer the applicable candidate1984        // with the lowest index.1985        //1986        // We do not want to use these impls to guide inference in case a user-written impl1987        // may also apply.1988        let object_bound = candidates1989            .iter()1990            .filter_map(|c| if let ObjectCandidate(i) = c.candidate { Some(i) } else { None })1991            .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) });1992        match object_bound {1993            Some(Some(index)) => {1994                return if has_non_region_infer1995                    && candidates.iter().any(|c| matches!(c.candidate, ImplCandidate(_)))1996                {1997                    None1998                } else {1999                    Some(ObjectCandidate(index))2000                };

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.