1 #![feature(alloc_layout_extra)]
2 #![feature(never_type)]
3 #![allow(unused_variables)]
5 pub(crate) use rustc_data_structures
::fx
::{FxIndexMap as Map, FxIndexSet as Set}
;
8 mod maybe_transmutable
;
18 /// Either transmutation is allowed, we have an error, or we have an optional
19 /// Condition that must hold.
20 #[derive(Debug, Hash, Eq, PartialEq, Clone)]
27 /// A condition which must hold for safe transmutation to be possible.
28 #[derive(Debug, Hash, Eq, PartialEq, Clone)]
29 pub enum Condition
<R
> {
30 /// `Src` is transmutable into `Dst`, if `src` is transmutable into `dst`.
31 IfTransmutable { src: R, dst: R }
,
33 /// `Src` is transmutable into `Dst`, if all of the enclosed requirements are met.
34 IfAll(Vec
<Condition
<R
>>),
36 /// `Src` is transmutable into `Dst` if any of the enclosed requirements are met.
37 IfAny(Vec
<Condition
<R
>>),
40 /// Answers "why wasn't the source type transmutable into the destination type?"
41 #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
43 /// The layout of the source type is not yet supported.
45 /// The layout of the destination type is not yet supported.
47 /// The layout of the destination type is bit-incompatible with the source type.
49 /// The destination type is uninhabited.
51 /// The destination type may carry safety invariants.
52 DstMayHaveSafetyInvariants
,
53 /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized.
55 /// A referent of `Dst` is larger than a referent in `Src`.
57 /// The referent of the source type.
59 /// The too-large referent of the destination type.
62 /// Src should have a stricter alignment than Dst, but it does not.
63 DstHasStricterAlignment { src_min_align: usize, dst_min_align: usize }
,
64 /// Can't go from shared pointer to unique pointer
66 /// Encountered a type error
68 /// The layout of src is unknown
70 /// The layout of dst is unknown
72 /// The size of src is overflow
74 /// The size of dst is overflow
78 #[cfg(feature = "rustc")]
82 use rustc_hir
::lang_items
::LangItem
;
83 use rustc_infer
::infer
::InferCtxt
;
84 use rustc_macros
::TypeVisitable
;
85 use rustc_middle
::traits
::ObligationCause
;
86 use rustc_middle
::ty
::Const
;
87 use rustc_middle
::ty
::ParamEnv
;
88 use rustc_middle
::ty
::Ty
;
89 use rustc_middle
::ty
::TyCtxt
;
90 use rustc_middle
::ty
::ValTree
;
91 use rustc_span
::DUMMY_SP
;
93 /// The source and destination types of a transmutation.
94 #[derive(TypeVisitable, Debug, Clone, Copy)]
95 pub struct Types
<'tcx
> {
98 /// The destination type.
102 pub struct TransmuteTypeEnv
<'cx
, 'tcx
> {
103 infcx
: &'cx InferCtxt
<'tcx
>,
106 impl<'cx
, 'tcx
> TransmuteTypeEnv
<'cx
, 'tcx
> {
107 pub fn new(infcx
: &'cx InferCtxt
<'tcx
>) -> Self {
112 pub fn is_transmutable(
114 cause
: ObligationCause
<'tcx
>,
116 assume
: crate::Assume
,
117 ) -> crate::Answer
<crate::layout
::rustc
::Ref
<'tcx
>> {
118 crate::maybe_transmutable
::MaybeTransmutableQuery
::new(
129 /// Constructs an `Assume` from a given const-`Assume`.
130 pub fn from_const
<'tcx
>(
132 param_env
: ParamEnv
<'tcx
>,
135 use rustc_middle
::ty
::ScalarInt
;
136 use rustc_span
::symbol
::sym
;
138 let Ok((ty
, cv
)) = c
.eval(tcx
, param_env
, DUMMY_SP
) else {
147 let adt_def
= ty
.ty_adt_def()?
;
150 tcx
.require_lang_item(LangItem
::TransmuteOpts
, None
),
152 "The given `Const` was not marked with the `{}` lang item.",
153 LangItem
::TransmuteOpts
.name(),
156 let variant
= adt_def
.non_enum_variant();
157 let fields
= match cv
{
158 ValTree
::Branch(branch
) => branch
,
169 let get_field
= |name
| {
170 let (field_idx
, _
) = variant
174 .find(|(_
, field_def
)| name
== field_def
.name
)
175 .unwrap_or_else(|| panic
!("There were no fields named `{name}`."));
176 fields
[field_idx
].unwrap_leaf() == ScalarInt
::TRUE
180 alignment
: get_field(sym
::alignment
),
181 lifetimes
: get_field(sym
::lifetimes
),
182 safety
: get_field(sym
::safety
),
183 validity
: get_field(sym
::validity
),
189 #[cfg(feature = "rustc")]