@@ -29,7 +29,9 @@ use core::ptr::{self, NonNull};
2929/// ```
3030#[ unstable( feature = "thin_box" , issue = "92791" ) ]
3131pub struct ThinBox < T : ?Sized > {
32- ptr : WithHeader < <T as Pointee >:: Metadata > ,
32+ // This is essentially `WithHeader<<T as Pointee>::Metadata>`,
33+ // but that would be invariant in `T`, and we want covariance.
34+ ptr : WithOpaqueHeader ,
3335 _marker : PhantomData < T > ,
3436}
3537
@@ -49,7 +51,7 @@ impl<T> ThinBox<T> {
4951 #[ cfg( not( no_global_oom_handling) ) ]
5052 pub fn new ( value : T ) -> Self {
5153 let meta = ptr:: metadata ( & value) ;
52- let ptr = WithHeader :: new ( meta, value) ;
54+ let ptr = WithOpaqueHeader :: new ( meta, value) ;
5355 ThinBox { ptr, _marker : PhantomData }
5456 }
5557}
@@ -73,7 +75,7 @@ impl<Dyn: ?Sized> ThinBox<Dyn> {
7375 T : Unsize < Dyn > ,
7476 {
7577 let meta = ptr:: metadata ( & value as & Dyn ) ;
76- let ptr = WithHeader :: new ( meta, value) ;
78+ let ptr = WithOpaqueHeader :: new ( meta, value) ;
7779 ThinBox { ptr, _marker : PhantomData }
7880 }
7981}
@@ -120,7 +122,7 @@ impl<T: ?Sized> Drop for ThinBox<T> {
120122 unsafe {
121123 let value = self . deref_mut ( ) ;
122124 let value = value as * mut T ;
123- self . ptr . drop :: < T > ( value) ;
125+ self . with_header ( ) . drop :: < T > ( value) ;
124126 }
125127 }
126128}
@@ -130,11 +132,16 @@ impl<T: ?Sized> ThinBox<T> {
130132 fn meta ( & self ) -> <T as Pointee >:: Metadata {
131133 // Safety:
132134 // - NonNull and valid.
133- unsafe { * self . ptr . header ( ) }
135+ unsafe { * self . with_header ( ) . header ( ) }
134136 }
135137
136138 fn data ( & self ) -> * mut u8 {
137- self . ptr . value ( )
139+ self . with_header ( ) . value ( )
140+ }
141+
142+ fn with_header ( & self ) -> & WithHeader < <T as Pointee >:: Metadata > {
143+ // SAFETY: both types are transparent to `NonNull<u8>`
144+ unsafe { & * ( ( & self . ptr ) as * const WithOpaqueHeader as * const WithHeader < _ > ) }
138145 }
139146}
140147
@@ -143,8 +150,22 @@ impl<T: ?Sized> ThinBox<T> {
143150/// metadata (`H`) are ZSTs.
144151/// 2. A pointer to a valid `T` that has a header `H` directly before the
145152/// pointed-to location.
153+ #[ repr( transparent) ]
146154struct WithHeader < H > ( NonNull < u8 > , PhantomData < H > ) ;
147155
156+ /// An opaque representation of `WithHeader<H>` to avoid the
157+ /// projection invariance of `<T as Pointee>::Metadata`.
158+ #[ repr( transparent) ]
159+ struct WithOpaqueHeader ( NonNull < u8 > ) ;
160+
161+ impl WithOpaqueHeader {
162+ #[ cfg( not( no_global_oom_handling) ) ]
163+ fn new < H , T > ( header : H , value : T ) -> Self {
164+ let ptr = WithHeader :: new ( header, value) ;
165+ Self ( ptr. 0 )
166+ }
167+ }
168+
148169impl < H > WithHeader < H > {
149170 #[ cfg( not( no_global_oom_handling) ) ]
150171 fn new < T > ( header : H , value : T ) -> WithHeader < H > {
0 commit comments