Do we stabilize `Receiver` now or wait for `#[derive(SmartPointer)]`?
## The decision
Do we:
* Stabilize a `Receiver` trait, without any special support for dynamic dispatch, allowing us to add more traits later for types which wish to support dynamic dispatch
* _Instead_ stabilize `#[derive(SmartPointer)]`, which currently might only `impl Receiver` but in future will also implement `DispatchFromDyn` (or whatever else is required to support dynamic dispatch).
If we're sure that we'll always want smart pointers to `#[derive(SmartPointer)]`, then we can reduce our future compatibility burden by not exposing `Receiver` additionally.
## Related material
* [`DispatchFromDyn`](https://doc.rust-lang.org/std/ops/trait.DispatchFromDyn.html)
* Arbitrary self types [design meeting minutes](https://hackmd.io/@rust-lang-team/rk2biy6n6)
* Notes on the RfL [needs](https://hackmd.io/@rust-lang-team/HymfJSLa6) and specifically on the [rationale for why this derive might be good](https://hackmd.io/@rust-lang-team/HymfJSLa6#Will-the-deriveSmartPointer-proposal-work-for-Rust-for-Linux)
* [RFC/minutes for this new `#derive`](https://hackmd.io/@rust-lang-team/HyYXScDa6)
## Questions
* Are there any use-cases for smart pointers where we would not want dynamic dispatch?
* Are there any types which might want to implement `Receiver` which are not smart pointers?
If the answer to either of these is "yes" then that's a definite reason to allow direct `impl` of `Receiver` instead of wrapping it up into`#[derive(SmartPointer)]`.
## C++ dynamic dispatch use-cases
Summary: `DispatchFromDyn` is harmless but probably not useful, and might be confusing. It would be better if we could implement `Receiver` without `DispatchFromDyn.`
Details:
Imagine we have:
```cpp
class Base {
public:
virtual void Method() const;
};
class Derived : public Base {
public:
virtual void Method() const;
};
```
We would like to be able to call that in Rust like this:
```rust
fn some_function() {
let cpp_ptr: CppPtr<Base> = obtain_from_cpp();
cpp_ptr.Method(); // may call Base::Method or Derived::Method
}
```
We couldn't use trait objects for this. It seems more likely that we'd want to call into some C++ shim function which does the dynamic dispatch according to C++'s precise vtable rules. (Cross-language inlining should make this free of overhead).
Most likely, the shim would look something like this:
```cpp
void CallBaseMethod(const Base* b) {
b->Method();
}
```
I am confident we would not use trait objects for C++ dispatch.
Are they actively harmful? Not really, but having two types of dynamic dispatch here might be confusing.
## Rust for Linux usecases
Summary: there are some types which want to implement `Receiver` and _definitely cannot_ implement `DispatchFromDyn`.
Details:
Rust for Linux has at least one type where they _do_ want to implement `Receiver` but do not and _cannot_ implement `DispatchFromDyn`:
This is the [`Wrapper` type described here](https://rust-for-linux.com/arc-in-the-linux-kernel#nextprev-pointers-and-dynamic-dispatch):
```rust
struct Wrapper<T: ?Sized> {
next: *mut Wrapper<T>,
prev: *mut Wrapper<T>,
value: T,
}
```
This isn't actually a _pointer_ so can't support dynamic dispatch.
## Conclusion
We must allow implementation of `Receiver` without implementing `DispatchFromDyn`, and therefore we should proceed with exposing `Receiver` intead of wrapping them up together into `#[derive(SmartPointer)]`.