1#![cfg_attr(test, feature(test))]
11#![feature(option_into_flat_iter)]
12pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set};
15
16pub mod layout;
17mod maybe_transmutable;
18
19#[derive(#[automatically_derived]
impl ::core::marker::Copy for Assume { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Assume { }
#[automatically_derived]
impl ::core::clone::Clone for Assume {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Assume {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f, "Assume",
"alignment", &self.alignment, "lifetimes", &self.lifetimes,
"safety", &self.safety, "validity", &&self.validity)
}
}Debug, #[automatically_derived]
impl ::core::default::Default for Assume {
#[inline]
fn default() -> Self {
Assume {
alignment: ::core::default::Default::default(),
lifetimes: ::core::default::Default::default(),
safety: ::core::default::Default::default(),
validity: ::core::default::Default::default(),
}
}
}Default)]
24pub struct Assume {
25 pub alignment: bool,
26 pub lifetimes: bool,
27 pub safety: bool,
28 pub validity: bool,
29}
30
31#[cfg(feature = "rustc")]
32mod rustc {
33 use rustc_attr_ir::lang_items::LangItem;
34 use rustc_middle::ty::transmute::Answer;
35 use rustc_middle::ty::{Const, Region, Ty, TyCtxt};
36
37 use super::*;
38
39 pub struct TransmuteTypeEnv<'tcx> {
40 tcx: TyCtxt<'tcx>,
41 }
42
43 impl<'tcx> TransmuteTypeEnv<'tcx> {
44 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
45 Self { tcx }
46 }
47
48 pub fn is_transmutable(
49 &mut self,
50 src: Ty<'tcx>,
51 dst: Ty<'tcx>,
52 assume: crate::Assume,
53 ) -> Answer<Region<'tcx>, Ty<'tcx>> {
54 crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, self.tcx)
55 .answer()
56 }
57 }
58
59 impl Assume {
60 pub fn from_const<'tcx>(tcx: TyCtxt<'tcx>, ct: Const<'tcx>) -> Option<Self> {
62 use rustc_middle::ty::ScalarInt;
63 use rustc_span::sym;
64
65 let cv = ct.try_to_value()?;
66 let adt_def = cv.ty.ty_adt_def()?;
67
68 if !tcx.is_lang_item(adt_def.did(), LangItem::TransmuteOpts) {
69 tcx.dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("The given `const` was not marked with the `{0}` lang item.",
LangItem::TransmuteOpts.name()))
})format!(
70 "The given `const` was not marked with the `{}` lang item.",
71 LangItem::TransmuteOpts.name()
72 ));
73 return Some(Self {
74 alignment: true,
75 lifetimes: true,
76 safety: true,
77 validity: true,
78 });
79 }
80
81 let variant = adt_def.non_enum_variant();
82 let fields = cv.to_branch();
83
84 let get_field = |name| {
85 let (field_idx, _) = variant
86 .fields
87 .iter()
88 .enumerate()
89 .find(|(_, field_def)| name == field_def.name)
90 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("There were no fields named `{0}`.",
name));
}panic!("There were no fields named `{name}`."));
91 fields[field_idx].try_to_leaf().map(|leaf| leaf == ScalarInt::TRUE)
92 };
93
94 Some(Self {
95 alignment: get_field(sym::alignment)?,
96 lifetimes: get_field(sym::lifetimes)?,
97 safety: get_field(sym::safety)?,
98 validity: get_field(sym::validity)?,
99 })
100 }
101 }
102}
103
104#[cfg(feature = "rustc")]
105pub use rustc::*;