diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 92288c89827..9faa172a497 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -141,7 +141,9 @@ impl FlagComputation { &ty::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {} + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { + self.add_flags(TypeFlags::HAS_TY_FRESH) + } ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { self.add_flags(TypeFlags::HAS_TY_INFER) @@ -278,7 +280,7 @@ impl FlagComputation { ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { - InferConst::Fresh(_) => {} + InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 8fcdf813b41..0dbcd483c45 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -59,6 +59,15 @@ bitflags! { | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits + // We consider 'freshened' types and constants + // to depend on a particular fn. + // The freshening process throws away information, + // which can make things unsuitable for use in a global + // cache. Note that there is no 'fresh lifetime' flag - + // freshening replaces all lifetimes with `ReErased`, + // which is different from how types/const are freshened. + | TypeFlags::HAS_TY_FRESH.bits + | TypeFlags::HAS_CT_FRESH.bits | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; /// Does this have `Projection`? @@ -90,6 +99,12 @@ bitflags! { /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? const STILL_FURTHER_SPECIALIZABLE = 1 << 17; + + /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? + const HAS_TY_FRESH = 1 << 18; + + /// Does this value have `InferConst::Fresh`? + const HAS_CT_FRESH = 1 << 19; } } diff --git a/src/test/ui/traits/issue-84399-bad-fresh-caching.rs b/src/test/ui/traits/issue-84399-bad-fresh-caching.rs new file mode 100644 index 00000000000..1494001564f --- /dev/null +++ b/src/test/ui/traits/issue-84399-bad-fresh-caching.rs @@ -0,0 +1,55 @@ +// compile-flags: --crate-type lib +// check-pass +// +// Regression test for issue #84399 +// Tests that we keep the full `ParamEnv` when +// caching predicates with freshened types in the global cache + +use std::marker::PhantomData; +pub trait Allocator { + type Buffer; +} +pub struct DefaultAllocator; +impl Allocator for DefaultAllocator { + type Buffer = (); +} +pub type Owned = >::Buffer; +pub type MatrixMN = Matrix>; +pub type Matrix4 = Matrix; +pub struct Matrix { + pub data: S, + _phantoms: PhantomData, +} +pub fn set_object_transform(matrix: &Matrix4<()>) { + matrix.js_buffer_view(); +} +pub trait Storable { + type Cell; + fn slice_to_items(_buffer: &()) -> &[Self::Cell] { + unimplemented!() + } +} +pub type Cell = ::Cell; +impl Storable for MatrixMN +where + DefaultAllocator: Allocator, +{ + type Cell = (); +} +pub trait JsBufferView { + fn js_buffer_view(&self) -> usize { + unimplemented!() + } +} +impl JsBufferView for [MatrixMN] +where + DefaultAllocator: Allocator, + MatrixMN: Storable, + [Cell>]: JsBufferView, +{ + fn js_buffer_view(&self) -> usize { + as Storable>::slice_to_items(&()).js_buffer_view() + } +} +impl JsBufferView for [()] {} +impl JsBufferView for MatrixMN where DefaultAllocator: Allocator {}