about summary refs log tree commit diff
path: root/library/core
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-04 07:55:44 +0000
committerbors <bors@rust-lang.org>2022-09-04 07:55:44 +0000
commit8521a8c92da6c0c845d4f6394e903651a227946a (patch)
tree18fff039f86b368a19865a2c5a563987ef4185d3 /library/core
parentc2d140bd36e7fcdc894b7c342fd81a63fdd66373 (diff)
parentfbcc038a224e58f7d3aca25c7f2321f11ce5513d (diff)
downloadrust-8521a8c92da6c0c845d4f6394e903651a227946a.tar.gz
rust-8521a8c92da6c0c845d4f6394e903651a227946a.zip
Auto merge of #100726 - jswrenn:transmute, r=oli-obk
safe transmute: use `Assume` struct to provide analysis options

This task was left as a TODO in #92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](https://github.com/rust-lang/compiler-team/issues/411).

**Before:**
```rust
pub unsafe trait BikeshedIntrinsicFrom<
    Src,
    Context,
    const ASSUME_ALIGNMENT: bool,
    const ASSUME_LIFETIMES: bool,
    const ASSUME_VALIDITY: bool,
    const ASSUME_VISIBILITY: bool,
> where
    Src: ?Sized,
{}
```
**After:**
```rust
pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
where
    Src: ?Sized,
{}
```

`Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change).

r? `@oli-obk`

---

Related:
- https://github.com/rust-lang/compiler-team/issues/411
- https://github.com/rust-lang/rust/issues/99571
Diffstat (limited to 'library/core')
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/mem/transmutability.rs88
2 files changed, 78 insertions, 12 deletions
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index bf75796f1fc..9d857eb63da 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -93,6 +93,7 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
+#![allow(incomplete_features)]
 //
 // Library features:
 #![feature(const_align_offset)]
@@ -160,6 +161,7 @@
 //
 // Language features:
 #![feature(abi_unadjusted)]
+#![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(associated_type_bounds)]
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index b4fabedad78..87a37863105 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -4,25 +4,20 @@
 /// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`,
 /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
 #[unstable(feature = "transmutability", issue = "99571")]
-#[lang = "transmute_trait"]
+#[cfg_attr(not(bootstrap), lang = "transmute_trait")]
 #[rustc_on_unimplemented(
     message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.",
     label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`."
 )]
-pub unsafe trait BikeshedIntrinsicFrom<
-    Src,
-    Context,
-    const ASSUME_ALIGNMENT: bool,
-    const ASSUME_LIFETIMES: bool,
-    const ASSUME_VALIDITY: bool,
-    const ASSUME_VISIBILITY: bool,
-> where
+pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
+where
     Src: ?Sized,
 {
 }
 
 /// What transmutation safety conditions shall the compiler assume that *you* are checking?
 #[unstable(feature = "transmutability", issue = "99571")]
+#[cfg_attr(not(bootstrap), lang = "transmute_opts")]
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct Assume {
     /// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that
@@ -33,11 +28,80 @@ pub struct Assume {
     /// that violates Rust's memory model.
     pub lifetimes: bool,
 
+    /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
+    /// type and field privacy of the destination type (and sometimes of the source type, too).
+    pub safety: bool,
+
     /// When `true`, the compiler assumes that *you* are ensuring that the source type is actually a valid
     /// instance of the destination type.
     pub validity: bool,
+}
 
-    /// When `true`, the compiler assumes that *you* have ensured that it is safe for you to violate the
-    /// type and field privacy of the destination type (and sometimes of the source type, too).
-    pub visibility: bool,
+impl Assume {
+    /// Do not assume that *you* have ensured any safety properties are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const NOTHING: Self =
+        Self { alignment: false, lifetimes: false, safety: false, validity: false };
+
+    /// Assume only that alignment conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const ALIGNMENT: Self = Self { alignment: true, ..Self::NOTHING };
+
+    /// Assume only that lifetime conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const LIFETIMES: Self = Self { lifetimes: true, ..Self::NOTHING };
+
+    /// Assume only that safety conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const SAFETY: Self = Self { safety: true, ..Self::NOTHING };
+
+    /// Assume only that dynamically-satisfiable validity conditions are met.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const VALIDITY: Self = Self { validity: true, ..Self::NOTHING };
+
+    /// Assume both `self` and `other_assumptions`.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const fn and(self, other_assumptions: Self) -> Self {
+        Self {
+            alignment: self.alignment || other_assumptions.alignment,
+            lifetimes: self.lifetimes || other_assumptions.lifetimes,
+            safety: self.safety || other_assumptions.safety,
+            validity: self.validity || other_assumptions.validity,
+        }
+    }
+
+    /// Assume `self`, excepting `other_assumptions`.
+    #[unstable(feature = "transmutability", issue = "99571")]
+    pub const fn but_not(self, other_assumptions: Self) -> Self {
+        Self {
+            alignment: self.alignment && !other_assumptions.alignment,
+            lifetimes: self.lifetimes && !other_assumptions.lifetimes,
+            safety: self.safety && !other_assumptions.safety,
+            validity: self.validity && !other_assumptions.validity,
+        }
+    }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Add for Assume {
+    type Output = Assume;
+
+    fn add(self, other_assumptions: Assume) -> Assume {
+        self.and(other_assumptions)
+    }
+}
+
+// FIXME(jswrenn): This const op is not actually usable. Why?
+// https://github.com/rust-lang/rust/pull/100726#issuecomment-1219928926
+#[unstable(feature = "transmutability", issue = "99571")]
+#[rustc_const_unstable(feature = "transmutability", issue = "99571")]
+impl const core::ops::Sub for Assume {
+    type Output = Assume;
+
+    fn sub(self, other_assumptions: Assume) -> Assume {
+        self.but_not(other_assumptions)
+    }
 }