rustc_middle/query/
erase.rs

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