1
1
use crate :: marker:: { ConstParamTy_ , UnsizedConstParamTy } ;
2
2
3
- /// Are values of a type transmutable into values of another type?
3
+ /// Marks that `Src` is transmutable into `Self`.
4
4
///
5
- /// This trait is implemented on-the-fly by the compiler for types `Src` and `Self` when the bits of
6
- /// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`,
7
- /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
5
+ /// # Implementation
6
+ ///
7
+ /// This trait cannot be implemented explicitly. It is implemented on-the-fly by
8
+ /// the compiler for all types `Src` and `Self` such that, given a set of safety
9
+ /// obligations on the programmer (see [`Assume`]), the compiler has proved that
10
+ /// the bits of a value of type `Src` can be soundly reinterpreted as a `Self`.
11
+ ///
12
+ /// Specifically, this trait models (and
13
+ /// [implements](BikeshedIntrinsicFrom::transmute)) the semantics of
14
+ /// transmute-via-union; i.e.:
15
+ ///
16
+ /// ```rust
17
+ /// pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst {
18
+ /// use core::mem::ManuallyDrop;
19
+ ///
20
+ /// #[repr(C)]
21
+ /// union Transmute<Src, Dst> {
22
+ /// src: ManuallyDrop<Src>,
23
+ /// dst: ManuallyDrop<Dst>,
24
+ /// }
25
+ ///
26
+ /// let transmute = Transmute {
27
+ /// src: ManuallyDrop::new(src),
28
+ /// };
29
+ ///
30
+ /// let dst = transmute.dst;
31
+ ///
32
+ /// ManuallyDrop::into_inner(dst)
33
+ /// }
34
+ /// ```
35
+ ///
36
+ /// Note that this construction supports some transmutations forbidden by
37
+ /// [`mem::transmute_copy`](super::transmute_copy); namely, transmutations that
38
+ /// extend the bits of `Src` with trailing padding to fill trailing
39
+ /// uninitialized bytes of `Self`; e.g.:
40
+ ///
41
+ /// ```ignore (cannot doctest this until bootstrap; remove ignore and corresponding test in tests/mem.rs in the future)
42
+ /// #![feature(transmutability)]
43
+ ///
44
+ /// use core::mem::{Assume, BikeshedIntrinsicFrom};
45
+ ///
46
+ /// let src = 42u8; // size = 1
47
+ ///
48
+ /// #[repr(C, align(2))]
49
+ /// struct Dst(u8); // size = 2
50
+ //
51
+ /// let _ = unsafe {
52
+ /// <Dst as BikeshedIntrinsicFrom<u8, { Assume::SAFETY }>>::transmute(src)
53
+ /// };
54
+ /// ```
55
+ ///
56
+ /// ## Portability
57
+ ///
58
+ /// Implementations of this trait do not provide any guarantee of portability
59
+ /// across toolchains, targets or compilations. This trait may be implemented
60
+ /// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains,
61
+ /// targets or compilations, but not others. For example, if the layouts of
62
+ /// `Src` or `Self` are non-deterministic, the presence or absence of an
63
+ /// implementation of this trait may also be non-deterministic. Even if `Src`
64
+ /// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs),
65
+ /// Rust does not specify the alignments of its primitive integer types, and
66
+ /// layouts that involve these types may vary across toolchains, targets or
67
+ /// compilations.
68
+ ///
69
+ /// ## Stability
70
+ ///
71
+ /// Implementations of this trait do not provide any guarantee of SemVer
72
+ /// stability across the crate versions that define the `Src` and `Self` types.
73
+ /// If SemVer stability is crucial to your application, you must consult the
74
+ /// documentation of `Src` and `Self`s' defining crates. Note that the presence
75
+ /// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability.
76
+ /// Furthermore, stability does not imply portability. For example, the size of
77
+ /// `usize` is stable, but not portable.
8
78
#[ unstable( feature = "transmutability" , issue = "99571" ) ]
9
79
#[ lang = "transmute_trait" ]
10
80
#[ rustc_deny_explicit_impl( implement_via_object = false ) ]
@@ -13,28 +83,96 @@ pub unsafe trait BikeshedIntrinsicFrom<Src, const ASSUME: Assume = { Assume::NOT
13
83
where
14
84
Src : ?Sized ,
15
85
{
86
+ /// Transmutes a `Src` value into a `Self`.
87
+ ///
88
+ /// # Safety
89
+ ///
90
+ /// The safety obligations of the caller depend on the value of `ASSUME`:
91
+ /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee
92
+ /// that the addresses of references in the returned `Self` satisfy the
93
+ /// alignment requirements of their referent types.
94
+ /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee
95
+ /// that references in the returned `Self` will not outlive their
96
+ /// referents.
97
+ /// - If [`ASSUME.safety`](Assume::safety), the returned value might not
98
+ /// satisfy the library safety invariants of `Self`, and the caller must
99
+ /// guarantee that undefined behavior does not arise from uses of the
100
+ /// returned value.
101
+ /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee
102
+ /// that `src` is a bit-valid instance of `Self`.
103
+ ///
104
+ /// When satisfying the above obligations (if any), the caller must *not*
105
+ /// assume that this trait provides any inherent guarantee of layout
106
+ /// [portability](#portability) or [stability](#stability).
107
+ unsafe fn transmute ( src : Src ) -> Self
108
+ where
109
+ Src : Sized ,
110
+ Self : Sized ,
111
+ {
112
+ use super :: ManuallyDrop ;
113
+
114
+ #[ repr( C ) ]
115
+ union Transmute < Src , Dst > {
116
+ src : ManuallyDrop < Src > ,
117
+ dst : ManuallyDrop < Dst > ,
118
+ }
119
+
120
+ let transmute = Transmute { src : ManuallyDrop :: new ( src) } ;
121
+
122
+ // SAFETY: It is safe to reinterpret the bits of `src` as a value of
123
+ // type `Self`, because, by combination of invariant on this trait and
124
+ // contract on the caller, `src` has been proven to satisfy both the
125
+ // language and library invariants of `Self`. For all invariants not
126
+ // `ASSUME`'d by the caller, the safety obligation is supplied by the
127
+ // compiler. Conversely, for all invariants `ASSUME`'d by the caller,
128
+ // the safety obligation is supplied by contract on the caller.
129
+ let dst = unsafe { transmute. dst } ;
130
+
131
+ ManuallyDrop :: into_inner ( dst)
132
+ }
16
133
}
17
134
18
- /// What transmutation safety conditions shall the compiler assume that *you* are checking?
135
+ /// Configurable proof assumptions of [`BikeshedIntrinsicFrom`].
136
+ ///
137
+ /// When `false`, the respective proof obligation belongs to the compiler. When
138
+ /// `true`, the onus of the safety proof belongs to the programmer.
139
+ /// [`BikeshedIntrinsicFrom`].
19
140
#[ unstable( feature = "transmutability" , issue = "99571" ) ]
20
141
#[ lang = "transmute_opts" ]
21
142
#[ derive( PartialEq , Eq , Clone , Copy , Debug ) ]
22
143
pub struct Assume {
23
- /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that
24
- /// destination referents do not have stricter alignment requirements than source referents.
144
+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
145
+ /// transmutations that might violate the the alignment requirements of
146
+ /// references.
147
+ ///
148
+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
149
+ /// that that references in the transmuted value satisfy the alignment
150
+ /// requirements of their referent types.
25
151
pub alignment : bool ,
26
152
27
- /// When `true`, the compiler assume that *you* are ensuring that lifetimes are not extended in a manner
28
- /// that violates Rust's memory model.
153
+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
154
+ /// transmutations that extend the lifetimes of references.
155
+ ///
156
+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
157
+ /// that that references in the transmuted value do not outlive their
158
+ /// referents.
29
159
pub lifetimes : bool ,
30
160
31
- /// When `true`, the compiler assumes that *you* have ensured that no
32
- /// unsoundness will arise from violating the safety invariants of the
33
- /// destination type (and sometimes of the source type, too).
161
+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
162
+ /// transmutations that might violate the library safety invariants of the
163
+ /// return type.
164
+ ///
165
+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
166
+ /// that undefined behavior does not arise from using the returned value.
34
167
pub safety : bool ,
35
168
36
- /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid
37
- /// instance of the destination type.
169
+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
170
+ /// transmutations that might violate the language-level bit-validity
171
+ /// invariant of the return type.
172
+ ///
173
+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
174
+ /// that the value being transmuted is a bit-valid instance of the return
175
+ /// type.
38
176
pub validity : bool ,
39
177
}
40
178
0 commit comments