Skip to content

Commit f775825

Browse files
committed
Transparent containers implement both traits
1 parent 8a62c64 commit f775825

File tree

1 file changed

+45
-17
lines changed

1 file changed

+45
-17
lines changed

text/3621-derive-smart-pointer.md

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,38 @@ Note that having the macro generate a `Receiver` impl instead doesn't work
393393
either, because that prevents the user from implementing `Deref` at all. (There
394394
is a blanket impl of `Receiver` for all `Deref` types.)
395395

396+
## Transparent containers
397+
398+
Smart pointers are not the only use case for implementing the [`CoerceUnsized`]
399+
and [`DispatchFromDyn`] traits. They are also used for "transparent containers"
400+
such as [`Cell`]. That use-case allows coercions such as `Cell<Box<MyStruct>>`
401+
to `Cell<Box<dyn MyTrait>>`. (Coercions where the `Cell` is inside the `Box` are
402+
already supported on stable Rust.)
403+
404+
It is not possible to use the derive macro proposed by this RFC for transparent
405+
containers because they require a different set of where bounds when
406+
implementing the traits. To compare:
407+
```rust
408+
// smart pointer example
409+
impl<T, U> DispatchFromDyn<Box<U>> for Box<T>
410+
where
411+
T: Unsize<U> + ?Sized,
412+
U: ?Sized,
413+
{}
414+
415+
// transparent container example
416+
impl<T, U> DispatchFromDyn<Cell<U>> for Cell<T>
417+
where
418+
T: DispatchFromDyn<U>,
419+
{}
420+
```
421+
Attempting to annotate `#[derive(SmartPointer)]` onto a transparent container
422+
will fail to compile because [it violates the rules for implementing
423+
`DispatchFromDyn`][tc-pg]. Supporting custom transparent containers is out of
424+
scope for this RFC.
425+
426+
[tc-pg]: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=c3fe2a11822e4c5e2dae5bfec9d77b9e
427+
396428
## Why not two derive macros?
397429

398430
The derive macro generates two different trait implementations:
@@ -406,21 +438,16 @@ It could be argued that these should be split into two separate derive macros.
406438
We are not proposing this for a few reasons:
407439

408440
- If there are two derive macros, then we have to support the case where you
409-
only use one of them. There are use-cases for implementing [`CoerceUnsized`]
410-
without [`DispatchFromDyn`], but you do this for cases where your type is not
411-
a smart pointer, but rather a transparent container like [`Cell`]. It makes
412-
coercions like `Cell<Box<MyStruct>>` to `Cell<Box<dyn MyTrait>>` possible.
413-
Supporting that is a significantly increased scope of the RFC, and the
414-
authors believe that supporting transparent containers should be a separate
415-
follow-up RFC.
416-
417-
- Right now there are use cases for `CoerceUnsized` (transparent containers)
418-
and `CoerceUnsized+DispatchFromDyn` (smart pointers), but there aren't any
419-
real use-cases for having `DispatchFromDyn` alone. Because of that, one
420-
possible future design of the underlying traits could be to have one trait
421-
for smart pointers, and another one for transparent containers. Adding two
422-
derive macros prevents us from changing the underlying traits to that design
423-
in the future.
441+
only use one of them. There isn't much reason to do that, and the authors are
442+
not aware of any examples where you would prefer to implement one of the
443+
traits without implementing both.
444+
445+
- Having two different macros means that we lock ourselves into solutions that
446+
involve two traits that split the feature in the way that we split it today.
447+
However, it is easy to imagine situations where we would want to split the
448+
traits in a different way. For example, we might instead want one trait for
449+
smart pointers, and another trait for transparent containers. Or maybe we just
450+
want one trait that does both things.
424451

425452
- The authors believe that a convenience `#[derive(SmartPointer)]` macro will
426453
continue to make sense, even once the underlying traits are stabilized. It is
@@ -643,8 +670,9 @@ can evolve. The authors hope that we will find a way to stabilize the
643670
underlying traits in the future.
644671

645672
One of the things that is left out of scope of this RFC is coercions involving
646-
custom transparent containers similar to [`Cell`]. They require an
647-
implementation of [`CoerceUnsized`] without [`DispatchFromDyn`].
673+
custom transparent containers similar to [`Cell`]. They require you to implement
674+
the traits with different where bounds. Adding support for custom transparent
675+
containers makes sense as a future expansion of the feature.
648676

649677
There is a reasonable change that we may be able to lift some of [the
650678
restrictions][input-requirements] on the shape of the struct as well. The

0 commit comments

Comments
 (0)