include ParamEnv in projection cache key

This commit is contained in:
Lukas Markeffsky 2024-04-20 16:42:18 +02:00
parent 584f183dc0
commit 88b10c1162
4 changed files with 19 additions and 13 deletions

View File

@ -78,11 +78,12 @@ pub struct ProjectionCacheStorage<'tcx> {
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct ProjectionCacheKey<'tcx> {
ty: ty::AliasTy<'tcx>,
param_env: ty::ParamEnv<'tcx>,
}
impl<'tcx> ProjectionCacheKey<'tcx> {
pub fn new(ty: ty::AliasTy<'tcx>) -> Self {
Self { ty }
pub fn new(ty: ty::AliasTy<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
Self { ty, param_env }
}
}

View File

@ -758,9 +758,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) {
if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(
if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
&mut self.selcx,
project_obligation.predicate,
&project_obligation,
) {
// If `predicate_must_hold_considering_regions` succeeds, then we've
// evaluated all sub-obligations. We can therefore mark the 'root'

View File

@ -344,7 +344,7 @@ pub(super) fn opt_normalize_projection_type<'a, 'b, 'tcx>(
let use_cache = !selcx.is_intercrate();
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
let cache_key = ProjectionCacheKey::new(projection_ty);
let cache_key = ProjectionCacheKey::new(projection_ty, param_env);
// FIXME(#20304) For now, I am caching here, which is good, but it
// means we don't capture the type variables that are created in
@ -2105,27 +2105,28 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
}
pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
fn from_poly_projection_predicate(
fn from_poly_projection_obligation(
selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: ty::PolyProjectionPredicate<'tcx>,
obligation: &PolyProjectionObligation<'tcx>,
) -> Option<Self>;
}
impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
fn from_poly_projection_predicate(
fn from_poly_projection_obligation(
selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: ty::PolyProjectionPredicate<'tcx>,
obligation: &PolyProjectionObligation<'tcx>,
) -> Option<Self> {
let infcx = selcx.infcx;
// We don't do cross-snapshot caching of obligations with escaping regions,
// so there's no cache key to use
predicate.no_bound_vars().map(|predicate| {
obligation.predicate.no_bound_vars().map(|predicate| {
ProjectionCacheKey::new(
// We don't attempt to match up with a specific type-variable state
// from a specific call to `opt_normalize_projection_type` - if
// there's no precise match, the original cache entry is "stranded"
// anyway.
infcx.resolve_vars_if_possible(predicate.projection_ty),
obligation.param_env,
)
})
}

View File

@ -815,7 +815,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `EvaluatedToOkModuloRegions`), and skip re-evaluating the
// sub-obligations.
if let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(self, data)
ProjectionCacheKey::from_poly_projection_obligation(
self,
&project_obligation,
)
{
if let Some(cached_res) = self
.infcx
@ -844,8 +847,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&& (eval_rslt == EvaluatedToOk
|| eval_rslt == EvaluatedToOkModuloRegions)
&& let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(
self, data,
ProjectionCacheKey::from_poly_projection_obligation(
self,
&project_obligation,
)
{
// If the result is something that we can cache, then mark this