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