Shallowly match opaque key in storage

This commit is contained in:
Michael Goulet 2024-10-12 09:10:04 -04:00
parent 8f8bee4f60
commit 470e9fa1af
2 changed files with 42 additions and 43 deletions

View File

@ -4,6 +4,7 @@ use derive_where::derive_where;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::Relate;
@ -18,9 +19,9 @@ use crate::delegate::SolverDelegate;
use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::inspect::{self, ProofTreeBuilder};
use crate::solve::search_graph::SearchGraph; use crate::solve::search_graph::SearchGraph;
use crate::solve::{ use crate::solve::{
CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
QueryResult, SolverMode, SolverMode,
}; };
pub(super) mod canonical; pub(super) mod canonical;
@ -987,40 +988,22 @@ where
// Do something for each opaque/hidden pair defined with `def_id` in the // Do something for each opaque/hidden pair defined with `def_id` in the
// current inference context. // current inference context.
pub(super) fn unify_existing_opaque_tys( pub(super) fn probe_existing_opaque_ty(
&mut self, &mut self,
param_env: I::ParamEnv,
key: ty::OpaqueTypeKey<I>, key: ty::OpaqueTypeKey<I>,
ty: I::Ty, ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
) -> Vec<CanonicalResponse<I>> { let mut matching =
// FIXME: Super inefficient to be cloning this... self.delegate.clone_opaque_types_for_query_response().into_iter().filter(
let opaques = self.delegate.clone_opaque_types_for_query_response(); |(candidate_key, _)| {
candidate_key.def_id == key.def_id
let mut values = vec![]; && DeepRejectCtxt::relate_rigid_rigid(self.cx())
for (candidate_key, candidate_ty) in opaques { .args_may_unify(candidate_key.args, key.args)
if candidate_key.def_id != key.def_id { },
continue;
}
values.extend(
self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
result: *result,
})
.enter(|ecx| {
for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) {
ecx.eq(param_env, a, b)?;
}
ecx.eq(param_env, candidate_ty, ty)?;
ecx.add_item_bounds_for_hidden_type(
candidate_key.def_id.into(),
candidate_key.args,
param_env,
candidate_ty,
);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}),
); );
} let first = matching.next();
values let second = matching.next();
assert_eq!(second, None);
first
} }
// Try to evaluate a const, or return `None` if the const is too generic. // Try to evaluate a const, or return `None` if the const is too generic.

View File

@ -7,7 +7,9 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner}; use rustc_type_ir::{self as ty, Interner};
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; use crate::solve::{
Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect,
};
impl<D, I> EvalCtxt<'_, D> impl<D, I> EvalCtxt<'_, D>
where where
@ -52,14 +54,28 @@ where
// //
// If that fails, we insert `expected` as a new hidden type instead of // If that fails, we insert `expected` as a new hidden type instead of
// eagerly emitting an error. // eagerly emitting an error.
let matches = let existing = self.probe_existing_opaque_ty(opaque_type_key);
self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected); if let Some((candidate_key, candidate_ty)) = existing {
if !matches.is_empty() { return self
if let Some(response) = self.try_merge_responses(&matches) { .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
return Ok(response); result: *result,
} else { })
return self.flounder(&matches); .enter(|ecx| {
} for (a, b) in std::iter::zip(
candidate_key.args.iter(),
opaque_type_key.args.iter(),
) {
ecx.eq(goal.param_env, a, b)?;
}
ecx.eq(goal.param_env, candidate_ty, expected)?;
ecx.add_item_bounds_for_hidden_type(
candidate_key.def_id.into(),
candidate_key.args,
goal.param_env,
candidate_ty,
);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
});
} }
// Otherwise, define a new opaque type // Otherwise, define a new opaque type