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)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct ProjectionCacheKey<'tcx> { pub struct ProjectionCacheKey<'tcx> {
ty: ty::AliasTy<'tcx>, ty: ty::AliasTy<'tcx>,
param_env: ty::ParamEnv<'tcx>,
} }
impl<'tcx> ProjectionCacheKey<'tcx> { impl<'tcx> ProjectionCacheKey<'tcx> {
pub fn new(ty: ty::AliasTy<'tcx>) -> Self { pub fn new(ty: ty::AliasTy<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
Self { ty } 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. // no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too. // FIXME: consider caching errors too.
if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) { 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, &mut self.selcx,
project_obligation.predicate, &project_obligation,
) { ) {
// If `predicate_must_hold_considering_regions` succeeds, then we've // If `predicate_must_hold_considering_regions` succeeds, then we've
// evaluated all sub-obligations. We can therefore mark the 'root' // 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 use_cache = !selcx.is_intercrate();
let projection_ty = infcx.resolve_vars_if_possible(projection_ty); 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 // 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 // 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 { pub(crate) trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized {
fn from_poly_projection_predicate( fn from_poly_projection_obligation(
selcx: &mut SelectionContext<'cx, 'tcx>, selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: ty::PolyProjectionPredicate<'tcx>, obligation: &PolyProjectionObligation<'tcx>,
) -> Option<Self>; ) -> Option<Self>;
} }
impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> {
fn from_poly_projection_predicate( fn from_poly_projection_obligation(
selcx: &mut SelectionContext<'cx, 'tcx>, selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: ty::PolyProjectionPredicate<'tcx>, obligation: &PolyProjectionObligation<'tcx>,
) -> Option<Self> { ) -> Option<Self> {
let infcx = selcx.infcx; let infcx = selcx.infcx;
// We don't do cross-snapshot caching of obligations with escaping regions, // We don't do cross-snapshot caching of obligations with escaping regions,
// so there's no cache key to use // so there's no cache key to use
predicate.no_bound_vars().map(|predicate| { obligation.predicate.no_bound_vars().map(|predicate| {
ProjectionCacheKey::new( ProjectionCacheKey::new(
// We don't attempt to match up with a specific type-variable state // We don't attempt to match up with a specific type-variable state
// from a specific call to `opt_normalize_projection_type` - if // from a specific call to `opt_normalize_projection_type` - if
// there's no precise match, the original cache entry is "stranded" // there's no precise match, the original cache entry is "stranded"
// anyway. // anyway.
infcx.resolve_vars_if_possible(predicate.projection_ty), 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 // `EvaluatedToOkModuloRegions`), and skip re-evaluating the
// sub-obligations. // sub-obligations.
if let Some(key) = 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 if let Some(cached_res) = self
.infcx .infcx
@ -844,8 +847,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&& (eval_rslt == EvaluatedToOk && (eval_rslt == EvaluatedToOk
|| eval_rslt == EvaluatedToOkModuloRegions) || eval_rslt == EvaluatedToOkModuloRegions)
&& let Some(key) = && let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate( ProjectionCacheKey::from_poly_projection_obligation(
self, data, self,
&project_obligation,
) )
{ {
// If the result is something that we can cache, then mark this // If the result is something that we can cache, then mark this