Ensure the canonical_param_env_cache does not contain inconsistent information about the defining anchor

This commit is contained in:
Oli Scherer 2024-04-02 13:07:13 +00:00
parent c8dfb59406
commit dc97b1eb58
3 changed files with 43 additions and 7 deletions

View File

@ -42,10 +42,9 @@ impl<'tcx> InferCtxt<'tcx> {
V: TypeFoldable<TyCtxt<'tcx>>,
{
let (param_env, value) = value.into_parts();
let param_env = self.tcx.canonical_param_env_cache.get_or_insert(
let mut param_env = self.tcx.canonical_param_env_cache.get_or_insert(
self.tcx,
param_env,
self.defining_opaque_types,
query_state,
|tcx, param_env, query_state| {
// FIXME(#118965): We don't canonicalize the static lifetimes that appear in the
@ -60,6 +59,8 @@ impl<'tcx> InferCtxt<'tcx> {
},
);
param_env.defining_opaque_types = self.defining_opaque_types;
Canonicalizer::canonicalize_with_base(
param_env,
value,
@ -611,6 +612,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
.max()
.unwrap_or(ty::UniverseIndex::ROOT);
assert!(
!infcx.is_some_and(|infcx| infcx.defining_opaque_types != base.defining_opaque_types)
);
Canonical {
max_universe,
variables: canonical_variables,

View File

@ -23,7 +23,6 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_hir::def_id::LocalDefId;
use rustc_macros::HashStable;
use rustc_type_ir::Canonical as IrCanonical;
use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo;
@ -312,7 +311,6 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
key: ty::ParamEnv<'tcx>,
defining_opaque_types: &'tcx ty::List<LocalDefId>,
state: &mut OriginalQueryValues<'tcx>,
canonicalize_op: fn(
TyCtxt<'tcx>,
@ -327,7 +325,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
max_universe: ty::UniverseIndex::ROOT,
variables: List::empty(),
value: key,
defining_opaque_types,
defining_opaque_types: ty::List::empty(),
};
}
@ -338,12 +336,19 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
match self.map.borrow().entry(key) {
Entry::Occupied(e) => {
let (canonical, var_values) = e.get();
if cfg!(debug_assertions) {
let mut state = state.clone();
let rerun_canonical = canonicalize_op(tcx, key, &mut state);
assert_eq!(rerun_canonical, *canonical);
let OriginalQueryValues { var_values: rerun_var_values, universe_map } = state;
assert_eq!(universe_map.len(), 1);
assert_eq!(**var_values, *rerun_var_values);
}
state.var_values.extend_from_slice(var_values);
*canonical
}
Entry::Vacant(e) => {
let mut canonical = canonicalize_op(tcx, key, state);
canonical.defining_opaque_types = defining_opaque_types;
let canonical = canonicalize_op(tcx, key, state);
let OriginalQueryValues { var_values, universe_map } = state;
assert_eq!(universe_map.len(), 1);
e.insert((canonical, tcx.arena.alloc_slice(var_values)));

View File

@ -0,0 +1,27 @@
//! This test checks that the param env canonicalization cache
//! does not end up with inconsistent values.
//@ check-pass
pub fn poison1() -> impl Sized
where
(): 'static,
{
}
pub fn poison2() -> impl Sized
where
(): 'static,
{
define_by_query((poison2, ()));
}
pub fn poison3() -> impl Sized
where
(): 'static,
{
}
trait Query {}
impl<Out, F: Fn() -> Out> Query for (F, Out) {}
fn define_by_query(_: impl Query) {}
fn main() {}