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: 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.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.

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();
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.87.0 (const: 1.87.0) · Source

pub const unsafe fn offset_from_unsigned(self, subtracted: NonNull<T>) -> usize
where T: Sized,

Calculates the distance between two pointers within the same allocation, where it’s known that self is equal to or greater than origin. The returned value is in units of T: the distance in bytes is divided by size_of::<T>().

This computes the same value that offset_from would compute, but with the added precondition that the offset is guaranteed to be non-negative. This method is equivalent to usize::try_from(self.offset_from(origin)).unwrap_unchecked(), but it provides slightly more information to the optimizer, which can sometimes allow it to optimize slightly better with some backends.

This method can be though of as recovering the count that was passed to add (or, with the parameters in the other order, to sub). The following are all equivalent, assuming that their safety preconditions are met:

ptr.offset_from_unsigned(origin) == count
origin.add(count) == ptr
ptr.sub(count) == origin
§Safety
  • The distance between the pointers must be non-negative (self >= origin)

  • All the safety conditions of offset_from apply to this method as well; see it for the full details.

Importantly, despite the return type of this method being able to represent a larger offset, it’s still not permitted to pass pointers which differ by more than isize::MAX bytes. As such, the result of this method will always be less than or equal to isize::MAX as usize.

§Panics

This function panics if T is a Zero-Sized Type (“ZST”).

§Examples
use std::ptr::NonNull;

let a = [0; 5];
let ptr1: NonNull<u32> = NonNull::from(&a[1]);
let ptr2: NonNull<u32> = NonNull::from(&a[3]);
unsafe {
    assert_eq!(ptr2.offset_from_unsigned(ptr1), 2);
    assert_eq!(ptr1.add(2), ptr2);
    assert_eq!(ptr2.sub(2), ptr1);
    assert_eq!(ptr2.offset_from_unsigned(ptr2), 0);
}

// This would be incorrect, as the pointers are not correctly ordered:
// ptr1.offset_from_unsigned(ptr2)

Trait Implementations§

1.25.0 · Source§

impl<T: PointeeSized> Clone for NonNull<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)
where Self:,

Performs copy-assignment from source. Read more
1.25.0 · Source§

impl<T: PointeeSized> PartialEq for NonNull<T>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
1.25.0 · Source§

impl<T: PointeeSized> Copy for NonNull<T>

1.25.0 · Source§

impl<T: PointeeSized> !Send for NonNull<T>

NonNull pointers are not Send because the data they reference may be aliased.

1.25.0 · Source§

impl<T: PointeeSized> !Sync for NonNull<T>

NonNull pointers are not Sync because the data they reference may be aliased.

Auto Trait Implementations§

§

impl<T> Freeze for NonNull<T>
where T: ?Sized,

§

impl<T> Unpin for NonNull<T>
where T: Unpin + ?Sized,

Blanket Implementations§

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.