@@ -83,9 +83,9 @@ First, let’s get some boilerplate out of the way:
8383use std :: marker :: {PhantomData , Unsize };
8484use std :: ptr :: {self , DynMetadata };
8585
86- trait DynTrait = Pointee <Metadata = DynMetadata >;
86+ trait DynTrait < Dyn > = Pointee <Metadata = DynMetadata < Dyn > >;
8787
88- pub struct ThinBox <Dyn : ? Sized + DynTrait > {
88+ pub struct ThinBox <Dyn : ? Sized + DynTrait < Dyn > > {
8989 ptr : ptr :: NonNull <WithMeta <()>>,
9090 phantom : PhantomData <Dyn >,
9191}
@@ -125,7 +125,7 @@ Accessing the value requires knowing its alignment:
125125impl <Dyn : ? Sized + DynTrait > ThinBox <Dyn > {
126126 fn data_ptr (& self ) -> * mut () {
127127 unsafe {
128- let offset = std :: mem :: size_of :: <DynMetadata >();
128+ let offset = std :: mem :: size_of :: <DynMetadata < Dyn >();
129129 let value_align = self . ptr. as_ref (). vtable. align ();
130130 let offset = align_up_to (offset , value_align );
131131 (self . ptr. as_ptr () as * mut u8 ). add (offset ) as * mut ()
@@ -218,15 +218,17 @@ This similarly includes extern types.
218218/// * For structs whose last field is a DST, metadata is the metadata for the last field
219219/// * For the `str` type, metadata is the length in bytes as `usize`
220220/// * For slice types like `[T]`, metadata is the length in items as `usize`
221- /// * For trait objects like `dyn SomeTrait`, metadata is [`DynMetadata`].
221+ /// * For trait objects like `dyn SomeTrait`, metadata is [`DynMetadata<Self>`][DynMetadata]
222+ /// (e.g. `DynMetadata<dyn SomeTrait>`).
222223///
223224/// In the future, the Rust language may gain new kinds of types
224225/// that have different pointer metadata.
225226///
226227/// Pointer metadata can be extracted from a pointer or reference with the [`metadata`] function.
227228/// The data pointer can be extracted by casting a (fat) pointer
228- /// to a (thin) pointer to a `Sized` type the `as` operator,
229- /// for example `(x: &dyn SomeTrait) as *const SomeTrait as *const ()`.
229+ /// to a (thin) pointer to a `Sized` type with the `as` operator,
230+ /// for example `(x: &dyn SomeTrait) as *const SomeTrait as *const ()`
231+ /// or `(x: *const dyn SomeTrait).cast::<()>()`.
230232///
231233/// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts
232234#[lang = " pointee" ]
@@ -282,7 +284,7 @@ impl<T: ?Sized> NonNull<T> {
282284 }
283285}
284286
285- /// The metadata for a `dyn SomeTrait` trait object type.
287+ /// The metadata for a `DynTrait = dyn SomeTrait` trait object type.
286288///
287289/// It is a pointer to a vtable (virtual call table)
288290/// that represents all the necessary information
@@ -297,17 +299,16 @@ impl<T: ?Sized> NonNull<T> {
297299/// Note that the first three are special because they’re necessary to allocate, drop,
298300/// and deallocate any trait object.
299301///
300- /// The layout of vtables is still unspecified, so this type is a more-type-safe
301- /// convenience for accessing those 3 special values. Note however that `DynMetadata` does
302- /// not actually know the trait it’s associated with, indicating that, at very least,
303- /// the location of `size`, `align`, and `drop_in_place` is identical for all
304- /// trait object vtables in a single program.
302+ /// It is possible to name this struct with a type parameter that is not a `dyn` trait object
303+ /// (for example `DynMetadata<u64>`) but not to obtain a meaningful value of that struct.
305304#[derive(Copy , Clone )]
306- pub struct DynMetadata {
305+ pub struct DynMetadata <DynTrait : ? Sized > {
306+ // Private fields
307307 vtable_ptr : ptr :: NonNull <()>,
308+ phantom : PhantomData <DynTrait >
308309}
309310
310- impl DynMetadata {
311+ impl < DynTrait : ? Sized > DynMetadata < DynTrait > {
311312 /// Returns the size of the type associated with this vtable.
312313 pub fn size (self ) -> usize { ... }
313314
@@ -343,12 +344,8 @@ In addition to being more general
343344and (hopefully) more compatible with future custom DSTs proposals,
344345this RFC resolves the question of what happens
345346if trait objects with super-fat pointers with multiple vtable pointers are ever added.
346- (Answer: they can use a different metadata type like ` [DynMetadata; N] ` .)
347-
348- ` DynMetadata ` could be made generic with a type parameter for the trait object type that it describes.
349- This would avoid forcing that the size, alignment, and destruction pointers
350- be in the same location (offset) for every vtable.
351- But keeping them in the same location is probaly desirable anyway to keep code size small.
347+ (Answer: they can use a different metadata type,
348+ possibly like ` (DynMetadata<dyn Trait>, DynMetadata<dyn OtherTrait>) ` .)
352349
353350[ 2579 ] : https://github.com/rust-lang/rfcs/pull/2579
354351
@@ -372,11 +369,11 @@ Except for `DynMetadata`’s methods, this RFC proposes a subset of what that th
372369
373370* The location of ` DynMetadata ` . Is another module more appropriate than ` std::ptr ` ?
374371
375- * Should ` DynMetadata ` have a type parameter for what trait object type it is a metadata of ?
376- Such that ` <dyn SomeTrait as Pointee>::Metadata ` is ` DynMetadata<dyn SomTrait> ` .
377- This would allow the memory layout to change based on the trait object type
378- (potentially super-wide pointers with multiple vtable pointers for multi-trait objects?)
379- or to have different methods .
372+ * Should ` DynMetadata ` not have a type parameter?
373+ This might reduce monomorphization cost,
374+ but would force that the size, alignment, and destruction pointers
375+ be in the same location (offset) for every vtable.
376+ But keeping them in the same location is probaly desirable anyway to keep code size small .
380377
381378* The name of ` Thin ` .
382379 This name is short and sweet but ` T: Thin ` suggests that ` T ` itself is thin,
0 commit comments