Skip to content

NonNull::{from_ref, from_mut} #333

Closed
@jhpratt

Description

@jhpratt

Proposal

Problem statement

The only way to construct a NonNull from a (mutable) reference is to either use NonNull::new_unchecked or NonNull::from. The former requires unsafe in addition to core::ptr::from_ref or casts for shared references, while the latter does not necessarily guarantee that there is no type conversion taking place.

Motivating examples or use cases

use std::ptr::NonNull;

struct Foo;
struct Bar;

impl From<&Foo> for NonNull<Bar> {
    fn from(_: &Foo) -> Self {
        unimplemented!()
    }
}

We are trying to avoid a situation where adding an implementation like this in conjunction with refactoring would result in a silent change to NonNull::from. For this reason we are currently using new_unchecked, though this is naturally less than ideal. Internally, I will be introducing an extension trait identical to the below to avoid both unsafe and the drawbacks.

Solution sketch

impl<T: ?Sized> NonNull<T> {
    #[unstable(feature = "nonnull_from_ref", issue = "TODO")]
    #[rustc_const_unstable(feature = "nonnull_from_ref", issue = "TODO")]
    pub const fn from_ref(r: &T) -> Self {
        // Safety: `r` is a reference that is guaranteed to be non-null.
        unsafe { NonNull::new_unchecked(core::ptr::from_ref(r).cast_mut()) }
    }

    #[unstable(feature = "nonnull_from_ref", issue = "TODO")]
    #[rustc_const_unstable(feature = "nonnull_from_ref", issue = "TODO")]
    pub const fn from_mut(r: &mut T) -> Self {
        // Safety: `r` is a reference that is guaranteed to be non-null.
        unsafe { NonNull::new_unchecked(core::ptr::from_mut(r)) }
    }
}

Alternatives

As with most library changes, the only alternatives are to not doing this and to leave it to the ecosystem.

Links and related work

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions