-
Notifications
You must be signed in to change notification settings - Fork 20
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
Restructure ptr_metadata to minimal support #111
Comments
The original RFC was dual t-lang and t-libs-api, so this feels like it might need lang decision too... Although perhaps it's enough to have that on some FCP later on. |
The intent of the ACP as-written is to introduce no new language semantics, and be implementable solely in terms of today's As far as I can tell, the point in the API as proposed here that would require T-lang sign-off is providing layout from the fully generic I'm striking the generic parts of my |
I want to note that while this may be a nice distinction from the stabilization pov, since it's easier to reason about smaller APIs, we still need |
Proposal
Problem statement
feature(ptr_metadata)
is in feature limbo. Being able to split pointers into raw pointer and metadata unlocks a lot of cool abilities in library code, but as currently architected the metadata APIs expose more than is really comfortable to stabilize in the short term. Notably,Pointee
is a very special lang-item, being automatically implemented for every type. Plus, it's unfortunately tied in identity to both "DynSized
",extern type
, and custom pointee metadata.This API offers a way to expose a minimal
feature(min_ptr_metadata)
subset offeature(ptr_metadata)
that unblocks the simple use cases of separating address from metadata, while remaining forward-compatible with any1 design for exposing more knobs later on.In short: this splits
feature(ptr_metadata)
into granular subfeatures such thatmin_ptr_metadata
might be stabilizable this year.Motivation, use-cases
My main motivating use case is custom reference-like types.
Consider something like a generational arena. When using an arena, instead of using something like
rc::Weak<Object>
, you useHandle<Object>
, whereHandle
is some index; perhaps{ ix: u32, salt: u32 }
. This works well when your arena stores a single sized type; youArena::<Object>::resolve(&self, Handle<Object>) -> &'_ Object
and all is good.This is simple enough to extend to storing arbitrary sized objects in the arena as well, so long as you use some kind of allocation strategy which can handle the mixed-layout allocations rather than a simple array storage. This also means that your index changes from an element index to a byte index, and you need some way to ensure that a handle is only used for the arena that it came from.
But what about unsized types? For example, in an actor-based game engine (as opposed to an ECS-based solution), you might have
Handle<PlayerPawn>
andHandle<EnemyPawn>
, and want to be able to store a handle to either one asHandle<dyn Pawn>
. Withoutfeature(ptr_metadata)
, such a handle is forced to store someptr::NonNull<dyn Pawn>
, where what actually wants to be stored is{ ix: u32, salt: u32, meta: ptr::Metadata<dyn Pawn> }
.Being able to separate pointer metadata from the actual pointer is a space-saving mechanism for such designs in cases where the storage is known to be pinned, as resolving a handle could be implemented to validate the index, salt, address, etc. match and then dereference the stored pointer with its metadata. When the storage is not pinned, however, allowing
dyn
-erased handles is just not possible, as there is no (stable) way (yet) to graft one pointer's metadata onto another's.Solution sketches
Due to the specifics of this proposal, the proposed API is a slight evolution of the existing API, and heavily split into multiple features. For continuity, all of these smaller features should be considered implied by the
ptr_metadata
feature.The key change is that rather than expose concrete metadata types, we only expose a single uniform opaque
ptr::Metadata<T>
type. This can have additional other benefit -- one key one I'm interested in is thatptr::Metadata<T>
canCoerceUnsized
, allowing pointer-like types wrappingptr::Metadata
to get unsizing coercions as if they were holding an actual pointer.The other key removal of surface area of
ptr_metadata
inmin_ptr_metadata
is the moving offrom_ptr_metadata
into a separate feature. This means that the choice of using*mut ()
or*mut u8
for the untyped pointer is deferred to a separate feature. The alternative iswith_metadata
[_of
].Other notes on API design choices
as
).cast()
between pointers which have the same<T as Pointee>::Metadata
type.(*const T, usize) -> *const [T]
functions, is why<[T] as Pointee>::Metadata
isusize
rather than aSliceMetadata<T>
type.core::ptr::WellFormed
is a raw pointer that is guaranteed non-null and aligned, per Commit to safety rules for dyn trait upcasting rust#101336size
function probably wants to wait for the public exposing of aValidSize
type which is bound to0..=isize::MAX
.align
function might want to wait for the public exposing of aValidAlign
type which is restricted to powers of two.size
function is fallible because it's possible to safely construct*const [T]
describing too-large objects.align
function is infallible because I don't see any utility in dynamic alignment requirements, but perhaps it should be fallible for uniformity?Pointee
as a default bound and makeextern type
be!Pointee
I find intriguing. Doing so might be able to unblock further experimentation withextern type
, as the current direction seems to be forbidding the use ofextern type
in generics which do not opt-in to supporting extern types, if opting in is allowed at all. In such a case, perhaps the trait really should evolve to beDynSized
.Links and related work
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
Footnotes
Asserted without proof. ↩
The text was updated successfully, but these errors were encountered: