From 73ada2d40429488aaaacf37b608bababc137b910 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:07:38 +0100 Subject: [PATCH 1/8] Explicitly document the size guarantees that Option makes. Triggered by a discussion on wg-unsafe-code-guidelines about which layouts of `Option` one can guarantee are optimised to a single pointer. --- library/core/src/option.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 3c7211fe040..745b0f1ae8d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -70,10 +70,18 @@ //! } //! ``` //! -//! This usage of [`Option`] to create safe nullable pointers is so -//! common that Rust does special optimizations to make the -//! representation of [`Option`]`<`[`Box`]`>` a single pointer. Optional pointers -//! in Rust are stored as efficiently as any other pointer type. +//! # Representation +//! +//! Rust guarantees to optimise the following inner types such that an [`Option`] which contains +//! them has the same size as a pointer: +//! +//! * `&T` +//! * `&mut T` +//! * `extern "C" fn` +//! * [`num::NonZero*`] +//! * [`ptr::NonNull`] +//! * `#[repr(transparent)]` struct around one of the types in this list. +//! * [`Box`] //! //! # Examples //! From f5118a525fcf9db4102d903650331039158eff11 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:36:55 +0100 Subject: [PATCH 2/8] Clarify and add guarantee about `transmute`. --- library/core/src/option.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 745b0f1ae8d..c1837f79840 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -72,16 +72,19 @@ //! //! # Representation //! -//! Rust guarantees to optimise the following inner types such that an [`Option`] which contains -//! them has the same size as a pointer: +//! Rust guarantees to optimize the following types `` such that an +//! [`Option`] has the same size as `T`: //! +//! * [`Box`] //! * `&T` //! * `&mut T` //! * `extern "C" fn` //! * [`num::NonZero*`] //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. -//! * [`Box`] +//! +//! For the above cases, it is guaranteed that one can use [`mem::transmute`] +//! between `T` and `Option` and vice versa. //! //! # Examples //! From 83f47aa11bd664ed8a15ef9833063833b7b3e71c Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:47:37 +0100 Subject: [PATCH 3/8] Be clear about the reverse `transmute` guarantees. --- library/core/src/option.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c1837f79840..db7583b0419 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -83,8 +83,9 @@ //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. //! -//! For the above cases, it is guaranteed that one can use [`mem::transmute`] -//! between `T` and `Option` and vice versa. +//! For the above cases, it is guaranteed that one can [`mem::transmute`] +//! from all valid values of `T` to `Option` but only from non-`None` +//! Option` to `T`. //! //! # Examples //! From f3d7196caec3f54e572c7389b1cef9fd9e62c1ed Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:53:58 +0100 Subject: [PATCH 4/8] Be clearer about Some/None transmute. --- library/core/src/option.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index db7583b0419..a8337c171a5 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -84,8 +84,9 @@ //! * `#[repr(transparent)]` struct around one of the types in this list. //! //! For the above cases, it is guaranteed that one can [`mem::transmute`] -//! from all valid values of `T` to `Option` but only from non-`None` -//! Option` to `T`. +//! from all valid values of `T` to `Option` but only from +//! `Option::Some(T)` to `T` (i.e. transmuting `None` to `` is undefined +//! behaviour). //! //! # Examples //! From 8cb8955d570c76631840bfc98825ca49c0dd8eea Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:19:46 +0000 Subject: [PATCH 5/8] Change notation. Co-authored-by: Ralf Jung --- library/core/src/option.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a8337c171a5..b8a501298c4 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -84,8 +84,8 @@ //! * `#[repr(transparent)]` struct around one of the types in this list. //! //! For the above cases, it is guaranteed that one can [`mem::transmute`] -//! from all valid values of `T` to `Option` but only from -//! `Option::Some(T)` to `T` (i.e. transmuting `None` to `` is undefined +//! from all valid values of `T` to `Option` and from +//! `Some::(_)` to `T` (but transmuting `None::` to `T` is undefined //! behaviour). //! //! # Examples From 55802e3bf3bf6d1db5c76aea581a7912bd752890 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Wed, 12 Aug 2020 15:38:18 +0000 Subject: [PATCH 6/8] Add Rust function pointers. Co-authored-by: Ralf Jung --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b8a501298c4..70b1abbc2a5 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -78,7 +78,7 @@ //! * [`Box`] //! * `&T` //! * `&mut T` -//! * `extern "C" fn` +//! * `fn`, `extern "C" fn` //! * [`num::NonZero*`] //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. From 68209c3fe4e0f5c3758f18e98efc175af31c2e51 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 17 Aug 2020 09:31:09 +0100 Subject: [PATCH 7/8] Rename the types for clarity. --- library/core/src/option.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 70b1abbc2a5..9789bce82dd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -72,15 +72,15 @@ //! //! # Representation //! -//! Rust guarantees to optimize the following types `` such that an +//! Rust guarantees to optimize the following types `T` such that //! [`Option`] has the same size as `T`: //! -//! * [`Box`] -//! * `&T` -//! * `&mut T` +//! * [`Box`] +//! * `&U` +//! * `&mut U` //! * `fn`, `extern "C" fn` //! * [`num::NonZero*`] -//! * [`ptr::NonNull`] +//! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. //! //! For the above cases, it is guaranteed that one can [`mem::transmute`] From 9bac5774d7b452b2227c9fb77a4c6de3f432ee55 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 17 Aug 2020 09:34:15 +0100 Subject: [PATCH 8/8] Grammar tweak. --- library/core/src/option.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 9789bce82dd..2f588e79bda 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -83,10 +83,10 @@ //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. //! -//! For the above cases, it is guaranteed that one can [`mem::transmute`] -//! from all valid values of `T` to `Option` and from -//! `Some::(_)` to `T` (but transmuting `None::` to `T` is undefined -//! behaviour). +//! It is further guaranteed that, for the cases above, one can +//! [`mem::transmute`] from all valid values of `T` to `Option` and +//! from `Some::(_)` to `T` (but transmuting `None::` to `T` +//! is undefined behaviour). //! //! # Examples //!