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.