Skip to content

Commit

Permalink
Rollup merge of rust-lang#134325 - theemathas:is_null-docs, r=RalfJung
Browse files Browse the repository at this point in the history
Correctly document CTFE behavior of is_null and methods that call is_null.

The "panic in const if CTFE doesn't know the answer" behavior was discussed to be the desired behavior in rust-lang#74939, and is currently how the function actually behaves.

I intentionally wrote this documentation to allow for the possibility that a panic might not occur even if the pointer is out of bounds, because of rust-lang#133700 and other potential changes in the future.

This is beta-nominated since `const fn is_null` stabilization is in beta already but the docs there are wrong, and it seems better to have the docs be correct at the time of stabilization.
  • Loading branch information
matthiaskrgr authored Dec 21, 2024
2 parents 51df98d + e6efbb2 commit 3aedae2
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 14 deletions.
38 changes: 31 additions & 7 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ impl<T: ?Sized> *const T {
/// Therefore, two pointers that are null may still not compare equal to
/// each other.
///
/// ## Behavior during const evaluation
/// # Panics during const evaluation
///
/// When this function is used during const evaluation, it may return `false` for pointers
/// that turn out to be null at runtime. Specifically, when a pointer to some memory
/// is offset beyond its bounds in such a way that the resulting pointer is null,
/// the function will still return `false`. There is no way for CTFE to know
/// the absolute position of that memory, so we cannot tell if the pointer is
/// null or not.
/// If this method is used during const evaluation, and `self` is a pointer
/// that is offset beyond the bounds of the memory it initially pointed to,
/// then there might not be enough information to determine whether the
/// pointer is null. This is because the absolute address in memory is not
/// known at compile time. If the nullness of the pointer cannot be
/// determined, this method will panic.
///
/// In-bounds pointers are never null, so the method will never panic for
/// such pointers.
///
/// # Examples
///
Expand Down Expand Up @@ -254,6 +257,13 @@ impl<T: ?Sized> *const T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # 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.
///
/// [`is_null`]: #method.is_null
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -331,6 +341,13 @@ impl<T: ?Sized> *const T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # 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.
///
/// [`is_null`]: #method.is_null
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -1607,6 +1624,13 @@ impl<T> *const [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # 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.
///
/// [`is_null`]: #method.is_null
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
Expand Down
58 changes: 51 additions & 7 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ impl<T: ?Sized> *mut T {
/// Therefore, two pointers that are null may still not compare equal to
/// each other.
///
/// ## Behavior during const evaluation
/// # Panics during const evaluation
///
/// When this function is used during const evaluation, it may return `false` for pointers
/// that turn out to be null at runtime. Specifically, when a pointer to some memory
/// is offset beyond its bounds in such a way that the resulting pointer is null,
/// the function will still return `false`. There is no way for CTFE to know
/// the absolute position of that memory, so we cannot tell if the pointer is
/// null or not.
/// If this method is used during const evaluation, and `self` is a pointer
/// that is offset beyond the bounds of the memory it initially pointed to,
/// then there might not be enough information to determine whether the
/// pointer is null. This is because the absolute address in memory is not
/// known at compile time. If the nullness of the pointer cannot be
/// determined, this method will panic.
///
/// In-bounds pointers are never null, so the method will never panic for
/// such pointers.
///
/// # Examples
///
Expand Down Expand Up @@ -243,6 +246,13 @@ impl<T: ?Sized> *mut T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -327,6 +337,13 @@ impl<T: ?Sized> *mut T {
/// Note that because the created reference is to `MaybeUninit<T>`, the
/// source pointer can point to uninitialized memory.
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -590,6 +607,12 @@ impl<T: ?Sized> *mut T {
/// the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
Expand Down Expand Up @@ -673,6 +696,13 @@ impl<T: ?Sized> *mut T {
///
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
Expand Down Expand Up @@ -1949,6 +1979,13 @@ impl<T> *mut [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
Expand Down Expand Up @@ -2000,6 +2037,13 @@ impl<T> *mut [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # 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.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
Expand Down
7 changes: 7 additions & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ impl<T: ?Sized> NonNull<T> {

/// 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.
///
/// [`is_null`]: ../primitive.pointer.html#method.is_null-1
///
/// # Examples
///
/// ```
Expand Down

0 comments on commit 3aedae2

Please sign in to comment.