rustc_middle/query/
erase.rs

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