Feature gate: maybe none? There’s no obvious way to use #[unstable] for this kind of library change.
This is a tracking issue for extending ptr::null, ptr::null_mut, and NonNull::dangling to work with any thin pointers. This change was accepted as part of RFC 2580 Pointer Metadata.
As of Rust 1.58:
- These functions can only return pointer to
T: Sized types. (This bound is implied by the lack of T: ?Sized pseudo-bound in their respective signature.)
extern types are the only kind of types that are not Sized 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 pointer metadata.)
So this description could be rephrased as extending ptr::null, ptr::null_mut, and NonNull::dangling to extern types. However future language proposals could potentially add new kinds of !Sized types whose pointers are thin. This change should then apply to such types too.
Motivation
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 Sized types.
However extern types add an intermediate kind of type that is !Sized but still still has thin pointers. The new Pointee 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 remains an open question for extern types.
Public API
These existing stable APIs of core::ptr / std::ptr:
pub const fn null<T>() -> *const T {…}
pub const fn null_mut<T>() -> *mut T {…}
Should be changed to
pub const fn null<T: ?Sized + Thin>() -> *const T {…}
pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {…}
… where Thin is an existing trait alias:
pub trait Thin = Pointee<Metadata = ()>;
pub trait Pointee {
type Metadata: Copy + Send + Sync + Ord + Hash + Unpin;
}
In 1.58, Pointee and Thin are both unstable and tracked at #81513. Pointee is automatically implemented for all types. For Sized and extern types, Metadata is (). So Sized implies Thin.
Because Sized implies Thin, 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 Pattern in str::find.)
Steps / History
Implementation strategy and related language change
null, null_mut, and dangling are implemented by converting an integer (zero or align_of()) to a raw pointer with the as operator. In Rust 1.58, as only allows such a conversion if the target type is a pointer to a Sized type. The obvious way to implement this proposed extension of null and friends would be to make the same extension to as. 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:
Cast expressions integer as *const T and integer as *mut T would change from being legal only if T: Sized, to being legal only if T: ?Sized + Thin.
Update: ptr::from_raw_parts could be used instead of as.
Unresolved Questions
Is the language change to the as operator described above desirable?
Should it separately go through the RFC process?
Feature gate: maybe none? There’s no obvious way to use
#[unstable]for this kind of library change.This is a tracking issue for extending
ptr::null,ptr::null_mut,andto work with any thin pointers. This change was accepted as part of RFC 2580 Pointer Metadata.NonNull::danglingAs of Rust 1.58:
T: Sizedtypes. (This bound is implied by the lack ofT: ?Sizedpseudo-bound in their respective signature.)externtypes are the only kind of types that are notSizedbut 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 pointer metadata.)So this description could be rephrased as extending
ptr::null,ptr::null_mut, andtoNonNull::danglingexterntypes. However future language proposals could potentially add new kinds of!Sizedtypes whose pointers are thin. This change should then apply to such types too.Motivation
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
Sizedtypes.However
externtypes add an intermediate kind of type that is!Sizedbut still still has thin pointers. The newPointeetrait 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 remains an open question forexterntypes.Public API
These existing stable APIs of
core::ptr/std::ptr:Should be changed to
… where
Thinis an existing trait alias:In 1.58,
PointeeandThinare both unstable and tracked at #81513.Pointeeis automatically implemented for all types. ForSizedandexterntypes,Metadatais(). SoSizedimpliesThin.Because
SizedimpliesThin, 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
Patterninstr::find.)Steps / History
Implementation strategy
and related language changenull,null_mut, anddanglingare implemented by converting an integer (zero oralign_of()) to a raw pointer with theasoperator. In Rust 1.58,asonly allows such a conversion if the target type is a pointer to aSizedtype. The obvious way to implement this proposed extension ofnulland friends would be to make the same extension toas. 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:
ptr::from_raw_partscould be used instead ofas.Unresolved Questions
Is the language change to theasoperator described above desirable?Should it separately go through the RFC process?