11use crate :: marker:: { ConstParamTy_ , UnsizedConstParamTy } ;
22
3- /// Are values of a type transmutable into values of another type?
3+ /// Marks that `Src` is transmutable into `Self`.
44///
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 that are unsound
37+ /// with [`mem::transmute_copy`](super::transmute_copy); namely, transmutations
38+ /// that extend the bits of `Src` with trailing padding to fill trailing
39+ /// uninitialized bytes of `Self`; e.g.:
40+ ///
41+ #[ cfg_attr( bootstrap, doc = "```rust,ignore not runnable on bootstrap" ) ]
42+ #[ cfg_attr( not( bootstrap) , doc = "```rust" ) ]
43+ /// #![feature(transmutability)]
44+ ///
45+ /// use core::mem::{Assume, BikeshedIntrinsicFrom};
46+ ///
47+ /// let src = 42u8; // size = 1
48+ ///
49+ /// #[repr(C, align(2))]
50+ /// struct Dst(u8); // size = 2
51+ //
52+ /// let _ = unsafe {
53+ /// <Dst as BikeshedIntrinsicFrom<u8, { Assume::SAFETY }>>::transmute(src)
54+ /// };
55+ /// ```
56+ ///
57+ /// ## Portability
58+ ///
59+ /// Implementations of this trait do not provide any guarantee of portability
60+ /// across toolchains, targets or compilations. This trait may be implemented
61+ /// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains,
62+ /// targets or compilations, but not others. For example, if the layouts of
63+ /// `Src` or `Self` are non-deterministic, the presence or absence of an
64+ /// implementation of this trait may also be non-deterministic. Even if `Src`
65+ /// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs),
66+ /// Rust does not specify the alignments of its primitive integer types, and
67+ /// layouts that involve these types may vary across toolchains, targets or
68+ /// compilations.
69+ ///
70+ /// ## Stability
71+ ///
72+ /// Implementations of this trait do not provide any guarantee of SemVer
73+ /// stability across the crate versions that define the `Src` and `Self` types.
74+ /// If SemVer stability is crucial to your application, you must consult the
75+ /// documentation of `Src` and `Self`s' defining crates. Note that the presence
76+ /// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability.
77+ /// Furthermore, stability does not imply portability. For example, the size of
78+ /// `usize` is stable, but not portable.
879#[ unstable( feature = "transmutability" , issue = "99571" ) ]
980#[ lang = "transmute_trait" ]
1081#[ rustc_deny_explicit_impl( implement_via_object = false ) ]
@@ -13,28 +84,96 @@ pub unsafe trait BikeshedIntrinsicFrom<Src, const ASSUME: Assume = { Assume::NOT
1384where
1485 Src : ?Sized ,
1586{
87+ /// Transmutes a `Src` value into a `Self`.
88+ ///
89+ /// # Safety
90+ ///
91+ /// The safety obligations of the caller depend on the value of `ASSUME`:
92+ /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee
93+ /// that the addresses of references in the returned `Self` satisfy the
94+ /// alignment requirements of their referent types.
95+ /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee
96+ /// that references in the returned `Self` will not outlive their
97+ /// referents.
98+ /// - If [`ASSUME.safety`](Assume::safety), the returned value might not
99+ /// satisfy the library safety invariants of `Self`, and the caller must
100+ /// guarantee that undefined behavior does not arise from uses of the
101+ /// returned value.
102+ /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee
103+ /// that `src` is a bit-valid instance of `Self`.
104+ ///
105+ /// When satisfying the above obligations (if any), the caller must *not*
106+ /// assume that this trait provides any inherent guarantee of layout
107+ /// [portability](#portability) or [stability](#stability).
108+ unsafe fn transmute ( src : Src ) -> Self
109+ where
110+ Src : Sized ,
111+ Self : Sized ,
112+ {
113+ use super :: ManuallyDrop ;
114+
115+ #[ repr( C ) ]
116+ union Transmute < Src , Dst > {
117+ src : ManuallyDrop < Src > ,
118+ dst : ManuallyDrop < Dst > ,
119+ }
120+
121+ let transmute = Transmute { src : ManuallyDrop :: new ( src) } ;
122+
123+ // SAFETY: It is safe to reinterpret the bits of `src` as a value of
124+ // type `Self`, because, by combination of invariant on this trait and
125+ // contract on the caller, `src` has been proven to satisfy both the
126+ // language and library invariants of `Self`. For all invariants not
127+ // `ASSUME`'d by the caller, the safety obligation is supplied by the
128+ // compiler. Conversely, for all invariants `ASSUME`'d by the caller,
129+ // the safety obligation is supplied by contract on the caller.
130+ let dst = unsafe { transmute. dst } ;
131+
132+ ManuallyDrop :: into_inner ( dst)
133+ }
16134}
17135
18- /// What transmutation safety conditions shall the compiler assume that *you* are checking?
136+ /// Configurable proof assumptions of [`BikeshedIntrinsicFrom`].
137+ ///
138+ /// When `false`, the respective proof obligation belongs to the compiler. When
139+ /// `true`, the onus of the safety proof belongs to the programmer.
140+ /// [`BikeshedIntrinsicFrom`].
19141#[ unstable( feature = "transmutability" , issue = "99571" ) ]
20142#[ lang = "transmute_opts" ]
21143#[ derive( PartialEq , Eq , Clone , Copy , Debug ) ]
22144pub 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.
145+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
146+ /// transmutations that might violate the the alignment requirements of
147+ /// references.
148+ ///
149+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
150+ /// that that references in the transmuted value satisfy the alignment
151+ /// requirements of their referent types.
25152 pub alignment : bool ,
26153
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.
154+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
155+ /// transmutations that extend the lifetimes of references.
156+ ///
157+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
158+ /// that that references in the transmuted value do not outlive their
159+ /// referents.
29160 pub lifetimes : bool ,
30161
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).
162+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
163+ /// transmutations that might violate the library safety invariants of the
164+ /// destination type.
165+ ///
166+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
167+ /// that undefined behavior does not arise from using the transmuted value.
34168 pub safety : bool ,
35169
36- /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid
37- /// instance of the destination type.
170+ /// When `false`, [`BikeshedIntrinsicFrom`] is not implemented for
171+ /// transmutations that might violate the language-level bit-validity
172+ /// invariant of the destination type.
173+ ///
174+ /// When `true`, [`BikeshedIntrinsicFrom`] assumes that *you* have ensured
175+ /// that the value being transmuted is a bit-valid instance of the
176+ /// transmuted value.
38177 pub validity : bool ,
39178}
40179
0 commit comments