@@ -65,6 +65,7 @@ stabilizing its expansion.
65
65
By using the macro, the following example will compile:
66
66
``` rust
67
67
#[derive(SmartPointer )]
68
+ #[repr(transparent)]
68
69
struct MySmartPointer <T : ? Sized >(Box <T >);
69
70
70
71
impl <T : ? Sized > Deref for MySmartPointer <T > {
@@ -147,12 +148,13 @@ Whenever a `self: MySmartPointer<Self>` method is called on a trait object, the
147
148
compiler will convert from ` MySmartPointer<dyn MyTrait> ` to
148
149
` MySmartPointer<MyStruct> ` using something similar to a transmute. Because of
149
150
this, there are strict requirements on the layout of ` MySmartPointer ` . It is
150
- required that ` MySmartPointer ` is a struct, and that (other than one-aligned,
151
- zero-sized fields) it must have exactly one field. The type must either be a
152
- standard library pointer type (reference, raw pointer, NonNull, Box, Arc, etc.)
153
- or another user-defined type also using this derive macro.
151
+ required that ` MySmartPointer ` is a ` #[repr(transparent)] ` struct, and the type
152
+ of its non- zero-sized field must either be a standard library pointer type
153
+ (reference, raw pointer, NonNull, Box, Arc, etc.) or another user-defined type
154
+ also using this derive macro.
154
155
``` rust
155
156
#[derive(SmartPointer )]
157
+ #[repr(transparent)]
156
158
struct MySmartPointer <T : ? Sized > {
157
159
ptr : Box <T >,
158
160
_phantom : PhantomData <T >,
@@ -165,6 +167,7 @@ If the type has multiple type parameters, then you must explicitly specify
165
167
which one should be used for dynamic dispatch. For example:
166
168
``` rust
167
169
#[derive(SmartPointer )]
170
+ #[repr(transparent)]
168
171
struct MySmartPointer <#[pointee] T : ? Sized , U > {
169
172
ptr : Box <T >,
170
173
_phantom : PhantomData <U >,
@@ -194,6 +197,7 @@ you could implement your own `Rc` type like this:
194
197
195
198
``` rust
196
199
#[derive(SmartPointer )]
200
+ #[repr(transparent)]
197
201
pub struct Rc <T : ? Sized > {
198
202
inner : NonNull <RcInner <T >>,
199
203
}
@@ -275,10 +279,9 @@ The macro sets the following requirements on its input:
275
279
276
280
(Adapted from the docs for [ ` DispatchFromDyn ` ] .)
277
281
278
- Point 1 and 2 are verified syntactically by the derive macro. Points 4 and 5
282
+ Points 1, 2 and 3 are verified syntactically by the derive macro. Points 4 and 5
279
283
are verified semantically by the compiler when checking the generated
280
- [ ` DispatchFromDyn ` ] implementation as it does today. Point 3 is verified by
281
- introducing a new unstable helper trait ` AssertReprTransparent ` .
284
+ [ ` DispatchFromDyn ` ] implementation as it does today.
282
285
283
286
The ` #[pointee] ` attribute may also be written as ` #[smart_pointer::pointee] ` .
284
287
@@ -303,6 +306,7 @@ following procedure:
303
306
Given the following example code:
304
307
``` rust
305
308
#[derive(SmartPointer )]
309
+ #[repr(transparent)]
306
310
struct MySmartPointer <'a , #[pointee] T , A >
307
311
where
308
312
T : ? Sized + SomeTrait <T >,
@@ -331,16 +335,6 @@ where
331
335
T : :: core :: marker :: Unsize <U >,
332
336
{}
333
337
```
334
- The macro will also generate an implementation of the new
335
- ` AssertReprTransparent ` helper trait. The implementation will have the same
336
- trait bounds as the struct definition.
337
- ``` rust
338
- #[automatically_derived]
339
- impl <'a , T , A > :: core :: ops :: AssertReprTransparent for MySmartPointer <'a , T , A >
340
- where
341
- T : ? Sized + SomeTrait <T >,
342
- {}
343
- ```
344
338
345
339
## ` Receiver ` and ` Deref ` implementations
346
340
@@ -400,13 +394,6 @@ Although this RFC proposes to add the `PinCoerceUnsized` trait to ensure that
400
394
unsizing coercions of pinned pointers cannot be used to cause unsoundness, the
401
395
RFC does not propose to stabilize the trait.
402
396
403
- ## ` AssertReprTransparent `
404
-
405
- To verify the requirement that the struct is ` #[repr(transparent)] ` , we
406
- introduce a new unstable marker trait called ` AssertReprTransparent ` . This trait
407
- will be a lang item, and the compiler will emit an error if the trait is used
408
- with a type that is not ` #[repr(transparent)] ` .
409
-
410
397
# Drawbacks
411
398
[ drawbacks ] : #drawbacks
412
399
@@ -455,6 +442,7 @@ However, it turns out that there are quite a few different ways we might
455
442
implement ` Deref ` . For example, consider [ the custom ` Rc ` example] [ custom-rc ] :
456
443
``` rust
457
444
#[derive(SmartPointer )]
445
+ #[repr(transparent)]
458
446
pub struct Rc <T : ? Sized > {
459
447
inner : NonNull <RcInner <T >>,
460
448
}
@@ -692,6 +680,7 @@ RFC][unsafe-attribute].
692
680
``` rust
693
681
// SAFETY: The Deref impl is not malicious.
694
682
#[unsafe (derive(SmartPointer ))]
683
+ #[repr(transparent)]
695
684
pub struct Rc <T : ? Sized > {
696
685
inner : NonNull <RcInner <T >>,
697
686
}
@@ -732,27 +721,6 @@ This RFC does not propose it because it is a breaking change and the
732
721
discussed in more details in [ the pre-RFC for stabilizing the underlying
733
722
traits] [ pre-rfc ] .
734
723
735
- ## ` AssertReprTransparent `
736
-
737
- When you implement the [ ` DispatchFromDyn ` ] trait, the compiler enforces various
738
- things about the type to verify that it makes sense to implement
739
- ` DispatchFromDyn ` . One of the things that the compiler verifies is that the
740
- struct must not be ` #[repr(packed)] ` or ` #[repr(C)] ` .
741
-
742
- However, because ` #[derive(SmartPointer)] ` has more narrow use-case than
743
- ` DispatchFromDyn ` , we would like to restrict it further so that the macro only
744
- works with ` #[repr(transparent)] ` types. To do this, we use a new trait called
745
- ` AssertReprTransparent ` that verifies that the struct is ` #[repr(transparent)] `
746
- like how ` DispatchFromDyn ` verifies that the struct must not be
747
- ` #[repr(packed)] ` or ` #[repr(C)] ` .
748
-
749
- We cannot change the logic in ` DispatchFromDyn ` because some existing standard
750
- library types cannot be ` #[repr(transparent)] ` . For example, this includes
751
- ` Box<T, A> ` due to its allocator field.
752
-
753
- This requirement may be relaxed in the future, in which case
754
- ` AssertReprTransparent ` can be removed again.
755
-
756
724
# Prior art
757
725
[ prior-art ] : #prior-art
758
726
@@ -820,9 +788,10 @@ proposals for relaxing them have been seen before (e.g., in the
820
788
[ pre-RFC] [ pre-rfc ] .)
821
789
822
790
One example of a restriction that we could lift is the restriction that there is
823
- only one non-zero-sized field. This would allow smart pointers to use custom
824
- allocators. (Today, types like ` Box ` and ` Rc ` only work with trait objects when
825
- using the default zero-sized allocator.)
791
+ only one non-zero-sized field (i.e., that it must be ` #[repr(transparent)] ` ).
792
+ This would allow smart pointers to use custom allocators. (Today, types like
793
+ ` Box ` and ` Rc ` only work with trait objects when using the default zero-sized
794
+ allocator.)
826
795
827
796
This could also allow implementations of ` Rc ` and ` Arc ` that store the value and
828
797
refcount in two different allocations, like how the C++ ` shared_ptr ` works.
0 commit comments