Skip to content

Commit 4fcfcca

Browse files
committed
Require #[repr(transparent)]
1 parent 5cfbde5 commit 4fcfcca

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

text/3621-derive-smart-pointer.md

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,8 @@ The macro sets the following requirements on its input:
265265
2. The struct must have at least one type parameter. If multiple type
266266
parameters are present, exactly one of them has to be annotated with the
267267
`#[pointee]` derive helper attribute.
268-
3. The struct must not be `#[repr(packed)]` or `#[repr(C)]`.
269-
4. Other than one-aligned, zero-sized fields, the struct must have exactly one
270-
field.
268+
3. The struct must be `#[repr(transparent)]`.
269+
4. The struct must have at least one field.
271270
5. Assume that `T` is a type that can be unsized to `U`, and let `FT` and `FU`
272271
be the type of the struct's field when the pointee is equal to `T` and `U`
273272
respectively. If the struct's trait bounds are satisfied for both `T` and
@@ -276,9 +275,10 @@ The macro sets the following requirements on its input:
276275

277276
(Adapted from the docs for [`DispatchFromDyn`].)
278277

279-
Point 1 and 2 are verified syntactically by the derive macro, whereas 3, 4 and 5
278+
Point 1 and 2 are verified syntactically by the derive macro. Points 4 and 5
280279
are verified semantically by the compiler when checking the generated
281-
[`DispatchFromDyn`] implementation as it does today.
280+
[`DispatchFromDyn`] implementation as it does today. Point 3 is verified by
281+
introducing a new unstable helper trait `AssertReprTransparent`.
282282

283283
The `#[pointee]` attribute may also be written as `#[smart_pointer::pointee]`.
284284

@@ -331,6 +331,16 @@ where
331331
T: ::core::marker::Unsize<U>,
332332
{}
333333
```
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+
```
334344

335345
## `Receiver` and `Deref` implementations
336346

@@ -390,6 +400,13 @@ Although this RFC proposes to add the `PinCoerceUnsized` trait to ensure that
390400
unsizing coercions of pinned pointers cannot be used to cause unsoundness, the
391401
RFC does not propose to stabilize the trait.
392402

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+
393410
# Drawbacks
394411
[drawbacks]: #drawbacks
395412

@@ -715,6 +732,27 @@ This RFC does not propose it because it is a breaking change and the
715732
discussed in more details in [the pre-RFC for stabilizing the underlying
716733
traits][pre-rfc].
717734

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+
718756
# Prior art
719757
[prior-art]: #prior-art
720758

0 commit comments

Comments
 (0)