Skip to content

Commit 85ef575

Browse files
committed
Remove details about how repr(transparent) constraint is implemented
And add #[repr(transparent)] to the examples.
1 parent 4fcfcca commit 85ef575

File tree

1 file changed

+17
-48
lines changed

1 file changed

+17
-48
lines changed

text/3621-derive-smart-pointer.md

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ stabilizing its expansion.
6565
By using the macro, the following example will compile:
6666
```rust
6767
#[derive(SmartPointer)]
68+
#[repr(transparent)]
6869
struct MySmartPointer<T: ?Sized>(Box<T>);
6970

7071
impl<T: ?Sized> Deref for MySmartPointer<T> {
@@ -147,12 +148,13 @@ Whenever a `self: MySmartPointer<Self>` method is called on a trait object, the
147148
compiler will convert from `MySmartPointer<dyn MyTrait>` to
148149
`MySmartPointer<MyStruct>` using something similar to a transmute. Because of
149150
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.
154155
```rust
155156
#[derive(SmartPointer)]
157+
#[repr(transparent)]
156158
struct 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
165167
which one should be used for dynamic dispatch. For example:
166168
```rust
167169
#[derive(SmartPointer)]
170+
#[repr(transparent)]
168171
struct 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)]
197201
pub 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
279283
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.
282285

283286
The `#[pointee]` attribute may also be written as `#[smart_pointer::pointee]`.
284287

@@ -303,6 +306,7 @@ following procedure:
303306
Given the following example code:
304307
```rust
305308
#[derive(SmartPointer)]
309+
#[repr(transparent)]
306310
struct MySmartPointer<'a, #[pointee] T, A>
307311
where
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
400394
unsizing coercions of pinned pointers cannot be used to cause unsoundness, the
401395
RFC 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
455442
implement `Deref`. For example, consider [the custom `Rc` example][custom-rc]:
456443
```rust
457444
#[derive(SmartPointer)]
445+
#[repr(transparent)]
458446
pub 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)]
695684
pub 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
732721
discussed in more details in [the pre-RFC for stabilizing the underlying
733722
traits][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

822790
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.)
826795

827796
This could also allow implementations of `Rc` and `Arc` that store the value and
828797
refcount in two different allocations, like how the C++ `shared_ptr` works.

0 commit comments

Comments
 (0)