| 1 | use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; |
| 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 | #[lang = "transmute_trait" ] |
| 87 | #[rustc_deny_explicit_impl ] |
| 88 | #[rustc_do_not_implement_via_object] |
| 89 | #[rustc_coinductive ] |
| 90 | pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }> |
| 91 | where |
| 92 | Src: ?Sized, |
| 93 | { |
| 94 | /// Transmutes a `Src` value into a `Self`. |
| 95 | /// |
| 96 | /// # Safety |
| 97 | /// |
| 98 | /// The safety obligations of the caller depend on the value of `ASSUME`: |
| 99 | /// - If [`ASSUME.alignment`](Assume::alignment), the caller must guarantee |
| 100 | /// that the addresses of references in the returned `Self` satisfy the |
| 101 | /// alignment requirements of their referent types. |
| 102 | /// - If [`ASSUME.lifetimes`](Assume::lifetimes), the caller must guarantee |
| 103 | /// that references in the returned `Self` will not outlive their |
| 104 | /// referents. |
| 105 | /// - If [`ASSUME.safety`](Assume::safety), the returned value might not |
| 106 | /// satisfy the library safety invariants of `Self`, and the caller must |
| 107 | /// guarantee that undefined behavior does not arise from uses of the |
| 108 | /// returned value. |
| 109 | /// - If [`ASSUME.validity`](Assume::validity), the caller must guarantee |
| 110 | /// that `src` is a bit-valid instance of `Self`. |
| 111 | /// |
| 112 | /// When satisfying the above obligations (if any), the caller must *not* |
| 113 | /// assume that this trait provides any inherent guarantee of layout |
| 114 | /// [portability](#portability) or [stability](#stability). |
| 115 | unsafe fn transmute(src: Src) -> Self |
| 116 | where |
| 117 | Src: Sized, |
| 118 | Self: Sized, |
| 119 | { |
| 120 | use super::ManuallyDrop; |
| 121 | |
| 122 | #[repr (C)] |
| 123 | union Transmute<Src, Dst> { |
| 124 | src: ManuallyDrop<Src>, |
| 125 | dst: ManuallyDrop<Dst>, |
| 126 | } |
| 127 | |
| 128 | let transmute = Transmute { src: ManuallyDrop::new(src) }; |
| 129 | |
| 130 | // SAFETY: It is safe to reinterpret the bits of `src` as a value of |
| 131 | // type `Self`, because, by combination of invariant on this trait and |
| 132 | // contract on the caller, `src` has been proven to satisfy both the |
| 133 | // language and library invariants of `Self`. For all invariants not |
| 134 | // `ASSUME`'d by the caller, the safety obligation is supplied by the |
| 135 | // compiler. Conversely, for all invariants `ASSUME`'d by the caller, |
| 136 | // the safety obligation is supplied by contract on the caller. |
| 137 | let dst = unsafe { transmute.dst }; |
| 138 | |
| 139 | ManuallyDrop::into_inner(dst) |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | /// Configurable proof assumptions of [`TransmuteFrom`]. |
| 144 | /// |
| 145 | /// When `false`, the respective proof obligation belongs to the compiler. When |
| 146 | /// `true`, the onus of the safety proof belongs to the programmer. |
| 147 | #[unstable (feature = "transmutability" , issue = "99571" )] |
| 148 | #[lang = "transmute_opts" ] |
| 149 | #[derive (PartialEq, Eq, Clone, Copy, Debug)] |
| 150 | pub struct Assume { |
| 151 | /// When `false`, [`TransmuteFrom`] is not implemented for transmutations |
| 152 | /// that might violate the alignment requirements of references; e.g.: |
| 153 | /// |
| 154 | /// ```compile_fail,E0277 |
| 155 | /// #![feature(transmutability)] |
| 156 | /// use core::mem::TransmuteFrom; |
| 157 | /// |
| 158 | /// assert_eq!(align_of::<[u8; 2]>(), 1); |
| 159 | /// assert_eq!(align_of::<u16>(), 2); |
| 160 | /// |
| 161 | /// let src: &[u8; 2] = &[0xFF, 0xFF]; |
| 162 | /// |
| 163 | /// // SAFETY: No safety obligations. |
| 164 | /// let dst: &u16 = unsafe { |
| 165 | /// <_ as TransmuteFrom<_>>::transmute(src) |
| 166 | /// }; |
| 167 | /// ``` |
| 168 | /// |
| 169 | /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured |
| 170 | /// that references in the transmuted value satisfy the alignment |
| 171 | /// requirements of their referent types; e.g.: |
| 172 | /// |
| 173 | /// ```rust |
| 174 | /// #![feature(pointer_is_aligned_to, transmutability)] |
| 175 | /// use core::mem::{Assume, TransmuteFrom}; |
| 176 | /// |
| 177 | /// let src: &[u8; 2] = &[0xFF, 0xFF]; |
| 178 | /// |
| 179 | /// let maybe_dst: Option<&u16> = if <*const _>::is_aligned_to(src, align_of::<u16>()) { |
| 180 | /// // SAFETY: We have checked above that the address of `src` satisfies the |
| 181 | /// // alignment requirements of `u16`. |
| 182 | /// Some(unsafe { |
| 183 | /// <_ as TransmuteFrom<_, { Assume::ALIGNMENT }>>::transmute(src) |
| 184 | /// }) |
| 185 | /// } else { |
| 186 | /// None |
| 187 | /// }; |
| 188 | /// |
| 189 | /// assert!(matches!(maybe_dst, Some(&u16::MAX) | None)); |
| 190 | /// ``` |
| 191 | pub alignment: bool, |
| 192 | |
| 193 | /// When `false`, [`TransmuteFrom`] is not implemented for transmutations |
| 194 | /// that extend the lifetimes of references. |
| 195 | /// |
| 196 | /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured that |
| 197 | /// references in the transmuted value do not outlive their referents. |
| 198 | pub lifetimes: bool, |
| 199 | |
| 200 | /// When `false`, [`TransmuteFrom`] is not implemented for transmutations |
| 201 | /// that might violate the library safety invariants of the destination |
| 202 | /// type; e.g.: |
| 203 | /// |
| 204 | /// ```compile_fail,E0277 |
| 205 | /// #![feature(transmutability)] |
| 206 | /// use core::mem::TransmuteFrom; |
| 207 | /// |
| 208 | /// let src: u8 = 3; |
| 209 | /// |
| 210 | /// struct EvenU8 { |
| 211 | /// // SAFETY: `val` must be an even number. |
| 212 | /// val: u8, |
| 213 | /// } |
| 214 | /// |
| 215 | /// // SAFETY: No safety obligations. |
| 216 | /// let dst: EvenU8 = unsafe { |
| 217 | /// <_ as TransmuteFrom<_>>::transmute(src) |
| 218 | /// }; |
| 219 | /// ``` |
| 220 | /// |
| 221 | /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured |
| 222 | /// that undefined behavior does not arise from using the transmuted value; |
| 223 | /// e.g.: |
| 224 | /// |
| 225 | /// ```rust |
| 226 | /// #![feature(transmutability)] |
| 227 | /// use core::mem::{Assume, TransmuteFrom}; |
| 228 | /// |
| 229 | /// let src: u8 = 42; |
| 230 | /// |
| 231 | /// struct EvenU8 { |
| 232 | /// // SAFETY: `val` must be an even number. |
| 233 | /// val: u8, |
| 234 | /// } |
| 235 | /// |
| 236 | /// let maybe_dst: Option<EvenU8> = if src % 2 == 0 { |
| 237 | /// // SAFETY: We have checked above that the value of `src` is even. |
| 238 | /// Some(unsafe { |
| 239 | /// <_ as TransmuteFrom<_, { Assume::SAFETY }>>::transmute(src) |
| 240 | /// }) |
| 241 | /// } else { |
| 242 | /// None |
| 243 | /// }; |
| 244 | /// |
| 245 | /// assert!(matches!(maybe_dst, Some(EvenU8 { val: 42 }))); |
| 246 | /// ``` |
| 247 | pub safety: bool, |
| 248 | |
| 249 | /// When `false`, [`TransmuteFrom`] is not implemented for transmutations |
| 250 | /// that might violate the language-level bit-validity invariant of the |
| 251 | /// destination type; e.g.: |
| 252 | /// |
| 253 | /// ```compile_fail,E0277 |
| 254 | /// #![feature(transmutability)] |
| 255 | /// use core::mem::TransmuteFrom; |
| 256 | /// |
| 257 | /// let src: u8 = 3; |
| 258 | /// |
| 259 | /// // SAFETY: No safety obligations. |
| 260 | /// let dst: bool = unsafe { |
| 261 | /// <_ as TransmuteFrom<_>>::transmute(src) |
| 262 | /// }; |
| 263 | /// ``` |
| 264 | /// |
| 265 | /// When `true`, [`TransmuteFrom`] assumes that *you* have ensured |
| 266 | /// that the value being transmuted is a bit-valid instance of the |
| 267 | /// transmuted value; e.g.: |
| 268 | /// |
| 269 | /// ```rust |
| 270 | /// #![feature(transmutability)] |
| 271 | /// use core::mem::{Assume, TransmuteFrom}; |
| 272 | /// |
| 273 | /// let src: u8 = 1; |
| 274 | /// |
| 275 | /// let maybe_dst: Option<bool> = if src == 0 || src == 1 { |
| 276 | /// // SAFETY: We have checked above that the value of `src` is a bit-valid |
| 277 | /// // instance of `bool`. |
| 278 | /// Some(unsafe { |
| 279 | /// <_ as TransmuteFrom<_, { Assume::VALIDITY }>>::transmute(src) |
| 280 | /// }) |
| 281 | /// } else { |
| 282 | /// None |
| 283 | /// }; |
| 284 | /// |
| 285 | /// assert_eq!(maybe_dst, Some(true)); |
| 286 | /// ``` |
| 287 | pub validity: bool, |
| 288 | } |
| 289 | |
| 290 | #[unstable (feature = "transmutability" , issue = "99571" )] |
| 291 | impl ConstParamTy_ for Assume {} |
| 292 | #[unstable (feature = "transmutability" , issue = "99571" )] |
| 293 | impl UnsizedConstParamTy for Assume {} |
| 294 | |
| 295 | impl 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" )] |
| 412 | impl 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" )] |
| 423 | impl 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 | } |
| 430 | |