Compute transmutability from rustc_target::abi::Layout
In its first step of computing transmutability, `rustc_transmutability` constructs a byte-level representation of type layout (`Tree`). Previously, this representation was computed for ADTs by inspecting the ADT definition and performing our own layout computations. This process was error-prone, verbose, and limited our ability to analyze many types (particularly default-repr types). In this PR, we instead construct `Tree`s from `rustc_target::abi::Layout`s. This helps ensure that layout optimizations are reflected our analyses, and increases the kinds of types we can now analyze, including: - default repr ADTs - transparent unions - `UnsafeCell`-containing types Overall, this PR expands the expressvity of `rustc_transmutability` to be much closer to the transmutability analysis performed by miri. Future PRs will work to close the remaining gaps (e.g., support for `Box`, raw pointers, `NonZero*`, coroutines, etc.).
This commit is contained in:
@@ -33,6 +33,9 @@ mod rustc {
|
||||
use super::*;
|
||||
use crate::layout::tree::rustc::Err;
|
||||
|
||||
use rustc_middle::ty::layout::LayoutCx;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::ParamEnv;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
@@ -43,12 +46,20 @@ mod rustc {
|
||||
pub fn answer(self) -> Answer<<TyCtxt<'tcx> as QueryContext>::Ref> {
|
||||
let Self { src, dst, assume, context } = self;
|
||||
|
||||
let layout_cx = LayoutCx { tcx: context, param_env: ParamEnv::reveal_all() };
|
||||
let layout_of = |ty| {
|
||||
layout_cx
|
||||
.layout_of(ty)
|
||||
.map_err(|_| Err::NotYetSupported)
|
||||
.and_then(|tl| Tree::from_ty(tl, layout_cx))
|
||||
};
|
||||
|
||||
// Convert `src` and `dst` from their rustc representations, to `Tree`-based
|
||||
// representations. If these conversions fail, conclude that the transmutation is
|
||||
// unacceptable; the layouts of both the source and destination types must be
|
||||
// well-defined.
|
||||
let src = Tree::from_ty(src, context);
|
||||
let dst = Tree::from_ty(dst, context);
|
||||
let src = layout_of(src);
|
||||
let dst = layout_of(dst);
|
||||
|
||||
match (src, dst) {
|
||||
(Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => {
|
||||
@@ -86,6 +97,10 @@ where
|
||||
// references.
|
||||
let src = src.prune(&|def| false);
|
||||
|
||||
if src.is_inhabited() && !dst.is_inhabited() {
|
||||
return Answer::No(Reason::DstUninhabited);
|
||||
}
|
||||
|
||||
trace!(?src, "pruned src");
|
||||
|
||||
// Remove all `Def` nodes from `dst`, additionally...
|
||||
|
||||
Reference in New Issue
Block a user