@@ -65,6 +65,7 @@ stabilizing its expansion.
6565By using the macro, the following example will compile:
6666``` rust
6767#[derive(SmartPointer )]
68+ #[repr(transparent)]
6869struct MySmartPointer <T : ? Sized >(Box <T >);
6970
7071impl <T : ? Sized > Deref for MySmartPointer <T > {
@@ -147,12 +148,13 @@ Whenever a `self: MySmartPointer<Self>` method is called on a trait object, the
147148compiler will convert from ` MySmartPointer<dyn MyTrait> ` to
148149` MySmartPointer<MyStruct> ` using something similar to a transmute. Because of
149150this, 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.
154155``` rust
155156#[derive(SmartPointer )]
157+ #[repr(transparent)]
156158struct MySmartPointer <T : ? Sized > {
157159 ptr : Box <T >,
158160 _phantom : PhantomData <T >,
@@ -165,6 +167,7 @@ If the type has multiple type parameters, then you must explicitly specify
165167which one should be used for dynamic dispatch. For example:
166168``` rust
167169#[derive(SmartPointer )]
170+ #[repr(transparent)]
168171struct MySmartPointer <#[pointee] T : ? Sized , U > {
169172 ptr : Box <T >,
170173 _phantom : PhantomData <U >,
@@ -194,6 +197,7 @@ you could implement your own `Rc` type like this:
194197
195198``` rust
196199#[derive(SmartPointer )]
200+ #[repr(transparent)]
197201pub struct Rc <T : ? Sized > {
198202 inner : NonNull <RcInner <T >>,
199203}
@@ -275,10 +279,9 @@ The macro sets the following requirements on its input:
275279
276280(Adapted from the docs for [ ` DispatchFromDyn ` ] .)
277281
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
279283are 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.
282285
283286The ` #[pointee] ` attribute may also be written as ` #[smart_pointer::pointee] ` .
284287
@@ -303,6 +306,7 @@ following procedure:
303306Given the following example code:
304307``` rust
305308#[derive(SmartPointer )]
309+ #[repr(transparent)]
306310struct MySmartPointer <'a , #[pointee] T , A >
307311where
308312 T : ? Sized + SomeTrait <T >,
@@ -331,16 +335,6 @@ where
331335 T : :: core :: marker :: Unsize <U >,
332336{}
333337```
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- ```
344338
345339## ` Receiver ` and ` Deref ` implementations
346340
@@ -400,13 +394,6 @@ Although this RFC proposes to add the `PinCoerceUnsized` trait to ensure that
400394unsizing coercions of pinned pointers cannot be used to cause unsoundness, the
401395RFC does not propose to stabilize the trait.
402396
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-
410397# Drawbacks
411398[ drawbacks ] : #drawbacks
412399
@@ -455,6 +442,7 @@ However, it turns out that there are quite a few different ways we might
455442implement ` Deref ` . For example, consider [ the custom ` Rc ` example] [ custom-rc ] :
456443``` rust
457444#[derive(SmartPointer )]
445+ #[repr(transparent)]
458446pub struct Rc <T : ? Sized > {
459447 inner : NonNull <RcInner <T >>,
460448}
@@ -692,6 +680,7 @@ RFC][unsafe-attribute].
692680``` rust
693681// SAFETY: The Deref impl is not malicious.
694682#[unsafe (derive(SmartPointer ))]
683+ #[repr(transparent)]
695684pub struct Rc <T : ? Sized > {
696685 inner : NonNull <RcInner <T >>,
697686}
@@ -732,27 +721,6 @@ This RFC does not propose it because it is a breaking change and the
732721discussed in more details in [ the pre-RFC for stabilizing the underlying
733722traits] [ pre-rfc ] .
734723
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-
756724# Prior art
757725[ prior-art ] : #prior-art
758726
@@ -820,9 +788,10 @@ proposals for relaxing them have been seen before (e.g., in the
820788[ pre-RFC] [ pre-rfc ] .)
821789
822790One 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.)
826795
827796This could also allow implementations of ` Rc ` and ` Arc ` that store the value and
828797refcount in two different allocations, like how the C++ ` shared_ptr ` works.
0 commit comments