about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-04-02 13:07:13 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2024-04-08 15:08:06 +0000
commitdc97b1eb587fe2db207bfe8c2e914034ab9b9306 (patch)
tree368577450fda42d73eb32d308388fec3a3a594a6
parentc8dfb594061d129e3c7cef7cf4b15ab3c0ab5931 (diff)
downloadrust-dc97b1eb587fe2db207bfe8c2e914034ab9b9306.tar.gz
rust-dc97b1eb587fe2db207bfe8c2e914034ab9b9306.zip
Ensure the canonical_param_env_cache does not contain inconsistent information about the defining anchor
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs8
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs15
-rw-r--r--tests/ui/impl-trait/different_where_bounds.rs27
3 files changed, 43 insertions, 7 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 9986fdfd15d..2cbf32dca98 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -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,
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index fac132686f8..62d7b7c28d1 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -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)));
diff --git a/tests/ui/impl-trait/different_where_bounds.rs b/tests/ui/impl-trait/different_where_bounds.rs
new file mode 100644
index 00000000000..87ae6db2822
--- /dev/null
+++ b/tests/ui/impl-trait/different_where_bounds.rs
@@ -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() {}