@@ -56,6 +56,13 @@ pub trait LabelDowncast<Id> {
5656 fn downcast_from ( data : u64 ) -> Option < Self :: Output > ;
5757}
5858
59+ #[ doc( hidden) ]
60+ pub struct VTable {
61+ // FIXME: When const TypeId stabilizes, inline the type instead of using a fn pointer for indirection.
62+ pub ty : fn ( ) -> :: std:: any:: TypeId ,
63+ pub fmt : fn ( u64 , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result ,
64+ }
65+
5966/// Macro to define a new label trait
6067///
6168/// # Example
@@ -81,25 +88,30 @@ macro_rules! define_label {
8188 $( #[ $id_attr] ) *
8289 #[ derive( Clone , Copy ) ]
8390 pub struct $id_name {
84- ty: :: std:: any:: TypeId ,
8591 data: u64 ,
86- f : fn ( u64 , & mut :: std :: fmt :: Formatter ) -> :: std :: fmt :: Result ,
92+ vtable : & ' static $crate :: label :: VTable ,
8793 }
8894
8995 impl :: std:: fmt:: Debug for $id_name {
9096 fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
9197 let data = self . data( ) ;
92- ( self . f ) ( data, f)
98+ ( self . vtable . fmt ) ( data, f)
9399 }
94100 }
95101
96102 $( #[ $label_attr] ) *
97103 pub trait $label_name: ' static {
104+ /// Essentially acts like a dynamic dispatch virtual table,
105+ /// but specialized for labels.
106+ const VTABLE : $crate:: label:: VTable = $crate:: label:: VTable {
107+ ty: || :: std:: any:: TypeId :: of:: <Self >( ) ,
108+ fmt: Self :: fmt,
109+ } ;
98110 /// Converts this type into an opaque, strongly-typed label.
99111 #[ inline]
100112 fn as_label( & self ) -> $id_name {
101113 let data = self . data( ) ;
102- $id_name { data, ty : :: std :: any :: TypeId :: of :: < Self > ( ) , f : Self :: fmt }
114+ $id_name { data, vtable : & Self :: VTABLE }
103115 }
104116 /// Returns a number used to distinguish different labels of the same type.
105117 fn data( & self ) -> u64 ;
@@ -129,23 +141,30 @@ macro_rules! define_label {
129141 impl PartialEq for $id_name {
130142 #[ inline]
131143 fn eq( & self , rhs: & Self ) -> bool {
132- self . ty == rhs. ty && self . data ( ) == rhs. data ( )
144+ self . data ( ) == rhs. data ( ) && self . type_id ( ) == rhs. type_id ( )
133145 }
134146 }
135147 impl Eq for $id_name { }
136148
137149
138150 impl std:: hash:: Hash for $id_name {
139151 fn hash<H : std:: hash:: Hasher >( & self , state: & mut H ) {
140- self . ty . hash( state) ;
152+ self . type_id ( ) . hash( state) ;
141153 self . data( ) . hash( state) ;
142154 }
143155 }
144156
145157 impl $id_name {
158+ /// Returns the [`TypeId`] of the label from which this ID was constructed.
159+ ///
160+ /// [`TypeId`]: ::std::any::TypeId
161+ #[ inline]
162+ pub fn type_id( self ) -> :: std:: any:: TypeId {
163+ ( self . vtable. ty) ( )
164+ }
146165 /// Returns true if this label was constructed from an instance of type `L`.
147166 pub fn is<L : $label_name>( self ) -> bool {
148- self . ty == :: std:: any:: TypeId :: of:: <L >( )
167+ self . type_id ( ) == :: std:: any:: TypeId :: of:: <L >( )
149168 }
150169 /// Attempts to downcast this label to type `L`.
151170 ///
0 commit comments