Skip to content

Commit 785459d

Browse files
committed
Erase query cache values
1 parent f211da7 commit 785459d

File tree

8 files changed

+329
-49
lines changed

8 files changed

+329
-49
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
use crate::ty;
2+
use std::intrinsics::type_name;
3+
use std::{
4+
fmt,
5+
mem::{size_of, transmute_copy, MaybeUninit},
6+
};
7+
8+
#[derive(Copy, Clone)]
9+
pub struct Erased<T: Copy> {
10+
data: MaybeUninit<T>,
11+
}
12+
13+
impl<T: Copy> fmt::Debug for Erased<T> {
14+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15+
write!(f, "Erased")
16+
}
17+
}
18+
19+
pub trait EraseType: Copy {
20+
type Result: Copy;
21+
}
22+
23+
// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
24+
#[allow(type_alias_bounds)]
25+
pub type Erase<T: Copy + EraseType> = Erased<impl Copy>;
26+
27+
#[inline(always)]
28+
pub fn erase<T: EraseType>(src: T) -> Erase<T> {
29+
assert_eq!(
30+
size_of::<T>(),
31+
size_of::<T::Result>(),
32+
"size of {} must match erased type {}",
33+
type_name::<T>(),
34+
type_name::<T::Result>()
35+
);
36+
Erased::<<T as EraseType>::Result> {
37+
// SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
38+
data: unsafe { transmute_copy(&src) },
39+
}
40+
}
41+
42+
/// Restores an erased value.
43+
#[inline(always)]
44+
pub fn restore<T: EraseType>(value: Erase<T>) -> T {
45+
let value: Erased<<T as EraseType>::Result> = value;
46+
// SAFETY: Due to the use of impl Trait in `Erase` the only way to safetly create an instance
47+
// of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
48+
// the right size.
49+
unsafe { transmute_copy(&value.data) }
50+
}
51+
52+
impl<T> EraseType for &'_ T {
53+
type Result = [u8; size_of::<*const ()>()];
54+
}
55+
56+
impl<T> EraseType for &'_ [T] {
57+
type Result = [u8; size_of::<*const [()]>()];
58+
}
59+
60+
impl<T> EraseType for &'_ ty::List<T> {
61+
type Result = [u8; size_of::<*const ()>()];
62+
}
63+
64+
impl<T: Copy, E: Copy> EraseType for Result<T, E> {
65+
type Result = Self;
66+
}
67+
68+
impl<T: Copy> EraseType for Option<T> {
69+
type Result = Self;
70+
}
71+
72+
impl<T: Copy> EraseType for rustc_hir::MaybeOwner<T> {
73+
type Result = Self;
74+
}
75+
76+
impl<T: Copy> EraseType for ty::Visibility<T> {
77+
type Result = Self;
78+
}
79+
80+
impl<T: Copy> EraseType for ty::Binder<'_, T> {
81+
type Result = Self;
82+
}
83+
84+
impl<T: Copy> EraseType for ty::EarlyBinder<T> {
85+
type Result = Self;
86+
}
87+
88+
impl<T0: Copy, T1: Copy> EraseType for (T0, T1) {
89+
type Result = Self;
90+
}
91+
92+
macro_rules! trivial {
93+
($($ty:ty),+ $(,)?) => {
94+
$(
95+
impl EraseType for $ty {
96+
type Result = [u8; size_of::<$ty>()];
97+
}
98+
)*
99+
}
100+
}
101+
102+
trivial! {
103+
(),
104+
bool,
105+
rustc_ast::expand::allocator::AllocatorKind,
106+
rustc_attr::ConstStability,
107+
rustc_attr::DefaultBodyStability,
108+
rustc_attr::Deprecation,
109+
rustc_attr::Stability,
110+
rustc_data_structures::svh::Svh,
111+
rustc_errors::ErrorGuaranteed,
112+
rustc_hir::Constness,
113+
rustc_hir::def_id::DefId,
114+
rustc_hir::def_id::DefIndex,
115+
rustc_hir::def_id::LocalDefId,
116+
rustc_hir::def::DefKind,
117+
rustc_hir::Defaultness,
118+
rustc_hir::definitions::DefKey,
119+
rustc_hir::GeneratorKind,
120+
rustc_hir::HirId,
121+
rustc_hir::IsAsync,
122+
rustc_hir::ItemLocalId,
123+
rustc_hir::LangItem,
124+
rustc_hir::OwnerId,
125+
rustc_hir::Upvar,
126+
rustc_index::bit_set::FiniteBitSet<u32>,
127+
rustc_middle::metadata::ModChild,
128+
rustc_middle::middle::dependency_format::Linkage,
129+
rustc_middle::middle::exported_symbols::SymbolExportInfo,
130+
rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
131+
rustc_middle::middle::resolve_bound_vars::ResolvedArg,
132+
rustc_middle::middle::stability::DeprecationEntry,
133+
rustc_middle::mir::ConstQualifs,
134+
rustc_middle::mir::interpret::AllocId,
135+
rustc_middle::mir::interpret::ErrorHandled,
136+
rustc_middle::mir::interpret::LitToConstError,
137+
rustc_middle::thir::ExprId,
138+
rustc_middle::traits::CodegenObligationError,
139+
rustc_middle::traits::EvaluationResult,
140+
rustc_middle::traits::OverflowError,
141+
rustc_middle::traits::query::NoSolution,
142+
rustc_middle::traits::WellFormedLoc,
143+
rustc_middle::ty::adjustment::CoerceUnsizedInfo,
144+
rustc_middle::ty::AssocItem,
145+
rustc_middle::ty::AssocItemContainer,
146+
rustc_middle::ty::BoundVariableKind,
147+
rustc_middle::ty::DeducedParamAttrs,
148+
rustc_middle::ty::Destructor,
149+
rustc_middle::ty::fast_reject::SimplifiedType,
150+
rustc_middle::ty::ImplPolarity,
151+
rustc_middle::ty::Representability,
152+
rustc_middle::ty::ReprOptions,
153+
rustc_middle::ty::UnusedGenericParams,
154+
rustc_middle::ty::util::AlwaysRequiresDrop,
155+
rustc_session::config::CrateType,
156+
rustc_session::config::EntryFnType,
157+
rustc_session::config::OptLevel,
158+
rustc_session::config::SymbolManglingVersion,
159+
rustc_session::cstore::CrateDepKind,
160+
rustc_session::cstore::ExternCrate,
161+
rustc_session::cstore::LinkagePreference,
162+
rustc_session::Limits,
163+
rustc_session::lint::LintExpectationId,
164+
rustc_span::def_id::CrateNum,
165+
rustc_span::def_id::DefPathHash,
166+
rustc_span::ExpnHash,
167+
rustc_span::ExpnId,
168+
rustc_span::Span,
169+
rustc_span::Symbol,
170+
rustc_span::symbol::Ident,
171+
rustc_target::spec::PanicStrategy,
172+
rustc_type_ir::Variance,
173+
u32,
174+
usize,
175+
}
176+
177+
macro_rules! tcx_lifetime {
178+
($($($fake_path:ident)::+),+ $(,)?) => {
179+
$(
180+
impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
181+
type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
182+
}
183+
)*
184+
}
185+
}
186+
187+
tcx_lifetime! {
188+
rustc_middle::hir::Owner,
189+
rustc_middle::middle::exported_symbols::ExportedSymbol,
190+
rustc_middle::mir::ConstantKind,
191+
rustc_middle::mir::DestructuredConstant,
192+
rustc_middle::mir::interpret::ConstAlloc,
193+
rustc_middle::mir::interpret::ConstValue,
194+
rustc_middle::mir::interpret::GlobalId,
195+
rustc_middle::mir::interpret::LitToConstInput,
196+
rustc_middle::traits::ChalkEnvironmentAndGoal,
197+
rustc_middle::traits::query::MethodAutoderefStepsResult,
198+
rustc_middle::traits::query::type_op::AscribeUserType,
199+
rustc_middle::traits::query::type_op::Eq,
200+
rustc_middle::traits::query::type_op::ProvePredicate,
201+
rustc_middle::traits::query::type_op::Subtype,
202+
rustc_middle::ty::AdtDef,
203+
rustc_middle::ty::AliasTy,
204+
rustc_middle::ty::Clause,
205+
rustc_middle::ty::ClosureTypeInfo,
206+
rustc_middle::ty::Const,
207+
rustc_middle::ty::DestructuredConst,
208+
rustc_middle::ty::ExistentialTraitRef,
209+
rustc_middle::ty::FnSig,
210+
rustc_middle::ty::GenericArg,
211+
rustc_middle::ty::GenericPredicates,
212+
rustc_middle::ty::inhabitedness::InhabitedPredicate,
213+
rustc_middle::ty::Instance,
214+
rustc_middle::ty::InstanceDef,
215+
rustc_middle::ty::layout::FnAbiError,
216+
rustc_middle::ty::layout::LayoutError,
217+
rustc_middle::ty::ParamEnv,
218+
rustc_middle::ty::Predicate,
219+
rustc_middle::ty::SymbolName,
220+
rustc_middle::ty::TraitRef,
221+
rustc_middle::ty::Ty,
222+
rustc_middle::ty::UnevaluatedConst,
223+
rustc_middle::ty::ValTree,
224+
rustc_middle::ty::VtblEntry,
225+
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use crate::ty::{self, print::describe_as_module, TyCtxt};
88
use rustc_span::def_id::LOCAL_CRATE;
99

10+
pub mod erase;
1011
mod keys;
1112
pub use keys::{AsLocalKey, Key, LocalCrate};
1213

compiler/rustc_middle/src/ty/query.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::mir::interpret::{
1717
};
1818
use crate::mir::interpret::{LitToConstError, LitToConstInput};
1919
use crate::mir::mono::CodegenUnit;
20+
use crate::query::erase::{erase, restore, Erase};
2021
use crate::query::{AsLocalKey, Key};
2122
use crate::thir;
2223
use crate::traits::query::{
@@ -57,6 +58,8 @@ use rustc_hir::hir_id::OwnerId;
5758
use rustc_hir::lang_items::{LangItem, LanguageItems};
5859
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
5960
use rustc_index::vec::IndexVec;
61+
pub(crate) use rustc_query_system::query::QueryJobId;
62+
use rustc_query_system::query::*;
6063
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
6164
use rustc_session::cstore::{CrateDepKind, CrateSource};
6265
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
@@ -66,18 +69,19 @@ use rustc_span::symbol::Symbol;
6669
use rustc_span::{Span, DUMMY_SP};
6770
use rustc_target::abi;
6871
use rustc_target::spec::PanicStrategy;
72+
73+
use std::marker::PhantomData;
6974
use std::mem;
7075
use std::ops::Deref;
7176
use std::path::PathBuf;
7277
use std::sync::Arc;
7378

74-
pub(crate) use rustc_query_system::query::QueryJobId;
75-
use rustc_query_system::query::*;
76-
7779
#[derive(Default)]
7880
pub struct QuerySystem<'tcx> {
7981
pub arenas: QueryArenas<'tcx>,
8082
pub caches: QueryCaches<'tcx>,
83+
// Since we erase query value types we tell the typesystem about them with `PhantomData`.
84+
_phantom_values: QueryPhantomValues<'tcx>,
8185
}
8286

8387
#[derive(Copy, Clone)]
@@ -263,8 +267,8 @@ macro_rules! define_callbacks {
263267
pub fn $name<'tcx>(
264268
_tcx: TyCtxt<'tcx>,
265269
value: query_provided::$name<'tcx>,
266-
) -> query_values::$name<'tcx> {
267-
query_if_arena!([$($modifiers)*]
270+
) -> Erase<query_values::$name<'tcx>> {
271+
erase(query_if_arena!([$($modifiers)*]
268272
{
269273
if mem::needs_drop::<query_provided::$name<'tcx>>() {
270274
&*_tcx.query_system.arenas.$name.alloc(value)
@@ -273,7 +277,7 @@ macro_rules! define_callbacks {
273277
}
274278
}
275279
(value)
276-
)
280+
))
277281
}
278282
)*
279283
}
@@ -282,7 +286,7 @@ macro_rules! define_callbacks {
282286
use super::*;
283287

284288
$(
285-
pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
289+
pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
286290
)*
287291
}
288292

@@ -334,6 +338,11 @@ macro_rules! define_callbacks {
334338
}
335339
}
336340

341+
#[derive(Default)]
342+
pub struct QueryPhantomValues<'tcx> {
343+
$($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
344+
}
345+
337346
#[derive(Default)]
338347
pub struct QueryCaches<'tcx> {
339348
$($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
@@ -395,10 +404,10 @@ macro_rules! define_callbacks {
395404
let key = key.into_query_param();
396405
opt_remap_env_constness!([$($modifiers)*][key]);
397406

398-
match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
407+
restore::<$V>(match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
399408
Some(value) => value,
400409
None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
401-
}
410+
})
402411
})*
403412
}
404413

@@ -459,7 +468,7 @@ macro_rules! define_callbacks {
459468
span: Span,
460469
key: query_keys::$name<'tcx>,
461470
mode: QueryMode,
462-
) -> Option<$V>;)*
471+
) -> Option<Erase<$V>>;)*
463472
}
464473
};
465474
}
@@ -486,7 +495,8 @@ macro_rules! define_feedable {
486495
opt_remap_env_constness!([$($modifiers)*][key]);
487496

488497
let tcx = self.tcx;
489-
let value = query_provided_to_value::$name(tcx, value);
498+
let erased = query_provided_to_value::$name(tcx, value);
499+
let value = restore::<$V>(erased);
490500
let cache = &tcx.query_system.caches.$name;
491501

492502
match try_get_cached(tcx, cache, &key) {
@@ -505,7 +515,7 @@ macro_rules! define_feedable {
505515
&value,
506516
hash_result!([$($modifiers)*]),
507517
);
508-
cache.complete(key, value, dep_node_index);
518+
cache.complete(key, erased, dep_node_index);
509519
value
510520
}
511521
}

compiler/rustc_query_impl/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@ extern crate rustc_middle;
1818

1919
use rustc_data_structures::sync::AtomicU64;
2020
use rustc_middle::arena::Arena;
21-
use rustc_middle::dep_graph::{self, DepKindStruct};
21+
use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
22+
use rustc_middle::query::erase::{erase, restore, Erase};
2223
use rustc_middle::query::AsLocalKey;
2324
use rustc_middle::ty::query::{
2425
query_keys, query_provided, query_provided_to_value, query_storage, query_values,
2526
};
2627
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
2728
use rustc_middle::ty::TyCtxt;
29+
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
30+
use rustc_query_system::Value;
2831
use rustc_span::Span;
2932

3033
#[macro_use]
3134
mod plumbing;
3235
pub use plumbing::QueryCtxt;
33-
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
3436
use rustc_query_system::query::*;
3537
#[cfg(parallel_compiler)]
3638
pub use rustc_query_system::query::{deadlock, QueryContext};
@@ -43,6 +45,14 @@ pub use on_disk_cache::OnDiskCache;
4345
mod profiling_support;
4446
pub use self::profiling_support::alloc_self_profile_query_strings;
4547

48+
trait QueryToConfig<'tcx>: 'tcx {
49+
type Value;
50+
type Config: QueryConfig<QueryCtxt<'tcx>>;
51+
52+
fn config(qcx: QueryCtxt<'tcx>) -> Self::Config;
53+
fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::Value;
54+
}
55+
4656
rustc_query_append! { define_queries! }
4757

4858
impl<'tcx> Queries<'tcx> {

0 commit comments

Comments
 (0)