rustc_middle/query/
erase.rs

1use std::intrinsics::transmute_unchecked;
2use std::mem::MaybeUninit;
3
4use rustc_span::ErrorGuaranteed;
5
6use crate::query::CyclePlaceholder;
7use crate::ty::adjustment::CoerceUnsizedInfo;
8use crate::ty::{self, Ty};
9use crate::{mir, traits};
10
11#[derive(Copy, Clone)]
12pub struct Erased<T: Copy> {
13    // We use `MaybeUninit` here so we can store any value
14    // in `data` since we aren't actually storing a `T`.
15    data: MaybeUninit<T>,
16}
17
18pub trait EraseType: Copy {
19    type Result: Copy;
20}
21
22// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
23#[allow(type_alias_bounds)]
24pub type Erase<T: EraseType> = Erased<impl Copy>;
25
26#[inline(always)]
27#[cfg_attr(not(bootstrap), define_opaque(Erase))]
28pub fn erase<T: EraseType>(src: T) -> Erase<T> {
29    // Ensure the sizes match
30    const {
31        if size_of::<T>() != size_of::<T::Result>() {
32            panic!("size of T must match erased type T::Result")
33        }
34    };
35
36    Erased::<<T as EraseType>::Result> {
37        // `transmute_unchecked` is needed here because it does not have `transmute`'s size check
38        // (and thus allows to transmute between `T` and `MaybeUninit<T::Result>`) (we do the size
39        // check ourselves in the `const` block above).
40        //
41        // `transmute_copy` is also commonly used for this (and it would work here since
42        // `EraseType: Copy`), but `transmute_unchecked` better explains the intent.
43        //
44        // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
45        data: unsafe { transmute_unchecked::<T, MaybeUninit<T::Result>>(src) },
46    }
47}
48
49/// Restores an erased value.
50#[inline(always)]
51#[cfg_attr(not(bootstrap), define_opaque(Erase))]
52pub fn restore<T: EraseType>(value: Erase<T>) -> T {
53    let value: Erased<<T as EraseType>::Result> = value;
54    // See comment in `erase` for why we use `transmute_unchecked`.
55    //
56    // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
57    // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
58    // the right size.
59    unsafe { transmute_unchecked::<MaybeUninit<T::Result>, T>(value.data) }
60}
61
62impl<T> EraseType for &'_ T {
63    type Result = [u8; size_of::<&'static ()>()];
64}
65
66impl<T> EraseType for &'_ [T] {
67    type Result = [u8; size_of::<&'static [()]>()];
68}
69
70impl<T> EraseType for &'_ ty::List<T> {
71    type Result = [u8; size_of::<&'static ty::List<()>>()];
72}
73
74impl<T> EraseType for &'_ ty::ListWithCachedTypeInfo<T> {
75    type Result = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()];
76}
77
78impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
79    type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
80}
81
82impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
83    type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
84}
85
86impl<T> EraseType for Result<&'_ [T], traits::query::NoSolution> {
87    type Result = [u8; size_of::<Result<&'static [()], traits::query::NoSolution>>()];
88}
89
90impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
91    type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
92}
93
94impl<T> EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
95    type Result = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
96}
97
98impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
99    type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
100}
101
102impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
103    type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
104}
105
106impl<T> EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> {
107    type Result = [u8; size_of::<
108        Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>,
109    >()];
110}
111
112impl EraseType for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
113    type Result =
114        [u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()];
115}
116
117impl EraseType for Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed> {
118    type Result = [u8; size_of::<Result<CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed>>()];
119}
120
121impl EraseType
122    for Result<Option<ty::EarlyBinder<'_, ty::Const<'_>>>, rustc_errors::ErrorGuaranteed>
123{
124    type Result = [u8; size_of::<
125        Result<Option<ty::EarlyBinder<'static, ty::Const<'static>>>, rustc_errors::ErrorGuaranteed>,
126    >()];
127}
128
129impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
130    type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
131}
132
133impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> {
134    type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
135}
136
137impl EraseType for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> {
138    type Result = [u8; size_of::<
139        Result<
140            rustc_abi::TyAndLayout<'static, Ty<'static>>,
141            &'static ty::layout::LayoutError<'static>,
142        >,
143    >()];
144}
145
146impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
147    type Result = [u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()];
148}
149
150impl EraseType for Result<mir::ConstValue<'_>, mir::interpret::ErrorHandled> {
151    type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()];
152}
153
154impl EraseType for Result<Result<ty::ValTree<'_>, Ty<'_>>, mir::interpret::ErrorHandled> {
155    type Result = [u8; size_of::<
156        Result<Result<ty::ValTree<'static>, Ty<'static>>, mir::interpret::ErrorHandled>,
157    >()];
158}
159
160impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
161    type Result =
162        [u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
163}
164
165impl EraseType for Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
166    type Result = [u8; size_of::<Result<ty::EarlyBinder<'static, Ty<'_>>, CyclePlaceholder>>()];
167}
168
169impl<T> EraseType for Option<&'_ T> {
170    type Result = [u8; size_of::<Option<&'static ()>>()];
171}
172
173impl<T> EraseType for Option<&'_ [T]> {
174    type Result = [u8; size_of::<Option<&'static [()]>>()];
175}
176
177impl EraseType for Option<mir::DestructuredConstant<'_>> {
178    type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
179}
180
181impl EraseType for Option<ty::ImplTraitHeader<'_>> {
182    type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()];
183}
184
185impl EraseType for Option<ty::EarlyBinder<'_, Ty<'_>>> {
186    type Result = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
187}
188
189impl EraseType for rustc_hir::MaybeOwner<'_> {
190    type Result = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
191}
192
193impl<T: EraseType> EraseType for ty::EarlyBinder<'_, T> {
194    type Result = T::Result;
195}
196
197impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
198    type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
199}
200
201impl EraseType for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
202    type Result = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
203}
204
205impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
206    type Result = [u8; size_of::<(&'static (), &'static ())>()];
207}
208
209impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
210    type Result = [u8; size_of::<(&'static (), &'static [()])>()];
211}
212
213impl<T0, T1> EraseType for (&'_ [T0], &'_ [T1]) {
214    type Result = [u8; size_of::<(&'static [()], &'static [()])>()];
215}
216
217impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
218    type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
219}
220
221macro_rules! trivial {
222    ($($ty:ty),+ $(,)?) => {
223        $(
224            impl EraseType for $ty {
225                type Result = [u8; size_of::<$ty>()];
226            }
227        )*
228    }
229}
230
231trivial! {
232    (),
233    bool,
234    Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
235    Option<rustc_ast::expand::allocator::AllocatorKind>,
236    Option<rustc_attr_data_structures::ConstStability>,
237    Option<rustc_attr_data_structures::DefaultBodyStability>,
238    Option<rustc_attr_data_structures::Stability>,
239    Option<rustc_data_structures::svh::Svh>,
240    Option<rustc_hir::def::DefKind>,
241    Option<rustc_hir::CoroutineKind>,
242    Option<rustc_hir::HirId>,
243    Option<rustc_middle::middle::stability::DeprecationEntry>,
244    Option<rustc_middle::ty::AsyncDestructor>,
245    Option<rustc_middle::ty::Destructor>,
246    Option<rustc_middle::ty::ImplTraitInTraitData>,
247    Option<rustc_middle::ty::ScalarInt>,
248    Option<rustc_span::def_id::CrateNum>,
249    Option<rustc_span::def_id::DefId>,
250    Option<rustc_span::def_id::LocalDefId>,
251    Option<rustc_span::Span>,
252    Option<rustc_abi::FieldIdx>,
253    Option<rustc_target::spec::PanicStrategy>,
254    Option<usize>,
255    Option<rustc_middle::ty::IntrinsicDef>,
256    Result<(), rustc_errors::ErrorGuaranteed>,
257    Result<(), rustc_middle::traits::query::NoSolution>,
258    Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
259    rustc_abi::ReprOptions,
260    rustc_ast::expand::allocator::AllocatorKind,
261    rustc_attr_data_structures::ConstStability,
262    rustc_attr_data_structures::DefaultBodyStability,
263    rustc_attr_data_structures::Deprecation,
264    rustc_attr_data_structures::Stability,
265    rustc_data_structures::svh::Svh,
266    rustc_errors::ErrorGuaranteed,
267    rustc_hir::Constness,
268    rustc_hir::def_id::DefId,
269    rustc_hir::def_id::DefIndex,
270    rustc_hir::def_id::LocalDefId,
271    rustc_hir::def_id::LocalModDefId,
272    rustc_hir::def::DefKind,
273    rustc_hir::Defaultness,
274    rustc_hir::definitions::DefKey,
275    rustc_hir::CoroutineKind,
276    rustc_hir::HirId,
277    rustc_hir::IsAsync,
278    rustc_hir::ItemLocalId,
279    rustc_hir::LangItem,
280    rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
281    rustc_hir::OwnerId,
282    rustc_hir::Upvar,
283    rustc_index::bit_set::FiniteBitSet<u32>,
284    rustc_middle::middle::dependency_format::Linkage,
285    rustc_middle::middle::exported_symbols::SymbolExportInfo,
286    rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
287    rustc_middle::middle::resolve_bound_vars::ResolvedArg,
288    rustc_middle::middle::stability::DeprecationEntry,
289    rustc_middle::mir::ConstQualifs,
290    rustc_middle::mir::interpret::AllocId,
291    rustc_middle::mir::interpret::CtfeProvenance,
292    rustc_middle::mir::interpret::ErrorHandled,
293    rustc_middle::thir::ExprId,
294    rustc_middle::traits::CodegenObligationError,
295    rustc_middle::traits::EvaluationResult,
296    rustc_middle::traits::OverflowError,
297    rustc_middle::traits::query::NoSolution,
298    rustc_middle::traits::WellFormedLoc,
299    rustc_middle::ty::adjustment::CoerceUnsizedInfo,
300    rustc_middle::ty::AssocItem,
301    rustc_middle::ty::AssocItemContainer,
302    rustc_middle::ty::Asyncness,
303    rustc_middle::ty::AsyncDestructor,
304    rustc_middle::ty::BoundVariableKind,
305    rustc_middle::ty::DeducedParamAttrs,
306    rustc_middle::ty::Destructor,
307    rustc_middle::ty::fast_reject::SimplifiedType,
308    rustc_middle::ty::ImplPolarity,
309    rustc_middle::ty::Representability,
310    rustc_middle::ty::UnusedGenericParams,
311    rustc_middle::ty::util::AlwaysRequiresDrop,
312    rustc_middle::ty::Visibility<rustc_span::def_id::DefId>,
313    rustc_session::config::CrateType,
314    rustc_session::config::EntryFnType,
315    rustc_session::config::OptLevel,
316    rustc_session::config::SymbolManglingVersion,
317    rustc_session::cstore::CrateDepKind,
318    rustc_session::cstore::ExternCrate,
319    rustc_session::cstore::LinkagePreference,
320    rustc_session::Limits,
321    rustc_session::lint::LintExpectationId,
322    rustc_span::def_id::CrateNum,
323    rustc_span::def_id::DefPathHash,
324    rustc_span::ExpnHash,
325    rustc_span::ExpnId,
326    rustc_span::Span,
327    rustc_span::Symbol,
328    rustc_span::Ident,
329    rustc_target::spec::PanicStrategy,
330    rustc_type_ir::Variance,
331    u32,
332    usize,
333}
334
335macro_rules! tcx_lifetime {
336    ($($($fake_path:ident)::+),+ $(,)?) => {
337        $(
338            impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
339                type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
340            }
341        )*
342    }
343}
344
345tcx_lifetime! {
346    rustc_middle::middle::exported_symbols::ExportedSymbol,
347    rustc_middle::mir::Const,
348    rustc_middle::mir::DestructuredConstant,
349    rustc_middle::mir::ConstAlloc,
350    rustc_middle::mir::ConstValue,
351    rustc_middle::mir::interpret::GlobalId,
352    rustc_middle::mir::interpret::LitToConstInput,
353    rustc_middle::mir::interpret::EvalStaticInitializerRawResult,
354    rustc_middle::mir::mono::MonoItemPartitions,
355    rustc_middle::traits::query::MethodAutoderefStepsResult,
356    rustc_middle::traits::query::type_op::AscribeUserType,
357    rustc_middle::traits::query::type_op::Eq,
358    rustc_middle::traits::query::type_op::ProvePredicate,
359    rustc_middle::traits::query::type_op::Subtype,
360    rustc_middle::ty::AdtDef,
361    rustc_middle::ty::AliasTy,
362    rustc_middle::ty::ClauseKind,
363    rustc_middle::ty::ClosureTypeInfo,
364    rustc_middle::ty::Const,
365    rustc_middle::ty::DestructuredConst,
366    rustc_middle::ty::ExistentialTraitRef,
367    rustc_middle::ty::FnSig,
368    rustc_middle::ty::GenericArg,
369    rustc_middle::ty::GenericPredicates,
370    rustc_middle::ty::ConstConditions,
371    rustc_middle::ty::inhabitedness::InhabitedPredicate,
372    rustc_middle::ty::Instance,
373    rustc_middle::ty::InstanceKind,
374    rustc_middle::ty::layout::FnAbiError,
375    rustc_middle::ty::layout::LayoutError,
376    rustc_middle::ty::ParamEnv,
377    rustc_middle::ty::Predicate,
378    rustc_middle::ty::SymbolName,
379    rustc_middle::ty::TraitRef,
380    rustc_middle::ty::Ty,
381    rustc_middle::ty::UnevaluatedConst,
382    rustc_middle::ty::ValTree,
383    rustc_middle::ty::VtblEntry,
384}