diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 2fff3f0efd73a..aef6ba31abb99 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1182,7 +1182,7 @@ impl fmt::Debug for Discriminant { /// // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union` /// // between `repr(C)` structs, each of which has the `u8` discriminant as its first /// // field, so we can read the discriminant without offsetting the pointer. -/// unsafe { *<*const _>::from(self).cast::() } +/// unsafe { *(self as *const Enum).cast::() } /// } /// } /// diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 926189a17b204..c444d641eb033 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1764,3 +1764,20 @@ impl PartialOrd for *const T { *self >= *other } } + +#[stable(feature = "pointer_from_option_ref", since = "CURRENT_RUSTC_VERSION")] +impl From> for *const T { + /// Converts from an optional reference to a raw pointer, returning [`ptr::null`] if `x` is `None`. + /// + /// Because of the [null pointer optimization][npo], this is a zero-cost transformation. + /// + /// [npo]: https://doc.rust-lang.org/std/option/index.html#representation + /// [`ptr::null`]: crate::ptr::null() + #[inline] + fn from(x: Option<&T>) -> *const T { + match x { + Some(x) => x, + None => null(), + } + } +} diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index c6f43857887c9..539d0d8851bbf 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -2203,3 +2203,20 @@ impl PartialOrd for *mut T { *self >= *other } } + +#[stable(feature = "pointer_from_option_ref", since = "CURRENT_RUSTC_VERSION")] +impl From> for *mut T { + /// Converts from an optional mutable reference to a raw pointer, providing [`ptr::null_mut`] if it is `None`. + /// + /// Because of the [null pointer optimization][npo], this is a zero-cost transformation. + /// + /// [npo]: https://doc.rust-lang.org/std/option/index.html#representation + /// [`ptr::null_mut`]: crate::ptr::null_mut() + #[inline] + fn from(x: Option<&mut T>) -> *mut T { + match x { + Some(x) => x, + None => null_mut(), + } + } +} diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index ee885adfeee61..6252d178b1795 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1126,3 +1126,28 @@ fn test_const_copy() { assert!(*ptr2 == 1); }; } + +#[test] +fn test_from_option_ref() { + let none_ref: Option<&i32> = None; + let some_ref: Option<&i32> = Some(&10); + + let non_const_ptr: *const i32 = none_ref.into(); + let some_const_ptr: *const i32 = some_ref.into(); + + assert!(non_const_ptr.is_null()); + assert!(!some_const_ptr.is_null()); + assert_eq!(unsafe { some_const_ptr.read() }, 10); + + let mut val: i32 = 20; + let none_mut: Option<&mut i32> = None; + let some_mut: Option<&mut i32> = Some(&mut val); + + let none_mut_ptr: *mut i32 = none_mut.into(); + let some_mut_ptr: *mut i32 = some_mut.into(); + + assert!(none_mut_ptr.is_null()); + assert!(!some_mut_ptr.is_null()); + assert_eq!(unsafe { some_mut_ptr.replace(30) }, 20); + assert_eq!(unsafe { some_mut_ptr.read() }, 30); +}