diff options
Diffstat (limited to 'compiler/rustc_middle/src/query/erase.rs')
-rw-r--r-- | compiler/rustc_middle/src/query/erase.rs | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs new file mode 100644 index 000000000..7d9aea022 --- /dev/null +++ b/compiler/rustc_middle/src/query/erase.rs @@ -0,0 +1,336 @@ +use crate::mir; +use crate::traits; +use crate::ty::{self, Ty}; +use std::mem::{size_of, transmute_copy, MaybeUninit}; + +#[derive(Copy, Clone)] +pub struct Erased<T: Copy> { + // We use `MaybeUninit` here so we can store any value + // in `data` since we aren't actually storing a `T`. + data: MaybeUninit<T>, +} + +pub trait EraseType: Copy { + type Result: Copy; +} + +// Allow `type_alias_bounds` since compilation will fail without `EraseType`. +#[allow(type_alias_bounds)] +pub type Erase<T: EraseType> = Erased<impl Copy>; + +#[inline(always)] +pub fn erase<T: EraseType>(src: T) -> Erase<T> { + // Ensure the sizes match + const { + if std::mem::size_of::<T>() != std::mem::size_of::<T::Result>() { + panic!("size of T must match erased type T::Result") + } + }; + + Erased::<<T as EraseType>::Result> { + // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes. + data: unsafe { transmute_copy(&src) }, + } +} + +/// Restores an erased value. +#[inline(always)] +pub fn restore<T: EraseType>(value: Erase<T>) -> T { + let value: Erased<<T as EraseType>::Result> = value; + // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance + // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of + // the right size. + unsafe { transmute_copy(&value.data) } +} + +impl<T> EraseType for &'_ T { + type Result = [u8; size_of::<*const ()>()]; +} + +impl<T> EraseType for &'_ [T] { + type Result = [u8; size_of::<*const [()]>()]; +} + +impl<T> EraseType for &'_ ty::List<T> { + type Result = [u8; size_of::<*const ()>()]; +} + +impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> { + type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()]; +} + +impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { + type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()]; +} + +impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> { + type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()]; +} + +impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> { + type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()]; +} + +impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> { + type Result = [u8; size_of::< + Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>, + >()]; +} + +impl EraseType for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> { + type Result = + [u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()]; +} + +impl EraseType for Result<Option<ty::Const<'_>>, rustc_errors::ErrorGuaranteed> { + type Result = + [u8; size_of::<Result<Option<ty::Const<'static>>, rustc_errors::ErrorGuaranteed>>()]; +} + +impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> { + type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()]; +} + +impl EraseType for Result<bool, ty::layout::LayoutError<'_>> { + type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()]; +} + +impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> { + type Result = [u8; size_of::< + Result< + rustc_target::abi::TyAndLayout<'static, Ty<'static>>, + ty::layout::LayoutError<'static>, + >, + >()]; +} + +impl EraseType for Result<ty::Const<'_>, mir::interpret::LitToConstError> { + type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()]; +} + +impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError> { + type Result = + [u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()]; +} + +impl EraseType for Result<mir::interpret::ConstAlloc<'_>, mir::interpret::ErrorHandled> { + type Result = [u8; size_of::< + Result<mir::interpret::ConstAlloc<'static>, mir::interpret::ErrorHandled>, + >()]; +} + +impl EraseType for Result<mir::interpret::ConstValue<'_>, mir::interpret::ErrorHandled> { + type Result = [u8; size_of::< + Result<mir::interpret::ConstValue<'static>, mir::interpret::ErrorHandled>, + >()]; +} + +impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> { + type Result = + [u8; size_of::<Result<Option<ty::ValTree<'static>>, mir::interpret::ErrorHandled>>()]; +} + +impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> { + type Result = + [u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()]; +} + +impl<T> EraseType for Option<&'_ T> { + type Result = [u8; size_of::<Option<&'static ()>>()]; +} + +impl<T> EraseType for Option<&'_ [T]> { + type Result = [u8; size_of::<Option<&'static [()]>>()]; +} + +impl EraseType for Option<rustc_middle::hir::Owner<'_>> { + type Result = [u8; size_of::<Option<rustc_middle::hir::Owner<'static>>>()]; +} + +impl EraseType for Option<mir::DestructuredConstant<'_>> { + type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()]; +} + +impl EraseType for Option<ty::EarlyBinder<ty::TraitRef<'_>>> { + type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::TraitRef<'static>>>>()]; +} + +impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> { + type Result = [u8; size_of::<Option<ty::EarlyBinder<Ty<'static>>>>()]; +} + +impl<T> EraseType for rustc_hir::MaybeOwner<&'_ T> { + type Result = [u8; size_of::<rustc_hir::MaybeOwner<&'static ()>>()]; +} + +impl<T: EraseType> EraseType for ty::EarlyBinder<T> { + type Result = T::Result; +} + +impl EraseType for ty::Binder<'_, ty::FnSig<'_>> { + type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()]; +} + +impl<T0, T1> EraseType for (&'_ T0, &'_ T1) { + type Result = [u8; size_of::<(&'static (), &'static ())>()]; +} + +impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) { + type Result = [u8; size_of::<(&'static (), &'static [()])>()]; +} + +macro_rules! trivial { + ($($ty:ty),+ $(,)?) => { + $( + impl EraseType for $ty { + type Result = [u8; size_of::<$ty>()]; + } + )* + } +} + +trivial! { + (), + bool, + Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, + Option<rustc_ast::expand::allocator::AllocatorKind>, + Option<rustc_attr::ConstStability>, + Option<rustc_attr::DefaultBodyStability>, + Option<rustc_attr::Stability>, + Option<rustc_data_structures::svh::Svh>, + Option<rustc_hir::def::DefKind>, + Option<rustc_hir::GeneratorKind>, + Option<rustc_hir::HirId>, + Option<rustc_middle::middle::stability::DeprecationEntry>, + Option<rustc_middle::ty::Destructor>, + Option<rustc_middle::ty::ImplTraitInTraitData>, + Option<rustc_span::def_id::CrateNum>, + Option<rustc_span::def_id::DefId>, + Option<rustc_span::def_id::LocalDefId>, + Option<rustc_span::Span>, + Option<rustc_target::spec::PanicStrategy>, + Option<usize>, + Result<(), rustc_errors::ErrorGuaranteed>, + Result<(), rustc_middle::traits::query::NoSolution>, + Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>, + rustc_ast::expand::allocator::AllocatorKind, + rustc_attr::ConstStability, + rustc_attr::DefaultBodyStability, + rustc_attr::Deprecation, + rustc_attr::Stability, + rustc_data_structures::svh::Svh, + rustc_errors::ErrorGuaranteed, + rustc_hir::Constness, + rustc_hir::def_id::DefId, + rustc_hir::def_id::DefIndex, + rustc_hir::def_id::LocalDefId, + rustc_hir::def::DefKind, + rustc_hir::Defaultness, + rustc_hir::definitions::DefKey, + rustc_hir::GeneratorKind, + rustc_hir::HirId, + rustc_hir::IsAsync, + rustc_hir::ItemLocalId, + rustc_hir::LangItem, + rustc_hir::OwnerId, + rustc_hir::Upvar, + rustc_index::bit_set::FiniteBitSet<u32>, + rustc_middle::middle::dependency_format::Linkage, + rustc_middle::middle::exported_symbols::SymbolExportInfo, + rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, + rustc_middle::middle::resolve_bound_vars::ResolvedArg, + rustc_middle::middle::stability::DeprecationEntry, + rustc_middle::mir::ConstQualifs, + rustc_middle::mir::interpret::AllocId, + rustc_middle::mir::interpret::ErrorHandled, + rustc_middle::mir::interpret::LitToConstError, + rustc_middle::thir::ExprId, + rustc_middle::traits::CodegenObligationError, + rustc_middle::traits::EvaluationResult, + rustc_middle::traits::OverflowError, + rustc_middle::traits::query::NoSolution, + rustc_middle::traits::WellFormedLoc, + rustc_middle::ty::adjustment::CoerceUnsizedInfo, + rustc_middle::ty::AssocItem, + rustc_middle::ty::AssocItemContainer, + rustc_middle::ty::BoundVariableKind, + rustc_middle::ty::DeducedParamAttrs, + rustc_middle::ty::Destructor, + rustc_middle::ty::fast_reject::SimplifiedType, + rustc_middle::ty::ImplPolarity, + rustc_middle::ty::Representability, + rustc_middle::ty::ReprOptions, + rustc_middle::ty::UnusedGenericParams, + rustc_middle::ty::util::AlwaysRequiresDrop, + rustc_middle::ty::Visibility<rustc_span::def_id::DefId>, + rustc_session::config::CrateType, + rustc_session::config::EntryFnType, + rustc_session::config::OptLevel, + rustc_session::config::SymbolManglingVersion, + rustc_session::cstore::CrateDepKind, + rustc_session::cstore::ExternCrate, + rustc_session::cstore::LinkagePreference, + rustc_session::Limits, + rustc_session::lint::LintExpectationId, + rustc_span::def_id::CrateNum, + rustc_span::def_id::DefPathHash, + rustc_span::ExpnHash, + rustc_span::ExpnId, + rustc_span::Span, + rustc_span::Symbol, + rustc_span::symbol::Ident, + rustc_target::spec::PanicStrategy, + rustc_type_ir::Variance, + u32, + usize, +} + +macro_rules! tcx_lifetime { + ($($($fake_path:ident)::+),+ $(,)?) => { + $( + impl<'tcx> EraseType for $($fake_path)::+<'tcx> { + type Result = [u8; size_of::<$($fake_path)::+<'static>>()]; + } + )* + } +} + +tcx_lifetime! { + rustc_middle::hir::Owner, + rustc_middle::middle::exported_symbols::ExportedSymbol, + rustc_middle::mir::ConstantKind, + rustc_middle::mir::DestructuredConstant, + rustc_middle::mir::interpret::ConstAlloc, + rustc_middle::mir::interpret::ConstValue, + rustc_middle::mir::interpret::GlobalId, + rustc_middle::mir::interpret::LitToConstInput, + rustc_middle::traits::ChalkEnvironmentAndGoal, + rustc_middle::traits::query::MethodAutoderefStepsResult, + rustc_middle::traits::query::type_op::AscribeUserType, + rustc_middle::traits::query::type_op::Eq, + rustc_middle::traits::query::type_op::ProvePredicate, + rustc_middle::traits::query::type_op::Subtype, + rustc_middle::ty::AdtDef, + rustc_middle::ty::AliasTy, + rustc_middle::ty::Clause, + rustc_middle::ty::ClosureTypeInfo, + rustc_middle::ty::Const, + rustc_middle::ty::DestructuredConst, + rustc_middle::ty::ExistentialTraitRef, + rustc_middle::ty::FnSig, + rustc_middle::ty::GenericArg, + rustc_middle::ty::GenericPredicates, + rustc_middle::ty::inhabitedness::InhabitedPredicate, + rustc_middle::ty::Instance, + rustc_middle::ty::InstanceDef, + rustc_middle::ty::layout::FnAbiError, + rustc_middle::ty::layout::LayoutError, + rustc_middle::ty::ParamEnv, + rustc_middle::ty::Predicate, + rustc_middle::ty::SymbolName, + rustc_middle::ty::TraitRef, + rustc_middle::ty::Ty, + rustc_middle::ty::UnevaluatedConst, + rustc_middle::ty::ValTree, + rustc_middle::ty::VtblEntry, +} |