From 19f1bdcf064e8259a622e2b8add5f7e361f65d8a Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Mon, 28 Aug 2023 21:40:55 -0700 Subject: [PATCH] Implement FromZeroes for thin raw pointers Makes progress on #170 --- src/lib.rs | 37 +++++++++++++++++++ .../ui-nightly/derive_transparent.stderr | 4 +- .../tests/ui-nightly/late_compile_pass.stderr | 8 ++-- .../tests/ui-stable/derive_transparent.stderr | 4 +- .../tests/ui-stable/late_compile_pass.stderr | 8 ++-- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fc5cd78109..4f57af6563 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -945,6 +945,40 @@ safety_comment! { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop); assert_unaligned!(ManuallyDrop<()>, ManuallyDrop); } +safety_comment! { + /// SAFETY: + /// The all-zeroes const and mut raw pointers are valid, and it is sound to + /// materialize them from nothing. The existence of `ptr::null` [1] and + /// `ptr::null_mut` [2], which are safe functions, guarantees this (if this + /// were not sound, these functions could not exist). Unlike non-null + /// pointers, it is always unsound to dereference null pointers, and so it's + /// not a footgun that converting from zeroes may not preserve pointer + /// provenance information. + /// + /// Since the encoding of fat pointers is not currently defined by the + /// reference, it would not be sound to implement `FromZeroes` for fat + /// pointer types such `*const T` for `T: ?Sized` or even for more + /// constrained pointer types such as `*const [T]` for `T: Sized`. + /// + /// Currently, though it would likely be sound, we choose not to implement + /// `FromBytes` or `AsBytes` for raw pointers because it would be easy for + /// code to mistakenly assume that converting from a raw pointer to a + /// different representation (such as a byte array) and back again via + /// `FromBytes` and `AsBytes` would result in a semantically identical + /// pointer. Thanks to provenance information, that may not actually be + /// true, so this would present a serious footgun. Note that this aspect of + /// Rust's memory model is still up in the air, so it's possible that these + /// conversions will one day be determined to be sound, at which point we + /// could choose to support these impls. See #170 for more information. + /// + /// [1] https://doc.rust-lang.org/core/ptr/fn.null.html + /// [2] https://doc.rust-lang.org/core/ptr/fn.null_mut.html + // TODO(https://github.com/rust-lang/reference/pull/1392#issuecomment-1696768191): + // Once the validity of materializing null pointers is guaranteed in the + // reference, cite that instead of `null` and `null_mut`. + unsafe_impl!(T: Sized => FromZeroes for *const T); + unsafe_impl!(T: Sized => FromZeroes for *mut T); +} safety_comment! { /// SAFETY: /// Per the reference [1]: @@ -3983,6 +4017,9 @@ mod tests { assert_impls!(Unalign: FromZeroes, FromBytes, AsBytes, Unaligned); assert_impls!(Unalign: Unaligned, !FromZeroes, !FromBytes, !AsBytes); + assert_impls!(*const NotZerocopy: FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*mut NotZerocopy: FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!([u8]: FromZeroes, FromBytes, AsBytes, Unaligned); assert_impls!([NotZerocopy]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); assert_impls!([u8; 0]: FromZeroes, FromBytes, AsBytes, Unaligned); diff --git a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr index 5a7d507b9e..bf596afd66 100644 --- a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr @@ -6,13 +6,13 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 I128 I16 - I32 - I64 and $N others note: required for `TransparentStruct` to implement `FromZeroes` --> tests/ui-nightly/derive_transparent.rs:23:19 diff --git a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr index fbf9da78ae..b3b9e38e42 100644 --- a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr @@ -6,13 +6,13 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 FromZeroes1 I128 - I16 - I32 and $N others = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable @@ -46,13 +46,13 @@ error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 FromZeroes1 I128 - I16 - I32 and $N others note: required by a bound in `FromBytes` --> $WORKSPACE/src/lib.rs diff --git a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr index 3810defe35..734a65b694 100644 --- a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr @@ -6,13 +6,13 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 I128 I16 - I32 - I64 and $N others note: required for `TransparentStruct` to implement `FromZeroes` --> tests/ui-stable/derive_transparent.rs:23:19 diff --git a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr index eab9b97f9b..19c7fc7bf5 100644 --- a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr @@ -6,13 +6,13 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 FromZeroes1 I128 - I16 - I32 and $N others = help: see issue #48214 = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -44,13 +44,13 @@ error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied | = help: the following other types implement trait `FromZeroes`: () + *const T + *mut T AU16 F32 F64 FromZeroes1 I128 - I16 - I32 and $N others note: required by a bound in `FromBytes` --> $WORKSPACE/src/lib.rs