1 #![feature(alloc_layout_extra, decl_macro, iterator_try_reduce, never_type)]
2 #![allow(dead_code, unused_variables)]
3 #![deny(rustc::untranslatable_diagnostic)]
4 #![deny(rustc::diagnostic_outside_of_impl)]
9 pub(crate) use rustc_data_structures
::fx
::{FxIndexMap as Map, FxIndexSet as Set}
;
11 pub(crate) mod layout
;
12 pub(crate) mod maybe_transmutable
;
22 /// The type encodes answers to the question: "Are these types transmutable?"
23 #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
28 /// `Src` is transmutable into `Dst`.
31 /// `Src` is NOT transmutable into `Dst`.
34 /// `Src` is transmutable into `Dst`, if `src` is transmutable into `dst`.
35 IfTransmutable { src: R, dst: R }
,
37 /// `Src` is transmutable into `Dst`, if all of the enclosed requirements are met.
38 IfAll(Vec
<Answer
<R
>>),
40 /// `Src` is transmutable into `Dst` if any of the enclosed requirements are met.
41 IfAny(Vec
<Answer
<R
>>),
44 /// Answers: Why wasn't the source type transmutable into the destination type?
45 #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
47 /// The layout of the source type is unspecified.
49 /// The layout of the destination type is unspecified.
51 /// The layout of the destination type is bit-incompatible with the source type.
53 /// There aren't any public constructors for `Dst`.
55 /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized.
59 #[cfg(feature = "rustc")]
63 use rustc_hir
::lang_items
::LangItem
;
64 use rustc_infer
::infer
::InferCtxt
;
65 use rustc_macros
::{TypeFoldable, TypeVisitable}
;
66 use rustc_middle
::traits
::ObligationCause
;
67 use rustc_middle
::ty
::Binder
;
68 use rustc_middle
::ty
::Const
;
69 use rustc_middle
::ty
::ParamEnv
;
70 use rustc_middle
::ty
::Ty
;
71 use rustc_middle
::ty
::TyCtxt
;
73 /// The source and destination types of a transmutation.
74 #[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)]
75 pub struct Types
<'tcx
> {
78 /// The destination type.
82 pub struct TransmuteTypeEnv
<'cx
, 'tcx
> {
83 infcx
: &'cx InferCtxt
<'tcx
>,
86 impl<'cx
, 'tcx
> TransmuteTypeEnv
<'cx
, 'tcx
> {
87 pub fn new(infcx
: &'cx InferCtxt
<'tcx
>) -> Self {
92 pub fn is_transmutable(
94 cause
: ObligationCause
<'tcx
>,
95 src_and_dst
: Binder
<'tcx
, Types
<'tcx
>>,
97 assume
: crate::Assume
,
98 ) -> crate::Answer
<crate::layout
::rustc
::Ref
<'tcx
>> {
99 let src
= src_and_dst
.map_bound(|types
| types
.src
).skip_binder();
100 let dst
= src_and_dst
.map_bound(|types
| types
.dst
).skip_binder();
101 crate::maybe_transmutable
::MaybeTransmutableQuery
::new(
113 /// Constructs an `Assume` from a given const-`Assume`.
114 pub fn from_const
<'tcx
>(
116 param_env
: ParamEnv
<'tcx
>,
119 use rustc_middle
::ty
::ScalarInt
;
120 use rustc_middle
::ty
::TypeVisitable
;
121 use rustc_span
::symbol
::sym
;
123 let c
= c
.eval(tcx
, param_env
);
125 if let Err(err
) = c
.error_reported() {
134 let adt_def
= c
.ty().ty_adt_def()?
;
137 tcx
.require_lang_item(LangItem
::TransmuteOpts
, None
),
139 "The given `Const` was not marked with the `{}` lang item.",
140 LangItem
::TransmuteOpts
.name(),
143 let variant
= adt_def
.non_enum_variant();
144 let fields
= c
.to_valtree().unwrap_branch();
146 let get_field
= |name
| {
147 let (field_idx
, _
) = variant
151 .find(|(_
, field_def
)| name
== field_def
.name
)
152 .expect(&format
!("There were no fields named `{name}`."));
153 fields
[field_idx
].unwrap_leaf() == ScalarInt
::TRUE
157 alignment
: get_field(sym
::alignment
),
158 lifetimes
: get_field(sym
::lifetimes
),
159 safety
: get_field(sym
::safety
),
160 validity
: get_field(sym
::validity
),
166 #[cfg(feature = "rustc")]