Refactor fetch_eligible_assoc_item output

This commit is contained in:
Jana Dönszelmann
2026-04-15 11:23:19 +02:00
parent 7ff71be015
commit 9fda7e0c97
6 changed files with 57 additions and 28 deletions
@@ -14,6 +14,8 @@
pub type CandidateSource<'tcx> = ir::solve::CandidateSource<TyCtxt<'tcx>>;
pub type CanonicalInput<'tcx, P = ty::Predicate<'tcx>> = ir::solve::CanonicalInput<TyCtxt<'tcx>, P>;
pub type CanonicalResponse<'tcx> = ir::solve::CanonicalResponse<TyCtxt<'tcx>>;
pub type FetchEligibleAssocItemResponse<'tcx> =
ir::solve::FetchEligibleAssocItemResponse<TyCtxt<'tcx>>;
pub type PredefinedOpaques<'tcx> = &'tcx ty::List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>;
@@ -1,6 +1,8 @@
use std::ops::Deref;
use rustc_type_ir::solve::{Certainty, Goal, NoSolution, VisibleForLeakCheck};
use rustc_type_ir::solve::{
Certainty, FetchEligibleAssocItemResponse, Goal, NoSolution, VisibleForLeakCheck,
};
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable};
pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
@@ -79,10 +81,7 @@ fn fetch_eligible_assoc_item(
goal_trait_ref: ty::TraitRef<Self::Interner>,
trait_assoc_def_id: <Self::Interner as Interner>::DefId,
impl_def_id: <Self::Interner as Interner>::ImplId,
) -> Result<
Option<<Self::Interner as Interner>::DefId>,
<Self::Interner as Interner>::ErrorGuaranteed,
>;
) -> FetchEligibleAssocItemResponse<Self::Interner>;
fn is_transmutable(
&self,
@@ -8,7 +8,9 @@
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind};
use rustc_type_ir::solve::{AccessedOpaques, MaybeInfo, OpaqueTypesJank, RerunCondition, SmallCopyList};
use rustc_type_ir::solve::{
AccessedOpaques, MaybeInfo, FetchEligibleAssocItemResponse, OpaqueTypesJank, RerunCondition, SmallCopyList,
};
use rustc_type_ir::{
self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased,
OpaqueTypeKey, PredicateKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
@@ -1350,7 +1352,7 @@ pub(super) fn fetch_eligible_assoc_item(
goal_trait_ref: ty::TraitRef<I>,
trait_assoc_def_id: I::DefId,
impl_def_id: I::ImplId,
) -> Result<Option<I::DefId>, I::ErrorGuaranteed> {
) -> FetchEligibleAssocItemResponse<I> {
self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
}
@@ -6,6 +6,8 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem};
use rustc_type_ir::solve::FetchEligibleAssocItemResponse;
use rustc_type_ir::{
self as ty, FieldInfo, Interner, MayBeErased, NormalizesTo, PredicateKind, Unnormalized,
Upcast as _,
@@ -281,9 +283,9 @@ fn consider_impl_candidate(
goal.predicate.def_id(),
impl_def_id,
) {
Ok(Some(target_item_def_id)) => target_item_def_id,
Ok(None) => {
match ecx.typing_mode() {
FetchEligibleAssocItemResponse::Found(target_item_def_id) => target_item_def_id,
FetchEligibleAssocItemResponse::NotFound(tm) => {
match tm {
// In case the associated item is hidden due to specialization,
// normalizing this associated item is always ambiguous. Treating
// the associated item as rigid would be incomplete and allow for
@@ -304,8 +306,7 @@ fn consider_impl_candidate(
ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis
| ty::TypingMode::ErasedNotCoherence(MayBeErased) => {
| ty::TypingMode::PostAnalysis => {
ecx.structurally_instantiate_normalizes_to_term(
goal,
goal.predicate.alias,
@@ -315,7 +316,11 @@ fn consider_impl_candidate(
}
};
}
Err(guar) => return error_response(ecx, guar),
FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar),
FetchEligibleAssocItemResponse::NotFoundBecauseErased => {
ecx.opaque_accesses.rerun_always("fetch eligible assoc item");
return Err(NoSolution);
}
};
if !cx.has_item_definition(target_item_def_id) {
@@ -9,13 +9,13 @@
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarKind, CanonicalVarValues,
};
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt};
use rustc_infer::traits::solve::Goal;
use rustc_infer::traits::solve::{FetchEligibleAssocItemResponse, Goal};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::{
self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_span::{DUMMY_SP, Span};
use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph};
@@ -283,8 +283,14 @@ fn fetch_eligible_assoc_item(
goal_trait_ref: ty::TraitRef<'tcx>,
trait_assoc_def_id: DefId,
impl_def_id: DefId,
) -> Result<Option<DefId>, ErrorGuaranteed> {
let node_item = specialization_graph::assoc_def(self.tcx, impl_def_id, trait_assoc_def_id)?;
) -> FetchEligibleAssocItemResponse<'tcx> {
let node_item =
match specialization_graph::assoc_def(self.tcx, impl_def_id, trait_assoc_def_id) {
Ok(i) => i,
Err(guar) => return FetchEligibleAssocItemResponse::Err(guar),
};
let typing_mode = self.typing_mode_raw();
let eligible = if node_item.is_final() {
// Non-specializable items are always projectable.
@@ -294,7 +300,7 @@ fn fetch_eligible_assoc_item(
// and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations.
match self.typing_mode_raw() {
match typing_mode {
TypingMode::Coherence
| TypingMode::Analysis { .. }
| TypingMode::Borrowck { .. }
@@ -304,14 +310,19 @@ fn fetch_eligible_assoc_item(
!poly_trait_ref.still_further_specializable()
}
TypingMode::ErasedNotCoherence(MayBeErased) => {
// TODO: make sure this can't be ignored by callers
return Ok(None);
return FetchEligibleAssocItemResponse::NotFoundBecauseErased;
}
}
};
// FIXME: Check for defaultness here may cause diagnostics problems.
if eligible { Ok(Some(node_item.item.def_id)) } else { Ok(None) }
if eligible {
FetchEligibleAssocItemResponse::Found(node_item.item.def_id)
} else {
// We know it's not erased since then we'd have returned in the match above,
// or node_item.final() was true and eligible is always true.
FetchEligibleAssocItemResponse::NotFound(typing_mode.assert_not_erased())
}
}
// FIXME: This actually should destructure the `Result` we get from transmutability and
+17 -7
View File
@@ -13,7 +13,9 @@
use crate::lang_items::SolverTraitLangItem;
use crate::search_graph::PathKind;
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
use crate::{
self as ty, Canonical, CanonicalVarValues, CantBeErased, Interner, TypingMode, Upcast,
};
pub type CanonicalInput<I, T = <I as Interner>::Predicate> =
ty::CanonicalQueryInput<I, QueryInput<I, T>>;
@@ -31,8 +33,8 @@
pub struct NoSolution;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext, GenericTypeVisitable))]
pub enum SmallCopyList<T: Copy + Debug + Hash + Eq> {
Empty,
One([T; 1]),
@@ -108,8 +110,8 @@ fn as_ref(&self) -> &[T] {
///
/// Some variant names contain an `Or` here. They rerun when any of the two conditions applies
#[derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext, GenericTypeVisitable))]
pub enum RerunCondition<I: Interner> {
Never,
@@ -212,8 +214,8 @@ fn might_rerun(&self) -> bool {
}
#[derive_where(Copy, Clone, Debug, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext, GenericTypeVisitable))]
pub struct AccessedOpaques<I: Interner> {
#[type_visitable(ignore)]
#[type_foldable(identity)]
@@ -486,6 +488,14 @@ pub enum BuiltinImplSource {
TraitUpcasting(usize),
}
#[derive_where(Copy, Clone, Debug; I: Interner)]
pub enum FetchEligibleAssocItemResponse<I: Interner> {
Err(I::ErrorGuaranteed),
Found(I::DefId),
NotFound(TypingMode<I, CantBeErased>),
NotFoundBecauseErased,
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]