core/mem/transmutability.rs
1use crate::marker::ConstParamTy_;
2
3/// Marks that `Src` is transmutable into `Self`.
4///
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/// # Safety
13///
14/// If `Dst: TransmuteFrom<Src, ASSUMPTIONS>`, the compiler guarantees that
15/// `Src` is soundly *union-transmutable* into a value of type `Dst`, provided
16/// that the programmer has guaranteed that the given [`ASSUMPTIONS`](Assume)
17/// are satisfied.
18///
19/// A union-transmute is any bit-reinterpretation conversion in the form of:
20///
21/// ```rust
22/// pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst {
23/// use core::mem::ManuallyDrop;
24///
25/// #[repr(C)]
26/// union Transmute<Src, Dst> {
27/// src: ManuallyDrop<Src>,
28/// dst: ManuallyDrop<Dst>,
29/// }
30///
31/// let transmute = Transmute {
32/// src: ManuallyDrop::new(src),
33/// };
34///
35/// let dst = unsafe { transmute.dst };
36///
37/// ManuallyDrop::into_inner(dst)
38/// }
39/// ```
40///
41/// Note that this construction is more permissive than
42/// [`mem::transmute_copy`](super::transmute_copy); union-transmutes permit
43/// conversions that extend the bits of `Src` with trailing padding to fill
44/// trailing uninitialized bytes of `Self`; e.g.:
45///
46/// ```rust
47/// #![feature(transmutability)]
48///
49/// use core::mem::{Assume, TransmuteFrom};
50///
51/// let src = 42u8; // size = 1
52///
53/// #[repr(C, align(2))]
54/// struct Dst(u8); // size = 2
55//
56/// let _ = unsafe {
57/// <Dst as TransmuteFrom<u8, { Assume::SAFETY }>>::transmute(src)
58/// };
59/// ```
60///
61/// # Caveats
62///
63/// ## Portability
64///
65/// Implementations of this trait do not provide any guarantee of portability
66/// across toolchains, targets or compilations. This trait may be implemented
67/// for certain combinations of `Src`, `Self` and `ASSUME` on some toolchains,
68/// targets or compilations, but not others. For example, if the layouts of
69/// `Src` or `Self` are non-deterministic, the presence or absence of an
70/// implementation of this trait may also be non-deterministic. Even if `Src`
71/// and `Self` have deterministic layouts (e.g., they are `repr(C)` structs),
72/// Rust does not specify the alignments of its primitive integer types, and
73/// layouts that involve these types may vary across toolchains, targets or
74/// compilations.
75///
76/// ## Stability
77///
78/// Implementations of this trait do not provide any guarantee of SemVer
79/// stability across the crate versions that define the `Src` and `Self` types.
80/// If SemVer stability is crucial to your application, you must consult the
81/// documentation of `Src` and `Self`s' defining crates. Note that the presence
82/// of `repr(C)`, alone, does not carry a safety invariant of SemVer stability.
83/// Furthermore, stability does not imply portability. For example, the size of
84/// `usize` is stable, but not portable.
85#[unstable(feature = "transmutability", issue = "99571")]
86#[unstable_feature_bound(transmutability)]
87#[lang = "transmute_trait"]
88#[rustc_deny_explicit_impl]
89#[rustc_do_not_implement_via_object]
90#[rustc_coinductive]
91pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }>
92where
93 Src: ?Sized,
94{
95 /// Transmutes a `Src` value into a `Self`.
96 ///
97 /// # Safety
98 ///
99 /// The safety obligations of the caller depend on the value of `ASSUME`:
100 /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee
101 /// that the addresses of references in the returned `Self` satisfy the
102 /// alignment requirements of their referent types.
103 /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee
104 /// that references in the returned `Self` will not outlive their
105 /// referents.
106 /// - If [`ASSUME.safety`](Assume::safety), the returned value might not
107 /// satisfy the library safety invariants of `Self`, and the caller must
108 /// guarantee that undefined behavior does not arise from uses of the
109 /// returned value.
110 /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee
111 /// that `src` is a bit-valid instance of `Self`.
112 ///
113 /// When satisfying the above obligations (if any), the caller must *not*
114 /// assume that this trait provides any inherent guarantee of layout
115 /// [portability](#portability) or [stability](#stability).
116 unsafe fn transmute(src: Src) -> Self
117 where
118 Src: Sized,
119 Self: Sized,
120 {
121 use super::ManuallyDrop;
122
123 #[repr(C)]
124 union Transmute<Src, Dst> {
125 src: ManuallyDrop<Src>,
126 dst: ManuallyDrop<Dst>,
127 }
128
129 let transmute = Transmute { src: ManuallyDrop::new(src) };
130
131 // SAFETY: It is safe to reinterpret the bits of `src` as a value of
132 // type `Self`, because, by combination of invariant on this trait and
133 // contract on the caller, `src` has been proven to satisfy both the
134 // language and library invariants of `Self`. For all invariants not
135 // `ASSUME`'d by the caller, the safety obligation is supplied by the
136 // compiler. Conversely, for all invariants `ASSUME`'d by the caller,
137 // the safety obligation is supplied by contract on the caller.
138 let dst = unsafe { transmute.dst };
139
140 ManuallyDrop::into_inner(dst)
141 }
142}
143
144/// Configurable proof assumptions of [`TransmuteFrom`].
145///
146/// When `false`, the respective proof obligation belongs to the compiler. When
147/// `true`, the onus of the safety proof belongs to the programmer.
148#[unstable(feature = "transmutability", issue = "99571")]
149#[lang = "transmute_opts"]
150#[derive(PartialEq, Eq, Clone, Copy, Debug)]
151pub struct Assume {
152 /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
153 /// that might violate the alignment requirements of references; e.g.:
154 ///
155 /// ```compile_fail,E0277
156 /// #![feature(transmutability)]
157 /// use core::mem::TransmuteFrom;
158 ///
159 /// assert_eq!(align_of::<[u8; 2]>(), 1);
160 /// assert_eq!(align_of::<u16>(), 2);
161 ///
162 /// let src: &[u8; 2] = &[0xFF, 0xFF];
163 ///
164 /// // SAFETY: No safety obligations.
165 /// let dst: &u16 = unsafe {
166 /// <_ as TransmuteFrom<_>>::transmute(src)
167 /// };
168 /// ```
169 ///
170 /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
171 /// that references in the transmuted value satisfy the alignment
172 /// requirements of their referent types; e.g.:
173 ///
174 /// ```rust
175 /// #![feature(pointer_is_aligned_to, transmutability)]
176 /// use core::mem::{Assume, TransmuteFrom};
177 ///
178 /// let src: &[u8; 2] = &[0xFF, 0xFF];
179 ///
180 /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::<u16>()) {
181 /// // SAFETY: We have checked above that the address of `src` satisfies the
182 /// // alignment requirements of `u16`.
183 /// Some(unsafe {
184 /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src)
185 /// })
186 /// } else {
187 /// None
188 /// };
189 ///
190 /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None));
191 /// ```
192 pub alignment: bool,
193
194 /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
195 /// that extend the lifetimes of references.
196 ///
197 /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that
198 /// references in the transmuted value do not outlive their referents.
199 pub lifetimes: bool,
200
201 /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
202 /// that might violate the library safety invariants of the destination
203 /// type; e.g.:
204 ///
205 /// ```compile_fail,E0277
206 /// #![feature(transmutability)]
207 /// use core::mem::TransmuteFrom;
208 ///
209 /// let src: u8 = 3;
210 ///
211 /// struct EvenU8 {
212 /// // SAFETY: `val` must be an even number.
213 /// val: u8,
214 /// }
215 ///
216 /// // SAFETY: No safety obligations.
217 /// let dst: EvenU8 = unsafe {
218 /// <_ as TransmuteFrom<_>>::transmute(src)
219 /// };
220 /// ```
221 ///
222 /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
223 /// that undefined behavior does not arise from using the transmuted value;
224 /// e.g.:
225 ///
226 /// ```rust
227 /// #![feature(transmutability)]
228 /// use core::mem::{Assume, TransmuteFrom};
229 ///
230 /// let src: u8 = 42;
231 ///
232 /// struct EvenU8 {
233 /// // SAFETY: `val` must be an even number.
234 /// val: u8,
235 /// }
236 ///
237 /// let maybe_dst: Option<EvenU8> = if src % 2 == 0 {
238 /// // SAFETY: We have checked above that the value of `src` is even.
239 /// Some(unsafe {
240 /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src)
241 /// })
242 /// } else {
243 /// None
244 /// };
245 ///
246 /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 })));
247 /// ```
248 pub safety: bool,
249
250 /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
251 /// that might violate the language-level bit-validity invariant of the
252 /// destination type; e.g.:
253 ///
254 /// ```compile_fail,E0277
255 /// #![feature(transmutability)]
256 /// use core::mem::TransmuteFrom;
257 ///
258 /// let src: u8 = 3;
259 ///
260 /// // SAFETY: No safety obligations.
261 /// let dst: bool = unsafe {
262 /// <_ as TransmuteFrom<_>>::transmute(src)
263 /// };
264 /// ```
265 ///
266 /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured
267 /// that the value being transmuted is a bit-valid instance of the
268 /// transmuted value; e.g.:
269 ///
270 /// ```rust
271 /// #![feature(transmutability)]
272 /// use core::mem::{Assume, TransmuteFrom};
273 ///
274 /// let src: u8 = 1;
275 ///
276 /// let maybe_dst: Option<bool> = if src == 0 || src == 1 {
277 /// // SAFETY: We have checked above that the value of `src` is a bit-valid
278 /// // instance of `bool`.
279 /// Some(unsafe {
280 /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src)
281 /// })
282 /// } else {
283 /// None
284 /// };
285 ///
286 /// assert_eq!(maybe_dst, Some(true));
287 /// ```
288 pub validity: bool,
289}
290
291#[unstable(feature = "transmutability", issue = "99571")]
292#[unstable_feature_bound(transmutability)]
293impl ConstParamTy_ for Assume {}
294
295impl Assume {
296 /// With this, [`TransmuteFrom`] does not assume you have ensured any safety
297 /// obligations are met, and relies only upon its own analysis to (dis)prove
298 /// transmutability.
299 #[unstable(feature = "transmutability", issue = "99571")]
300 pub const NOTHING: Self =
301 Self { alignment: false, lifetimes: false, safety: false, validity: false };
302
303 /// With this, [`TransmuteFrom`] assumes only that you have ensured that
304 /// references in the transmuted value satisfy the alignment requirements of
305 /// their referent types. See [`Assume::alignment`] for examples.
306 #[unstable(feature = "transmutability", issue = "99571")]
307 pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING };
308
309 /// With this, [`TransmuteFrom`] assumes only that you have ensured that
310 /// references in the transmuted value do not outlive their referents. See
311 /// [`Assume::lifetimes`] for examples.
312 #[unstable(feature = "transmutability", issue = "99571")]
313 pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING };
314
315 /// With this, [`TransmuteFrom`] assumes only that you have ensured that
316 /// undefined behavior does not arise from using the transmuted value. See
317 /// [`Assume::safety`] for examples.
318 #[unstable(feature = "transmutability", issue = "99571")]
319 pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING };
320
321 /// With this, [`TransmuteFrom`] assumes only that you have ensured that the
322 /// value being transmuted is a bit-valid instance of the transmuted value.
323 /// See [`Assume::validity`] for examples.
324 #[unstable(feature = "transmutability", issue = "99571")]
325 pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING };
326
327 /// Combine the assumptions of `self` and `other_assumptions`.
328 ///
329 /// This is especially useful for extending [`Assume`] in generic contexts;
330 /// e.g.:
331 ///
332 /// ```rust
333 /// #![feature(
334 /// adt_const_params,
335 /// generic_const_exprs,
336 /// pointer_is_aligned_to,
337 /// transmutability,
338 /// )]
339 /// #![allow(incomplete_features)]
340 /// use core::mem::{Assume, TransmuteFrom};
341 ///
342 /// /// Attempts to transmute `src` to `&Dst`.
343 /// ///
344 /// /// Returns `None` if `src` violates the alignment requirements of `&Dst`.
345 /// ///
346 /// /// # Safety
347 /// ///
348 /// /// The caller guarantees that the obligations required by `ASSUME`, except
349 /// /// alignment, are satisfied.
350 /// unsafe fn try_transmute_ref<'a, Src, Dst, const ASSUME: Assume>(src: &'a Src) -> Option<&'a Dst>
351 /// where
352 /// &'a Dst: TransmuteFrom<&'a Src, { ASSUME.and(Assume::ALIGNMENT) }>,
353 /// {
354 /// if <*const _>::is_aligned_to(src, align_of::<Dst>()) {
355 /// // SAFETY: By the above dynamic check, we have ensured that the address
356 /// // of `src` satisfies the alignment requirements of `&Dst`. By contract
357 /// // on the caller, the safety obligations required by `ASSUME` have also
358 /// // been satisfied.
359 /// Some(unsafe {
360 /// <_ as TransmuteFrom<_, { ASSUME.and(Assume::ALIGNMENT) }>>::transmute(src)
361 /// })
362 /// } else {
363 /// None
364 /// }
365 /// }
366 ///
367 /// let src: &[u8; 2] = &[0xFF, 0xFF];
368 ///
369 /// // SAFETY: No safety obligations.
370 /// let maybe_dst: Option<&u16> = unsafe {
371 /// try_transmute_ref::<_, _, { Assume::NOTHING }>(src)
372 /// };
373 ///```
374 #[unstable(feature = "transmutability", issue = "99571")]
375 pub const fn and(self, other_assumptions: Self) -> Self {
376 Self {
377 alignment: self.alignment || other_assumptions.alignment,
378 lifetimes: self.lifetimes || other_assumptions.lifetimes,
379 safety: self.safety || other_assumptions.safety,
380 validity: self.validity || other_assumptions.validity,
381 }
382 }
383
384 /// Remove `other_assumptions` the obligations of `self`; e.g.:
385 ///
386 /// ```rust
387 /// #![feature(transmutability)]
388 /// use core::mem::Assume;
389 ///
390 /// let assumptions = Assume::ALIGNMENT.and(Assume::SAFETY);
391 /// let to_be_removed = Assume::SAFETY.and(Assume::VALIDITY);
392 ///
393 /// assert_eq!(
394 /// assumptions.but_not(to_be_removed),
395 /// Assume::ALIGNMENT,
396 /// );
397 /// ```
398 #[unstable(feature = "transmutability", issue = "99571")]
399 pub const fn but_not(self, other_assumptions: Self) -> Self {
400 Self {
401 alignment: self.alignment && !other_assumptions.alignment,
402 lifetimes: self.lifetimes && !other_assumptions.lifetimes,
403 safety: self.safety && !other_assumptions.safety,
404 validity: self.validity && !other_assumptions.validity,
405 }
406 }
407}
408
409// FIXME(jswrenn): This const op is not actually usable. Why?
410// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
411#[unstable(feature = "transmutability", issue = "99571")]
412impl core::ops::Add for Assume {
413 type Output = Assume;
414
415 fn add(self, other_assumptions: Assume) -> Assume {
416 self.and(other_assumptions)
417 }
418}
419
420// FIXME(jswrenn): This const op is not actually usable. Why?
421// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
422#[unstable(feature = "transmutability", issue = "99571")]
423impl core::ops::Sub for Assume {
424 type Output = Assume;
425
426 fn sub(self, other_assumptions: Assume) -> Assume {
427 self.but_not(other_assumptions)
428 }
429}