diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 33b812ec59ff9..a9d23ab234a67 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -148,7 +148,7 @@ use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, }; use core::pin::Pin; -use core::ptr::{self, Unique}; +use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; use crate::alloc::{handle_alloc_error, AllocError, Allocator, Global, Layout}; @@ -1168,6 +1168,22 @@ impl From for Box { } } +#[stable(feature = "nonnull_from_box", since = "1.51.0")] +impl From> for NonNull { + /// Convert a `Box` into a [`NonNull`](core::ptr::NonNull). + /// + /// After calling this function, the caller is responsible for eventually + /// releasing the memory previously managed by the `Box` (for example, via + /// [`Box::from_raw`]). + #[inline] + #[must_use = "this will leak memory if unused"] + fn from(b: Box) -> Self { + // Safety: Box's pointer is guaranteed to be nonnull, so we can use + // new_unchecked. + unsafe { NonNull::new_unchecked(Box::into_raw(b)) } + } +} + #[stable(feature = "pin", since = "1.33.0")] impl From> for Pin> where diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 6a83f5da87cc8..871163e373809 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -57,3 +57,19 @@ fn box_deref_lval() { x.set(1000); assert_eq!(x.get(), 1000); } + +#[test] +fn nonnull_from_box() { + let x = Box::new(5); + let p = NonNull::from(x); + assert_eq!(unsafe { *p.as_ref() }, 5); + let _ = unsafe { Box::from_raw(p.as_ptr()) }; +} + +#[test] +fn nonnull_from_box_dynsized() { + let s: Box = "foo".into(); + let ps = NonNull::from(s); + let s_again = unsafe { Box::from_raw(ps.as_ptr()) }; + assert_eq!(&*s_again, "foo"); +}