-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue for extending null() and null_mut() to non-Sized thin pointers #93959
Comments
As @scottmcm pointed out on Zulip, instead of of extending |
In terms of its own signature |
We know that, but the compiler doesn’t (yet)
… so this wrong. I in error[E0271]: type mismatch resolving `<T as Pointee>::Metadata == ()`
--> library/core/src/sync/atomic.rs:177:24
|
177 | AtomicPtr::new(crate::ptr::null_mut())
| ^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type
|
= note: expected unit type `()`
found associated type `<T as Pointee>::Metadata`
= help: consider constraining the associated type `<T as Pointee>::Metadata` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `ptr::null_mut`
--> library/core/src/ptr/mod.rs:232:35
|
232 | pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
| ^^^^ required by this bound in `ptr::null_mut` I tried encoding the desired implication with this: --- library/core/src/marker.rs
+++ library/core/src/marker.rs
@@ -89,7 +90,7 @@ impl<T: ?Sized> !Send for *mut T {}
)]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[rustc_specialization_trait]
-pub trait Sized {
+pub trait Sized: ptr::Thin {
// Empty.
} But this caused many errors like: error[E0271]: type mismatch resolving `<Cell<T> as Pointee>::Metadata == ()`
--> library/core/src/cell.rs:260:18
|
260 | impl<T: Default> Default for Cell<T> {
| ^^^^^^^ expected associated type, found `()`
|
= note: expected associated type `<Cell<T> as Pointee>::Metadata`
found unit type `()`
= help: consider constraining the associated type `<Cell<T> as Pointee>::Metadata` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html I think this is because pub trait Default: Sized { So Since #81172, when asked specifically for |
I don't see a problem with defining |
The obstacle is that things break when I do it, as described in my previous comment. It looks like #93977 might fix that. |
…ata, r=wesleywiser Type params and assoc types have unit metadata if they are sized Extend the logic in `Pointee` projection to ensure that we can satisfy `<T as Pointee>::Metadata = ()` if `T: Sized`. cc: `@SimonSapin` and rust-lang#93959
Extend ptr::null and null_mut to all thin (including extern) types 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(const_fn_trait_bound)` * Having `rustc_allow_const_fn_unstable(ptr_metadata)`
Thanks for doing this @SimonSapin! |
Fixes rust-lang/rust#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/rust#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)`
Extend ptr::null and null_mut to all thin (including extern) types Fixes rust-lang/rust#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/rust#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(const_fn_trait_bound)` * Having `rustc_allow_const_fn_unstable(ptr_metadata)`
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::dangling
As of Rust 1.58:
T: Sized
types. (This bound is implied by the lack ofT: ?Sized
pseudo-bound in their respective signature.)extern
types are the only kind of types that are notSized
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
, andtoNonNull::dangling
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 newPointee
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 forextern
types.Public API
These existing stable APIs of
core::ptr
/std::ptr
:Should be changed to
… where
Thin
is an existing trait alias:In 1.58,
Pointee
andThin
are both unstable and tracked at #81513.Pointee
is automatically implemented for all types. ForSized
andextern
types,Metadata
is()
. SoSized
impliesThin
.Because
Sized
impliesThin
, 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
instr::find
.)Steps / History
Implementation strategy
and related language changenull
,null_mut
, anddangling
are implemented by converting an integer (zero oralign_of()
) to a raw pointer with theas
operator. In Rust 1.58,as
only allows such a conversion if the target type is a pointer to aSized
type. The obvious way to implement this proposed extension ofnull
and 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_parts
could be used instead ofas
.Unresolved Questions
Is the language change to theas
operator described above desirable?Should it separately go through the RFC process?The text was updated successfully, but these errors were encountered: