NonNull

Struct NonNull 

1.25.0 · Source
pub struct NonNull<T: PointeeSized> { /* private fields */ }
Expand description

*mut T but non-zero and covariant.

This is often the correct thing to use when building data structures using raw pointers, but is ultimately more dangerous to use because of its additional properties. If you’re not sure if you should use NonNull<T>, just use *mut T!

Unlike *mut T, the pointer must always be non-null, even if the pointer is never dereferenced. This is so that enums may use this forbidden value as a discriminant – Option<NonNull<T>> has the same size as *mut T. However the pointer may still dangle if it isn’t dereferenced.

Unlike *mut T, NonNull<T> is covariant over T. This is usually the correct choice for most data structures and safe abstractions, such as Box, Rc, Arc, Vec, and LinkedList.

In rare cases, if your type exposes a way to mutate the value of T through a NonNull<T>, and you need to prevent unsoundness from variance (for example, if T could be a reference with a shorter lifetime), you should add a field to make your type invariant, such as PhantomData<Cell<T>> or PhantomData<&'a mut T>.

Example of a type that must be invariant:

use std::cell::Cell;
use std::marker::PhantomData;
struct Invariant<T> {
    ptr: std::ptr::NonNull<T>,
    _invariant: PhantomData<Cell<T>>,
}

Notice that NonNull<T> has a From instance for &T. However, this does not change the fact that mutating through a (pointer derived from a) shared reference is undefined behavior unless the mutation happens inside an UnsafeCell<T>. The same goes for creating a mutable reference from a shared reference. When using this From instance without an UnsafeCell<T>, it is your responsibility to ensure that as_mut is never called, and as_ptr is never used for mutation.

§Representation

Thanks to the null pointer optimization, NonNull<T> and Option<NonNull<T>> are guaranteed to have the same size and alignment:

use std::ptr::NonNull;

assert_eq!(size_of::<NonNull<i16>>(), size_of::<Option<NonNull<i16>>>());
assert_eq!(align_of::<NonNull<i16>>(), align_of::<Option<NonNull<i16>>>());

assert_eq!(size_of::<NonNull<str>>(), size_of::<Option<NonNull<str>>>());
assert_eq!(align_of::<NonNull<str>>(), align_of::<Option<NonNull<str>>>());

Implementations§

Source§

impl<T: Sized> NonNull<T>

1.89.0 (const: 1.89.0) · Source

pub const fn without_provenance(addr: NonZero<usize>) -> Self

Creates a pointer with the given address and no provenance.

For more details, see the equivalent method on a raw pointer, ptr::without_provenance_mut.

This is a Strict Provenance API.

1.25.0 (const: 1.36.0) · Source

pub const fn dangling() -> Self

Creates a new NonNull that is dangling, but well-aligned.

This is useful for initializing types which lazily allocate, like Vec::new does.

Note that the address of the returned pointer may potentially be that of a valid pointer, which means this must not be used as a “not yet initialized” sentinel value. Types that lazily allocate must track initialization by some other means.

§Examples
use std::ptr::NonNull;

let ptr = NonNull::<u32>::dangling();
// Important: don't try to access the value of `ptr` without
// initializing it first! The pointer is not null but isn't valid either!
1.89.0 · Source

pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self

Converts an address back to a mutable pointer, picking up some previously ‘exposed’ provenance.

For more details, see the equivalent method on a raw pointer, ptr::with_exposed_provenance_mut.

This is an Exposed Provenance API.

Source

pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit<T>

🔬This is a nightly-only experimental API. (ptr_as_uninit #75402)

Returns a shared references to the value. In contrast to as_ref, this does not require that the value has to be initialized.

For the mutable counterpart see as_uninit_mut.

§Safety

When calling this method, you have to ensure that the pointer is convertible to a reference. Note that because the created reference is to MaybeUninit<T>, the source pointer can point to uninitialized memory.

Source

pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit<T>

🔬This is a nightly-only experimental API. (ptr_as_uninit #75402)

Returns a unique references to the value. In contrast to as_mut, this does not require that the value has to be initialized.

For the shared counterpart see as_uninit_ref.

§Safety

When calling this method, you have to ensure that the pointer is convertible to a reference. Note that because the created reference is to MaybeUninit<T>, the source pointer can point to uninitialized memory.

Source

pub const fn cast_array<const N: usize>(self) -> NonNull<[T; N]>

🔬This is a nightly-only experimental API. (ptr_cast_array #144514)

Casts from a pointer-to-T to a pointer-to-[T; N].

Source§

impl<T: PointeeSized> NonNull<T>

1.25.0 (const: 1.25.0) · Source

pub const unsafe fn new_unchecked(ptr: *mut T) -> Self

Creates a new NonNull.

§Safety

ptr must be non-null.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let ptr = unsafe { NonNull::new_unchecked(&mut x as *mut _) };

Incorrect usage of this function:

use std::ptr::NonNull;

// NEVER DO THAT!!! This is undefined behavior. ⚠️
let ptr = unsafe { NonNull::<u32>::new_unchecked(std::ptr::null_mut()) };
1.25.0 (const: 1.85.0) · Source

pub const fn new(ptr: *mut T) -> Option<Self>

Creates a new NonNull if ptr is non-null.

§Panics during const evaluation

This method will panic during const evaluation if the pointer cannot be determined to be null or not. See is_null for more information.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let ptr = NonNull::<u32>::new(&mut x as *mut _).expect("ptr is null!");

if let Some(ptr) = NonNull::<u32>::new(std::ptr::null_mut()) {
    unreachable!();
}
1.89.0 (const: 1.89.0) · Source

pub const fn from_ref(r: &T) -> Self

Converts a reference to a NonNull pointer.

1.89.0 (const: 1.89.0) · Source

pub const fn from_mut(r: &mut T) -> Self

Converts a mutable reference to a NonNull pointer.

Source

pub const fn from_raw_parts( data_pointer: NonNull<impl Thin>, metadata: <T as Pointee>::Metadata, ) -> NonNull<T>

🔬This is a nightly-only experimental API. (ptr_metadata #81513)

Performs the same functionality as std::ptr::from_raw_parts, except that a NonNull pointer is returned, as opposed to a raw *const pointer.

See the documentation of std::ptr::from_raw_parts for more details.

Source

pub const fn to_raw_parts(self) -> (NonNull<()>, <T as Pointee>::Metadata)

🔬This is a nightly-only experimental API. (ptr_metadata #81513)

Decompose a (possibly wide) pointer into its data pointer and metadata components.

The pointer can be later reconstructed with NonNull::from_raw_parts.

1.84.0 · Source

pub fn addr(self) -> NonZero<usize>

Gets the “address” portion of the pointer.

For more details, see the equivalent method on a raw pointer, pointer::addr.

This is a Strict Provenance API.

1.89.0 · Source

pub fn expose_provenance(self) -> NonZero<usize>

Exposes the “provenance” part of the pointer for future use in with_exposed_provenance and returns the “address” portion.

For more details, see the equivalent method on a raw pointer, pointer::expose_provenance.

This is an Exposed Provenance API.

1.84.0 · Source

pub fn with_addr(self, addr: NonZero<usize>) -> Self

Creates a new pointer with the given address and the provenance of self.

For more details, see the equivalent method on a raw pointer, pointer::with_addr.

This is a Strict Provenance API.

1.84.0 · Source

pub fn map_addr(self, f: impl FnOnce(NonZero<usize>) -> NonZero<usize>) -> Self

Creates a new pointer by mapping self’s address to a new one, preserving the provenance of self.

For more details, see the equivalent method on a raw pointer, pointer::map_addr.

This is a Strict Provenance API.

1.25.0 (const: 1.32.0) · Source

pub const fn as_ptr(self) -> *mut T

Acquires the underlying *mut pointer.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let ptr = NonNull::new(&mut x).expect("ptr is null!");

let x_value = unsafe { *ptr.as_ptr() };
assert_eq!(x_value, 0);

unsafe { *ptr.as_ptr() += 2; }
let x_value = unsafe { *ptr.as_ptr() };
assert_eq!(x_value, 2);
1.25.0 (const: 1.73.0) · Source

pub const unsafe fn as_ref<'a>(&self) -> &'a T

Returns a shared reference to the value. If the value may be uninitialized, as_uninit_ref must be used instead.

For the mutable counterpart see as_mut.

§Safety

When calling this method, you have to ensure that the pointer is convertible to a reference.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let ptr = NonNull::new(&mut x as *mut _).expect("ptr is null!");

let ref_x = unsafe { ptr.as_ref() };
println!("{ref_x}");
1.25.0 (const: 1.83.0) · Source

pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T

Returns a unique reference to the value. If the value may be uninitialized, as_uninit_mut must be used instead.

For the shared counterpart see as_ref.

§Safety

When calling this method, you have to ensure that the pointer is convertible to a reference.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let mut ptr = NonNull::new(&mut x).expect("null pointer");

let x_ref = unsafe { ptr.as_mut() };
assert_eq!(*x_ref, 0);
*x_ref += 2;
assert_eq!(*x_ref, 2);
1.27.0 (const: 1.36.0) · Source

pub const fn cast<U>(self) -> NonNull<U>

Casts to a pointer of another type.

§Examples
use std::ptr::NonNull;

let mut x = 0u32;
let ptr = NonNull::new(&mut x as *mut _).expect("null pointer");

let casted_ptr = ptr.cast::<i8>();
let raw_ptr: *mut i8 = casted_ptr.as_ptr();
Source

pub fn try_cast_aligned<U>(self) -> Option<NonNull<U>>

🔬This is a nightly-only experimental API. (pointer_try_cast_aligned #141221)

Try to cast to a pointer of another type by checking alignment.

If the pointer is properly aligned to the target type, it will be cast to the target type. Otherwise, None is returned.

§Examples
#![feature(pointer_try_cast_aligned)]
use std::ptr::NonNull;

let mut x = 0u64;

let aligned = NonNull::from_mut(&mut x);
let unaligned = unsafe { aligned.byte_add(1) };

assert!(aligned.try_cast_aligned::<u32>().is_some());
assert!(unaligned.try_cast_aligned::<u32>().is_none());
1.80.0 (const: 1.80.0) · Source

pub const unsafe fn offset(self, count: isize) -> Self
where T: Sized,

Adds an offset to a pointer.

count is in units of T; e.g., a count of 3 represents a pointer offset of 3 * size_of::<T>() bytes.

§Safety

If any of the following conditions are violated, the result is Undefined Behavior:

  • The computed offset, count * size_of::<T>() bytes, must not overflow isize.

  • If the computed offset is non-zero, then self must be derived from a pointer to some allocation, and the entire memory range between self and the result must be in bounds of that allocation. In particular, this range must not “wrap around” the edge of the address space.

Allocations can never be larger than isize::MAX bytes, so if the computed offset stays in bounds of the allocation, it is guaranteed to satisfy the first requirement. This implies, for instance, that vec.as_ptr().add(vec.len()) (for vec: Vec<T>) is always safe.

§Examples
use std::ptr::NonNull;

let mut s = [1, 2, 3];
let ptr: NonNull<u32> = NonNull::new(s.as_mut_ptr()).unwrap();

unsafe {
    println!("{}", ptr.offset(1).read());
    println!("{}", ptr.offset(2).read());
}
1.80.0 (const: 1.80.0) · Source

pub const unsafe fn byte_offset(self, count: isize) -> Self

Calculates the offset from a pointer in bytes.

count is in units of bytes.

This is purely a convenience for casting to a u8 pointer and using offset on it. See that method for documentation and safety requirements.

For non-Sized pointees this operation changes only the data pointer, leaving the metadata untouched.

1.80.0 (const: 1.80.0) · Source

pub const unsafe fn add(self, count: usize) -> Self
where T: Sized,

Adds an offset to a pointer (convenience for .offset(count as isize)).

count is in units of T; e.g., a count of 3 represents a pointer offset of 3 * size_of::<T>() bytes.

§Safety

If any of the following conditions are violated, the result is Undefined Behavior:

  • The computed offset, count * size_of::<T>() bytes, must not overflow isize.

  • If the computed offset is non-zero, then self must be derived from a pointer to some allocation, and the entire memory range between self and the result must be in bounds of that allocation. In particular, this range must not “wrap around” the edge of the address space.

Allocations can never be larger than isize::MAX bytes, so if the computed offset stays in bounds of the allocation, it is guaranteed to satisfy the first requirement. This implies, for instance, that vec.as_ptr().add(vec.len()) (for vec: Vec<T>) is always safe.

§Examples
use std::ptr::NonNull;

let s: &str = "123";
let ptr: NonNull<u8> = NonNull::new(s.as_ptr().cast_mut()).unwrap();

unsafe {
    println!("{}", ptr.add(1).read() as char);
    println!("{}", ptr.add(2).read() as char);
}
1.80.0 (const: 1.80.0) · Source

pub const unsafe fn byte_add(self, count: usize) -> Self