Skip to content

Commit

Permalink
Extend ptr::null and null_mut to all thin (including extern) types
Browse files Browse the repository at this point in the history
Fixes rust-lang#93959

This change was accepted in https://rust-lang.github.io/rfcs/2580-ptr-meta.html

Note that this changes the signature of **stable** functions.
The change should be backward-compatible, but it is **insta-stable**
since it cannot (easily, at all?) be made available only
through a `#![feature(…)]` opt-in.

The RFC also proposed the same change for `NonNull::dangling`,
which makes sense it terms of its signature but not in terms of its implementation.
`dangling` uses `align_of()` as an address. But what `align_of()` should be for
extern types or whether it should be allowed at all remains an open question.

This commit depends on rust-lang#93977, which is not yet
part of the bootstrap compiler. So `#[cfg]` is used to only apply the change in
stage 1+. As far a I know bounds cannot be made conditional with `#[cfg]`, so the
entire functions are duplicated. This is unfortunate but temporary.

Since this duplication makes it less obvious in the diff,
the new definitions differ in:

* More permissive bounds (`Thin` instead of implied `Sized`)
* Different implementation
* Having `rustc_allow_const_fn_unstable(ptr_metadata)`
  • Loading branch information
SimonSapin committed May 13, 2022
1 parent 1c80ac0 commit 7ccc09b
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 1 deletion.
46 changes: 46 additions & 0 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,33 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_diagnostic_item = "ptr_null"]
#[cfg(bootstrap)]
pub const fn null<T>() -> *const T {
invalid(0)
}

/// Creates a null raw pointer.
///
/// # Examples
///
/// ```
/// use std::ptr;
///
/// let p: *const i32 = ptr::null();
/// assert!(p.is_null());
/// ```
#[inline(always)]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_allow_const_fn_unstable(ptr_metadata)]
#[rustc_diagnostic_item = "ptr_null"]
#[cfg(not(bootstrap))]
pub const fn null<T: ?Sized + Thin>() -> *const T {
from_raw_parts(0 as *const (), ())
}

/// Creates a null mutable raw pointer.
///
/// # Examples
Expand All @@ -527,6 +550,7 @@ pub const fn null<T>() -> *const T {
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_diagnostic_item = "ptr_null_mut"]
#[cfg(bootstrap)]
pub const fn null_mut<T>() -> *mut T {
invalid_mut(0)
}
Expand Down Expand Up @@ -657,6 +681,28 @@ where
addr as *mut T
}

/// Creates a null mutable raw pointer.
///
/// # Examples
///
/// ```
/// use std::ptr;
///
/// let p: *mut i32 = ptr::null_mut();
/// assert!(p.is_null());
/// ```
#[inline(always)]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
#[rustc_allow_const_fn_unstable(ptr_metadata)]
#[rustc_diagnostic_item = "ptr_null_mut"]
#[cfg(not(bootstrap))]
pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
from_raw_parts_mut(0 as *mut (), ())
}

/// Forms a raw slice from a pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
Expand Down
12 changes: 12 additions & 0 deletions library/core/tests/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ fn test_is_null() {

let nmi: *mut dyn ToString = null_mut::<isize>();
assert!(nmi.is_null());

#[cfg(not(bootstrap))]
{
extern "C" {
type Extern;
}
let ec: *const Extern = null::<Extern>();
assert!(ec.is_null());

let em: *mut Extern = null_mut::<Extern>();
assert!(em.is_null());
}
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/cast/casts-issue-46365.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ struct Lorem {
}

fn main() {
let _foo: *mut Lorem = core::ptr::null_mut(); // no error here
let _foo: *mut Lorem = core::ptr::NonNull::dangling().as_ptr(); // no error here
}

0 comments on commit 7ccc09b

Please sign in to comment.