rust-lang / libs-team

The home of the library team
Apache License 2.0
123 stars 19 forks source link

ACP: Add `from_ref` and `from_mut` constructors to `core::ptr::NonNull`. #448

Closed bjoernager closed 1 week ago

bjoernager commented 1 week ago

Proposal

Problem statement

To create a core::ptr::NonNull object from a reference, one can simply use the provided From implementation. But in constant expressions (const functions/blocks), trait methods are (mostly) forbidden, and one currently has to resort to more complicated work arounds.

Motivating examples or use cases

To circumvent the trait restrictions, one could instead first create a raw pointer and then construct the relevant non-null pointer from the raw pointer:

let mut value = /* something... */;

// SAFETY: References can never be null.
let non_null = unsafe { core::ptr::NonNull::new_unchecked(core::ptr::from_mut(&mut value)) };

with raw_ref_op, however, this can be simplified to the following:

let mut value = /* something... */;

// SAFETY: References can never be null.
let non_null = unsafe { core::ptr::NonNull::new_unchecked(&raw mut value) };

But this is still unnecessarily complicated for an operation that should be a no-op.

Solution sketch

I propose adding the from_ref and from_mut constructors for parity with the similar global functions in core::ptr:

// core::ptr

impl<T: ?Sized> NonNull<T> {
    pub const fn from_ref(r: &T) -> Self;

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

Which would allow directly constructing a non-null pointer like the following:

let mut value = /* something... */;

let non_null = core::ptr::NonNull::from_mut(&mut value);

The latter constructor is inherently unblocked by the stabilisation of const_mut_refs.

Alternatives

An alternative solution would be to directly allow primitive casts to the NonNull type:

let mut value = /* something... /*;

let non_null = &mut value as core::ptr::NonNull;

Although I doubt this would actually be preferred over the primary solution.

Another alternative would be to allow traits in constant expressions, but this is already covered by const_trait_impl.

Links and related work

The #130822 PR implements the from_ref and from_mut constructors behind the non_null_from_ref feature gate. The #130823 issue tracks this feature gate.

dtolnay commented 1 week ago

:+1: This makes sense to me. Thank you for your work on this feature.