1use tracing::{debug, instrument, trace};
2
3pub(crate) mod query_context;
4#[cfg(test)]
5mod tests;
6
7use crate::layout::{self, Def, Dfa, Reference, Tree, dfa, union};
8use crate::maybe_transmutable::query_context::QueryContext;
9use crate::{Answer, Condition, Map, Reason};
10
11pub(crate) struct MaybeTransmutableQuery<L, C>
12where
13 C: QueryContext,
14{
15 src: L,
16 dst: L,
17 assume: crate::Assume,
18 context: C,
19}
20
21impl<L, C> MaybeTransmutableQuery<L, C>
22where
23 C: QueryContext,
24{
25 pub(crate) fn new(src: L, dst: L, assume: crate::Assume, context: C) -> Self {
26 Self { src, dst, assume, context }
27 }
28}
29
30#[cfg(feature = "rustc")]
31mod rustc {
32 use rustc_middle::ty::layout::LayoutCx;
33 use rustc_middle::ty::{Ty, TyCtxt, TypingEnv};
34
35 use super::*;
36 use crate::layout::tree::rustc::Err;
37
38 impl<'tcx> MaybeTransmutableQuery<Ty<'tcx>, TyCtxt<'tcx>> {
39 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("answer",
"rustc_transmute::maybe_transmutable::rustc",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(41u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable::rustc"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.src)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.dst)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Answer<<TyCtxt<'tcx> as QueryContext>::Region,
<TyCtxt<'tcx> as QueryContext>::Type> = loop {};
return __tracing_attr_fake_return;
}
{
let Self { src, dst, assume, context } = self;
let layout_cx =
LayoutCx::new(context, TypingEnv::fully_monomorphized());
let src = Tree::from_ty(src, layout_cx);
let dst = Tree::from_ty(dst, layout_cx);
match (src, dst) {
(Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => {
Answer::No(Reason::TypeError)
}
(Err(Err::UnknownLayout), _) =>
Answer::No(Reason::SrcLayoutUnknown),
(_, Err(Err::UnknownLayout)) =>
Answer::No(Reason::DstLayoutUnknown),
(Err(Err::NotYetSupported), _) =>
Answer::No(Reason::SrcIsNotYetSupported),
(_, Err(Err::NotYetSupported)) =>
Answer::No(Reason::DstIsNotYetSupported),
(Err(Err::SizeOverflow), _) =>
Answer::No(Reason::SrcSizeOverflow),
(_, Err(Err::SizeOverflow)) =>
Answer::No(Reason::DstSizeOverflow),
(Ok(src), Ok(dst)) =>
MaybeTransmutableQuery {
src,
dst,
assume,
context,
}.answer(),
}
}
}
}#[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
42 pub(crate) fn answer(
43 self,
44 ) -> Answer<<TyCtxt<'tcx> as QueryContext>::Region, <TyCtxt<'tcx> as QueryContext>::Type>
45 {
46 let Self { src, dst, assume, context } = self;
47
48 let layout_cx = LayoutCx::new(context, TypingEnv::fully_monomorphized());
49
50 let src = Tree::from_ty(src, layout_cx);
53 let dst = Tree::from_ty(dst, layout_cx);
54
55 match (src, dst) {
56 (Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => {
57 Answer::No(Reason::TypeError)
58 }
59 (Err(Err::UnknownLayout), _) => Answer::No(Reason::SrcLayoutUnknown),
60 (_, Err(Err::UnknownLayout)) => Answer::No(Reason::DstLayoutUnknown),
61 (Err(Err::NotYetSupported), _) => Answer::No(Reason::SrcIsNotYetSupported),
62 (_, Err(Err::NotYetSupported)) => Answer::No(Reason::DstIsNotYetSupported),
63 (Err(Err::SizeOverflow), _) => Answer::No(Reason::SrcSizeOverflow),
64 (_, Err(Err::SizeOverflow)) => Answer::No(Reason::DstSizeOverflow),
65 (Ok(src), Ok(dst)) => MaybeTransmutableQuery { src, dst, assume, context }.answer(),
66 }
67 }
68 }
69}
70
71impl<C>
72 MaybeTransmutableQuery<
73 Tree<<C as QueryContext>::Def, <C as QueryContext>::Region, <C as QueryContext>::Type>,
74 C,
75 >
76where
77 C: QueryContext,
78{
79 #[inline(always)]
85 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("answer",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(85u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.src)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.dst)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Answer<<C as QueryContext>::Region,
<C as QueryContext>::Type> = loop {};
return __tracing_attr_fake_return;
}
{
let Self { src, dst, assume, context } = self;
let src = src.prune(&|_def| false);
if src.is_inhabited() && !dst.is_inhabited() {
return Answer::No(Reason::DstUninhabited);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:98",
"rustc_transmute::maybe_transmutable",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(98u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("pruned src")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let dst =
if assume.safety {
dst.prune(&|_def| false)
} else { dst.prune(&|def| def.has_safety_invariants()) };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:108",
"rustc_transmute::maybe_transmutable",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(108u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("pruned dst")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let src =
match Dfa::from_tree(src) {
Ok(src) => src,
Err(layout::Uninhabited) => return Answer::Yes,
};
let dst =
match Dfa::from_tree(dst) {
Ok(dst) => dst,
Err(layout::Uninhabited) =>
return Answer::No(Reason::DstMayHaveSafetyInvariants),
};
MaybeTransmutableQuery { src, dst, assume, context }.answer()
}
}
}#[instrument(level = "debug", skip(self), fields(src = ?self.src, dst = ?self.dst))]
86 pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Region, <C as QueryContext>::Type> {
87 let Self { src, dst, assume, context } = self;
88
89 let src = src.prune(&|_def| false);
93
94 if src.is_inhabited() && !dst.is_inhabited() {
95 return Answer::No(Reason::DstUninhabited);
96 }
97
98 trace!(?src, "pruned src");
99
100 let dst = if assume.safety {
103 dst.prune(&|_def| false)
104 } else {
105 dst.prune(&|def| def.has_safety_invariants())
106 };
107
108 trace!(?dst, "pruned dst");
109
110 let src = match Dfa::from_tree(src) {
115 Ok(src) => src,
116 Err(layout::Uninhabited) => return Answer::Yes,
117 };
118
119 let dst = match Dfa::from_tree(dst) {
123 Ok(dst) => dst,
124 Err(layout::Uninhabited) => return Answer::No(Reason::DstMayHaveSafetyInvariants),
125 };
126
127 MaybeTransmutableQuery { src, dst, assume, context }.answer()
128 }
129}
130
131impl<C> MaybeTransmutableQuery<Dfa<<C as QueryContext>::Region, <C as QueryContext>::Type>, C>
132where
133 C: QueryContext,
134{
135 pub(crate) fn answer(self) -> Answer<<C as QueryContext>::Region, <C as QueryContext>::Type> {
137 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:137",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(137u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.src)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(src = ?self.src);
138 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:138",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(138u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.dst)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(dst = ?self.dst);
139 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:139",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(139u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src_transitions_len")
}> =
::tracing::__macro_support::FieldName::new("src_transitions_len");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst_transitions_len")
}> =
::tracing::__macro_support::FieldName::new("dst_transitions_len");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&self.src.transitions.len()
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&self.dst.transitions.len()
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
140 src_transitions_len = self.src.transitions.len(),
141 dst_transitions_len = self.dst.transitions.len()
142 );
143 self.answer_memo(&mut Map::default(), self.src.start, self.dst.start)
144 }
145
146 #[inline(always)]
147 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("answer_memo",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src_state")
}> =
::tracing::__macro_support::FieldName::new("src_state");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst_state")
}> =
::tracing::__macro_support::FieldName::new("dst_state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src_state)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst_state)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Answer<<C as QueryContext>::Region,
<C as QueryContext>::Type> = loop {};
return __tracing_attr_fake_return;
}
{
if let Some(answer) = cache.get(&(src_state, dst_state)) {
answer.clone()
} else {
let answer = self.answer_impl(cache, src_state, dst_state);
if let Some(..) =
cache.insert((src_state, dst_state), answer.clone()) {
{
::core::panicking::panic_fmt(format_args!("failed to correctly cache transmutability"));
}
}
answer
}
}
}
}#[instrument(level = "debug", skip(self, cache))]
148 fn answer_memo(
149 &self,
150 cache: &mut Map<
151 (dfa::State, dfa::State),
152 Answer<<C as QueryContext>::Region, <C as QueryContext>::Type>,
153 >,
154 src_state: dfa::State,
155 dst_state: dfa::State,
156 ) -> Answer<<C as QueryContext>::Region, <C as QueryContext>::Type> {
157 if let Some(answer) = cache.get(&(src_state, dst_state)) {
158 answer.clone()
159 } else {
160 let answer = self.answer_impl(cache, src_state, dst_state);
161 if let Some(..) = cache.insert((src_state, dst_state), answer.clone()) {
162 panic!("failed to correctly cache transmutability")
163 }
164 answer
165 }
166 }
167
168 fn answer_impl(
169 &self,
170 cache: &mut Map<
171 (dfa::State, dfa::State),
172 Answer<<C as QueryContext>::Region, <C as QueryContext>::Type>,
173 >,
174 src_state: dfa::State,
175 dst_state: dfa::State,
176 ) -> Answer<<C as QueryContext>::Region, <C as QueryContext>::Type> {
177 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:177",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(177u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src_state")
}> =
::tracing::__macro_support::FieldName::new("src_state");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst_state")
}> =
::tracing::__macro_support::FieldName::new("dst_state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src_state)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst_state)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?src_state, ?dst_state);
178 if dst_state == self.dst.accept {
179 Answer::Yes
184 } else if src_state == self.src.accept {
185 if let Some(dst_state_prime) = self.dst.get_uninit_edge_dst(dst_state) {
187 self.answer_memo(cache, src_state, dst_state_prime)
188 } else {
189 Answer::No(Reason::DstIsTooBig)
190 }
191 } else {
192 let src_quantifier = if self.assume.validity {
193 Quantifier::ThereExists
197 } else {
198 Quantifier::ForAll
201 };
202
203 let bytes_answer = src_quantifier.apply(
204 union(self.src.bytes_from(src_state), self.dst.bytes_from(dst_state)).filter_map(
205 |(_range, (src_state_prime, dst_state_prime))| {
206 match (src_state_prime, dst_state_prime) {
207 (None, _) => None,
209 (Some(_), None) => Some(Answer::No(Reason::DstIsBitIncompatible)),
211 (Some(src_state_prime), Some(dst_state_prime)) => {
213 Some(self.answer_memo(cache, src_state_prime, dst_state_prime))
214 }
215 }
216 },
217 ),
218 );
219
220 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs:229",
"rustc_transmute::maybe_transmutable",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/923c95cdf5ba65cea505aa2ea829f578e1506ed8/compiler/rustc_transmute/src/maybe_transmutable/mod.rs"),
::tracing_core::__macro_support::Option::Some(229u32),
::tracing_core::__macro_support::Option::Some("rustc_transmute::maybe_transmutable"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bytes_answer")
}> =
::tracing::__macro_support::FieldName::new("bytes_answer");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bytes_answer)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?bytes_answer);
230 match bytes_answer {
231 Answer::No(_) if !self.assume.validity => return bytes_answer,
232 Answer::Yes if self.assume.validity => return bytes_answer,
233 _ => {}
234 };
235
236 let refs_answer = src_quantifier.apply(
237 self.src.refs_from(src_state).map(|(src_ref, src_state_prime)| {
239 Quantifier::ThereExists.apply(self.dst.refs_from(dst_state).map(
241 |(dst_ref, dst_state_prime)| {
242 if !src_ref.is_mut && dst_ref.is_mut {
243 Answer::No(Reason::DstIsMoreUnique)
244 } else if !self.assume.alignment
245 && src_ref.referent_align < dst_ref.referent_align
246 {
247 Answer::No(Reason::DstHasStricterAlignment {
248 src_min_align: src_ref.referent_align,
249 dst_min_align: dst_ref.referent_align,
250 })
251 } else if dst_ref.referent_size > src_ref.referent_size {
252 Answer::No(Reason::DstRefIsTooBig {
253 src: src_ref.referent,
254 src_size: src_ref.referent_size,
255 dst: dst_ref.referent,
256 dst_size: dst_ref.referent_size,
257 })
258 } else {
259 let mut conditions = Vec::with_capacity(4);
260 let mut is_transmutable =
261 |src: Reference<_, _>, dst: Reference<_, _>| {
262 conditions.push(Condition::Transmutable {
263 src: src.referent,
264 dst: dst.referent,
265 });
266 if !self.assume.lifetimes {
267 conditions.push(Condition::Outlives {
268 long: src.region,
269 short: dst.region,
270 });
271 }
272 };
273
274 is_transmutable(src_ref, dst_ref);
275
276 if dst_ref.is_mut {
277 is_transmutable(dst_ref, src_ref);
278 } else {
279 conditions.push(Condition::Immutable { ty: dst_ref.referent });
280 }
281
282 Answer::If(Condition::IfAll(conditions)).and(self.answer_memo(
283 cache,
284 src_state_prime,
285 dst_state_prime,
286 ))
287 }
288 },
289 ))
290 }),
291 );
292
293 if self.assume.validity {
294 bytes_answer.or(refs_answer)
295 } else {
296 bytes_answer.and(refs_answer)
297 }
298 }
299 }
300}
301
302impl<R, T> Answer<R, T> {
303 fn and(self, rhs: Answer<R, T>) -> Answer<R, T> {
305 let lhs = self;
306 match (lhs, rhs) {
307 (Answer::No(Reason::DstIsBitIncompatible), Answer::No(reason))
310 | (Answer::No(reason), Answer::No(_))
311 | (Answer::No(reason), _) | (_, Answer::No(reason)) => Answer::No(reason),
313 (Answer::Yes, other) | (other, Answer::Yes) => other,
315 (Answer::If(Condition::IfAll(mut lhs)), Answer::If(Condition::IfAll(ref mut rhs))) => {
317 lhs.append(rhs);
318 Answer::If(Condition::IfAll(lhs))
319 }
320 (Answer::If(cond), Answer::If(Condition::IfAll(mut conds)))
322 | (Answer::If(Condition::IfAll(mut conds)), Answer::If(cond)) => {
323 conds.push(cond);
324 Answer::If(Condition::IfAll(conds))
325 }
326 (Answer::If(lhs), Answer::If(rhs)) => Answer::If(Condition::IfAll(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[lhs, rhs]))vec![lhs, rhs])),
328 }
329 }
330
331 fn or(self, rhs: Answer<R, T>) -> Answer<R, T> {
336 let lhs = self;
337 match (lhs, rhs) {
338 (Answer::No(Reason::DstIsBitIncompatible), Answer::No(reason))
341 | (Answer::No(reason), Answer::No(_)) => Answer::No(reason),
342 (Answer::No(_), other) | (other, Answer::No(_)) => other.or(Answer::Yes),
344 (Answer::Yes, other) | (other, Answer::Yes) => other,
346 (Answer::If(Condition::IfAny(mut lhs)), Answer::If(Condition::IfAny(ref mut rhs))) => {
348 lhs.append(rhs);
349 Answer::If(Condition::IfAny(lhs))
350 }
351 (Answer::If(cond), Answer::If(Condition::IfAny(mut conds)))
353 | (Answer::If(Condition::IfAny(mut conds)), Answer::If(cond)) => {
354 conds.push(cond);
355 Answer::If(Condition::IfAny(conds))
356 }
357 (Answer::If(lhs), Answer::If(rhs)) => Answer::If(Condition::IfAny(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[lhs, rhs]))vec![lhs, rhs])),
359 }
360 }
361}
362
363enum Quantifier {
364 ThereExists,
365 ForAll,
366}
367
368impl Quantifier {
369 fn apply<R, T, I>(&self, iter: I) -> Answer<R, T>
373 where
374 R: layout::Region,
375 T: layout::Type,
376 I: IntoIterator<Item = Answer<R, T>>,
377 {
378 use std::ops::ControlFlow::{Break, Continue};
379
380 let (init, try_fold_f): (_, fn(_, _) -> _) = match self {
381 Self::ThereExists => {
382 (Answer::No(Reason::DstIsBitIncompatible), |accum: Answer<R, T>, next| match accum
383 .or(next)
384 {
385 Answer::Yes => Break(Answer::Yes),
386 maybe => Continue(maybe),
387 })
388 }
389 Self::ForAll => (Answer::Yes, |accum: Answer<R, T>, next| {
390 let answer = accum.and(next);
391 match answer {
392 Answer::No(_) => Break(answer),
393 maybe => Continue(maybe),
394 }
395 }),
396 };
397
398 let (Continue(result) | Break(result)) = iter.into_iter().try_fold(init, try_fold_f);
399 result
400 }
401}