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