]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_transmute/src/lib.rs
Rollup merge of #99573 - tbodt:stabilize-backtrace, r=yaahc
[rust.git] / compiler / rustc_transmute / src / lib.rs
1 #![feature(
2     alloc_layout_extra,
3     control_flow_enum,
4     decl_macro,
5     iterator_try_reduce,
6     never_type,
7     result_into_ok_or_err
8 )]
9 #![allow(dead_code, unused_variables)]
10
11 #[macro_use]
12 extern crate tracing;
13
14 #[cfg(feature = "rustc")]
15 pub(crate) use rustc_data_structures::fx::{FxHashMap as Map, FxHashSet as Set};
16
17 #[cfg(not(feature = "rustc"))]
18 pub(crate) use std::collections::{HashMap as Map, HashSet as Set};
19
20 pub(crate) mod layout;
21 pub(crate) mod maybe_transmutable;
22
23 #[derive(Default)]
24 pub struct Assume {
25     pub alignment: bool,
26     pub lifetimes: bool,
27     pub validity: bool,
28     pub visibility: bool,
29 }
30
31 /// The type encodes answers to the question: "Are these types transmutable?"
32 #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
33 pub enum Answer<R>
34 where
35     R: layout::Ref,
36 {
37     /// `Src` is transmutable into `Dst`.
38     Yes,
39
40     /// `Src` is NOT transmutable into `Dst`.
41     No(Reason),
42
43     /// `Src` is transmutable into `Dst`, if `src` is transmutable into `dst`.
44     IfTransmutable { src: R, dst: R },
45
46     /// `Src` is transmutable into `Dst`, if all of the enclosed requirements are met.
47     IfAll(Vec<Answer<R>>),
48
49     /// `Src` is transmutable into `Dst` if any of the enclosed requirements are met.
50     IfAny(Vec<Answer<R>>),
51 }
52
53 /// Answers: Why wasn't the source type transmutable into the destination type?
54 #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)]
55 pub enum Reason {
56     /// The layout of the source type is unspecified.
57     SrcIsUnspecified,
58     /// The layout of the destination type is unspecified.
59     DstIsUnspecified,
60     /// The layout of the destination type is bit-incompatible with the source type.
61     DstIsBitIncompatible,
62     /// There aren't any public constructors for `Dst`.
63     DstIsPrivate,
64     /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized.
65     DstIsTooBig,
66 }
67
68 #[cfg(feature = "rustc")]
69 mod rustc {
70     use rustc_infer::infer::InferCtxt;
71     use rustc_macros::{TypeFoldable, TypeVisitable};
72     use rustc_middle::traits::ObligationCause;
73     use rustc_middle::ty::Binder;
74     use rustc_middle::ty::Ty;
75
76     /// The source and destination types of a transmutation.
77     #[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)]
78     pub struct Types<'tcx> {
79         /// The source type.
80         pub src: Ty<'tcx>,
81         /// The destination type.
82         pub dst: Ty<'tcx>,
83     }
84
85     pub struct TransmuteTypeEnv<'cx, 'tcx> {
86         infcx: &'cx InferCtxt<'cx, 'tcx>,
87     }
88
89     impl<'cx, 'tcx> TransmuteTypeEnv<'cx, 'tcx> {
90         pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> Self {
91             Self { infcx }
92         }
93
94         #[allow(unused)]
95         pub fn is_transmutable(
96             &mut self,
97             cause: ObligationCause<'tcx>,
98             src_and_dst: Binder<'tcx, Types<'tcx>>,
99             scope: Ty<'tcx>,
100             assume: crate::Assume,
101         ) -> crate::Answer<crate::layout::rustc::Ref<'tcx>> {
102             let src = src_and_dst.map_bound(|types| types.src).skip_binder();
103             let dst = src_and_dst.map_bound(|types| types.dst).skip_binder();
104             crate::maybe_transmutable::MaybeTransmutableQuery::new(
105                 src,
106                 dst,
107                 scope,
108                 assume,
109                 self.infcx.tcx,
110             )
111             .answer()
112         }
113     }
114 }
115
116 #[cfg(feature = "rustc")]
117 pub use rustc::*;