Skip to content
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

Hierarchy of Sized traits #3729

Open
wants to merge 65 commits into
base: master
Choose a base branch
from

Conversation

davidtwco
Copy link
Member

@davidtwco davidtwco commented Nov 15, 2024

All of Rust's types are either sized, which implement the Sized trait and have a statically known size during compilation, or unsized, which do not implement the Sized trait and are assumed to have a size which can be computed at runtime. However, this dichotomy misses two categories of type - types whose size is unknown during compilation but is a runtime constant, and types whose size can never be known. Supporting the former is a prerequisite to stable scalable vector types and supporting the latter is a prerequisite to unblocking extern types. This RFC proposes a hierarchy of Sized traits in order to be able to support these use cases.

This RFC relies on experimental, yet-to-be-RFC'd const traits, so this is blocked on that. I haven't squashed any of the previous revisions but can do so if/when this is approved. Already discussed in the 2024-11-13 t-lang design meeting with feedback incorporated.

See this comment for the most recent summary of changes to this RFC since it was opened.

Rendered

@davidtwco davidtwco added the T-lang Relevant to the language team, which will review and decide on the RFC. label Nov 15, 2024
Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
text/3729-sized-hierarchy.md Outdated Show resolved Hide resolved
@tmandry tmandry added the I-lang-nominated Indicates that an issue has been nominated for prioritizing at the next lang team meeting. label Nov 15, 2024
@davidtwco
Copy link
Member Author

Since there seems to be consensus on it, I've adopted the alternative for replacing ValueSized with MetaSized and included this in the document. It just makes sense as it matches the current ?Sized semantics.

@safinaskar
Copy link

safinaskar commented Dec 22, 2024

Edit: oops, I see that thin CStr is mentioned.

What about thin CStr? Please, mention it in RFC. It is somewhat unique, because it has a size, but to determine size, we should read actual data, and thus size_of_val_raw is always unsafe. See https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/CStr.20as.20thin.20pointer/near/405436807 , https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/CStr.20as.20thin.20pointer/near/405473727 , https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/CStr.20as.20thin.20pointer/near/405518769 .

And I absolutely want to be able to use thin CStr as a last field of a struct, because this will finally solve long-standing dirent problem on Linux, which currently requires this horrible hack in standard library: https://github.com/rust-lang/rust/blob/c1132470a6986b12503e8000e322e9164c1f03ac/library/std/src/sys/pal/unix/fs.rs#L730-L768

This was referenced Jan 2, 2025
@workingjubilee workingjubilee added the A-dst Proposals re. DSTs label Jan 2, 2025
@Ericson2314
Copy link
Contributor

Ericson2314 commented Jan 2, 2025

Wow, a funny (but good!) feeling to think that this might finally get resolved after a decade. :)

Instead of introducing a new marker trait, std::ptr::Pointee could be re-used if there were some mechanism to indicate that associated types or methods could only be referred to with fully-qualified syntax. Alternatively, it would be possible to introduce forward-compatibility lints in current edition, the new traits were introduced in the next edition and the edition migration previously described in the next next edition.

I think std::ptr::Pointee should definitely be reused. I am not sure which alternative is, but it seems to me like the right thing to do is:

  • Use std::ptr::Pointee
  • Do the hack to avoid new ambiguity in the current addition
  • Remove the hack in the next addition

Also, I agree with @RalfJung than the ? avoidance is quite confusing, and we are mixing up syntax and semantics. The bottom line is that semantically, the trait hierarchy is the free lattice over the trait partial order. Decoding the complex math speak: that means the minimum element (or maxiumum, whatever way you want the arrows to point) is not a trait but the empty set of traits. So we need to specify what that means.

After we do that, we we can debate syntax.

In particular, the "Why have Pointee?" is a bit misleading in that semantically there currently is indeed no reason, it is just there for syntactic purposes.

However, if we reuse std::ptr::Pointee then there is a semantic reason, namely the associated type. ({} / no traits has no associated types or any other trait members, because it has no traits!) So here is an extra incentive to reuse std::ptr::Pointee --- one can side-step what @RalfJung and I are saying :).

At the point I still think it is good education to talk about the empty trait set as:

  • You can't use it behind a pointer
  • You can't use it as a value
  • You could use it in PhantomData, but probably this is left as future work
  • Maybe you can't quantify over it all (as opposed to you can, but then you can't use the variable anywhere, and then its an unused type parameter error)

Oh and a final thing on semantics, I might also also present the back compat / editions story this way:

  • Old semantic hierarchy
  • New semantic hierarchy
  • mapping from old to new semantics, (old {} (no traits) is mapped not to new {} but to const MetaSized) --- in particular, do not speak of ?Size when describing this semantic mapping.
  • mapping from new syntax in next edition maps to new semantics.

In particular, the existing old syntax maps to the new semantics via the old semantics; we can cleanly factor that into those two steps, and I think this brings conceptual clarity.

@programmerjake
Copy link
Member

  • Use std::ptr::Pointee
  • Do the hack to avoid new ambiguity in the current addition
  • Remove the hack in the next addition

imo having an associated type on practically every type will be annoying, so I think it might be useful to require writing <T as Pointee>::Metadata instead of T::Metadata on all editions.

@workingjubilee
Copy link
Member

the trait's unstable, if it's just a matter of bikeshedding we can rename the type PtrMetadata or sth

davidtwco referenced this pull request in oli-obk/rfcs Jan 8, 2025
@davidtwco
Copy link
Member Author

I think std::ptr::Pointee should definitely be reused. I am not sure which alternative is, but it seems to me like the right thing to do is:

  • Use std::ptr::Pointee
  • Do the hack to avoid new ambiguity in the current addition
  • Remove the hack in the next addition

I've added this as one of the unresolved questions.

In particular, the "Why have Pointee?" is a bit misleading in that semantically there currently is indeed no reason, it is just there for syntactic purposes.

I've rewritten this section, it should have been updated earlier with the addition of the alternatives which keep the ?Sized syntax and clarified that it's just a syntactic difference.

At the point I still think it is good education to talk about the empty trait set as:

  • You can't use it behind a pointer
  • You can't use it as a value
  • You could use it in PhantomData, but probably this is left as future work
  • Maybe you can't quantify over it all (as opposed to you can, but then you can't use the variable anywhere, and then its an unused type parameter error)

Oh and a final thing on semantics, I might also also present the back compat / editions story this way:

  • Old semantic hierarchy
  • New semantic hierarchy
  • mapping from old to new semantics, (old {} (no traits) is mapped not to new {} but to const MetaSized) --- in particular, do not speak of ?Size when describing this semantic mapping.
  • mapping from new syntax in next edition maps to new semantics.

In particular, the existing old syntax maps to the new semantics via the old semantics; we can cleanly factor that into those two steps, and I think this brings conceptual clarity.

I haven't made these changes at the moment - I've had good feedback about the explanations in the RFC and would prefer not to make major changes to that until the proposal itself needs changing.

@davidtwco
Copy link
Member Author

I've updated the previous summary comment so it is still accurate.

@davidtwco
Copy link
Member Author

I've pushed one small change with a reference to the now-upstream const traits RFC in #3762.

@traviscross traviscross added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Indicates that an issue has been nominated for prioritizing at the next lang team meeting. labels Jan 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-dst Proposals re. DSTs I-lang-radar Items that are on lang's radar and will need eventual work or consideration. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.