Change:
Feature gate: maybe none? There’s no obvious way to use for this kind of library change. This is a tracking issue for extending , , ~and ~ to work with any thin pointers. This change was accepted as part of . As of Rust 1.58: These functions can only return pointer to types. (This bound is implied by the lack of pseudo-bound in their respective signature.) are the only kind of types that are not but pointers to them are still “thin”. (As opposed to pointers to slices or trait objects, that are “wide” and store a length or a vtable pointer as .) So this description could be rephrased as extending , , and ~~ to types. However future language proposals could potentially add new kinds of types whose pointers are thin. This change should then apply to such types too. These functions deliberately do not support slices or trait objects. What length or vtable would be used in the new pointers? More generally, their implementation is only obvious for thin pointers. That is, when pointer metadata is zero-size, such as for types. However types add an intermediate kind of type that is but still still has thin pointers. The new trait from the Pointer Metadata RFC allows expressing more precise bounds within the trait system. That same RFC proposed the change tracked here and was accepted, but that change is not implemented yet so it for types. These existing stable APIs of / : Should be changed to … where is an existing trait alias: In 1.58, and are both unstable and tracked at is automatically implemented for all types. For and types, is . So implies . Because implies , this proposed change to the signatures of stable functions should be backward-compatible. Having an unstable trait involved in a bound of a stable function is unusual but not unprecedented. (For example in .) [ ] Implementation: #... [ ] Final comment period (FCP) [ ] Stabilization PR (?) <!-- Once the feature has gone through a few release cycles and there are no unresolved questions left, the feature might be ready for stabilization. If this feature didn't go through the RFC process, a final comment period (FCP) is always needed before stabilization. This works as follows: A library API team member can kick off the stabilization process, at which point the rfcbot will ask all the team members to verify they agree with stabilization. Once enough members agree and there are no concerns, the final comment period begins: this issue will be marked as such and will be listed in the next This Week in Rust newsletter. If no blocking concerns are raised in that period of 10 days, a stabilzation PR can be opened by anyone. --~, , and are implemented by converting an integer (zero or ) to a raw pointer with the operator. In Rust 1.58, only allows such a conversion if the target type is a pointer to a type. The obvious way to implement this proposed extension of and friends would be to make the same extension to . However this change in language semantics is not part of an accepted RFC. It should be approved by the language team, perhaps with its own RFC.~ ~To summarize, the proposed language change is:~ Update: could be used instead of . ~Is the language change to the operator described above desirable?~ ~Should it separately go through the RFC process?~
As , instead of of extending the implementation of could look like this: . So I’m withdrawing the language change proposal. (I someone else wants to propose the same elsewhere, feel free.)
In terms of its own signature seems like it could be extended to all thin pointers, but in terms of its behavior it relies of . What should (or ) be for extern types? Let’s… not get into that here. So not touching and only extending and .
We know that, but the compiler doesn’t (yet) … so this wrong. I in itself I get only one error, but it likely affects every user of or in a generic context where holds but doesn’t without an explicit bound: I tried encoding the desired implication with this: But this caused many errors like: I think this is because is defined as: So requires . Since , when asked specifically for the compile knows to resolve it to . But trait resolution doesn’t seem to be aware of the "equality".
I don't see a problem with defining since the trait is implemented by the compiler anyway. Is there any obstacle I don't see?
The obstacle is that things break when I do it, as described in my previous comment. It looks like might fix that.
Thanks for doing this

Discussion:
#[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_diagnostic_item = "ptr_null"] <ins> #[cfg(bootstrap)] </ins> pub const fn null<T>() -> *const T { invalid(0) } <ins> /// 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 (), ()) } </ins> /// Creates a null mutable raw pointer. /// /// # Examples

#[rustc_promotable] #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] #[rustc_diagnostic_item = "ptr_null_mut"] <ins> #[cfg(bootstrap)] </ins> pub const fn null_mut<T>() -> *mut T { invalid_mut(0) }

addr as *mut T } <ins> /// 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 (), ()) } </ins> /// Forms a raw slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes.

let nmi: *mut dyn ToString = null_mut::<isize>(); assert!(nmi.is_null()); <ins> #[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()); } </ins> } #[test]

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