You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/3519-arbitrary-self-types-v2.md
+10-25
Original file line number
Diff line number
Diff line change
@@ -131,6 +131,8 @@ If you're implementing a smart pointer `P<T>`, and you need to allow `impl T { f
131
131
132
132
Therefore, the current Arbitrary Self Types v2 provides a separate `Receiver` trait, so that there's no need to provide an awkward `Deref::deref` implementation.
133
133
134
+
In addition, this v2 proposes to block generic receivers, which are currently allowed by the v1 (unstable) arbitrary self types feature. See the [diagnostics section for reasoning](#diagnostics).
In case `a` the lifetime could be elided (as demonstrated by `free_function`) yet an explicit lifetime is currently demanded by the compiler. For now, this extra clarity seems actually desirable. We could relax this restriction in future. (The authors of this RFC are interested in other views here!)
285
287
286
288
## Diagnostics
289
+
[diagnostics]: #diagnostics
287
290
288
291
The existing branches in the compiler for "arbitrary self types" already emit excellent diagnostics. We will largely re-use them, with the following improvements:
289
292
290
293
- In the case where a self type is invalid because it doesn't implement `Receiver`, the existing excellent error message will be updated.
291
294
- An easy mistake is to implement `Receiver` for `P<T>`, forgetting to specify `T: ?Sized`. `P<Self>` then only works as a `self` parameter in traits `where Self: Sized`, an unusual stipulation. It's not obvious that `Sized`ness is the problem here, so we will identify this case specifically and produce an error giving that hint.
292
295
- There are certain types which feel like they "should" implement `Receiver` but do not: `Weak` and `NotNull`. If these are encountered as a self type, we should produce a specific diagnostic explaining that they do not implement `Receiver` and suggesting that they could be wrapped in a newtype wrapper if method calls are important. We hope this can be achieved with [diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html).
293
-
- Under some circumstances, the compiler identifies method candidates but then discovers that the self type doesn't match. This results currently in a simple "mismatched types" error; we can provide a more specific error message here. The only known case is where a method is generic over `Receiver`, and the caller explicitly specifies the wrong type:
294
-
```rust
295
-
#![feature(receiver_trait)]
296
-
297
-
usestd::ops::Receiver;
298
-
299
-
structSmartPtr<'a, T:?Sized>(&'aT);
300
-
301
-
impl<'a, T:?Sized> ReceiverforSmartPtr<'a, T> {
302
-
typeTarget=T;
303
-
}
304
-
305
-
structFoo(u32);
306
-
implFoo {
307
-
fna<R:Receiver<Target=Self>>(self:R) { }
308
-
}
309
-
310
-
fnmain() {
311
-
letfoo=Foo(1);
312
-
letsmart_ptr=SmartPtr(&foo);
313
-
smart_ptr.a(); // this compiles
314
-
smart_ptr.a::<&Foo>(); // currently results in "mismatched types"; we can probably do better
315
-
}
316
-
```
317
-
-Ifamethod `m` isgenericover `R:Receiver<Target=T>` (or, perhapsmorecommonly, `R:Deref<Target=T>`) and `self:R`, thensomeonecallsitwith `object_by_value.m()`, itwon'tworkbecauseRustdoesn'tknowtouse `&object_by_value`, and the message `the trait bound Foo: 'Receiver/Deref' is not satisfied` is generated.While correct, this may be surprising because users expect to be able to use `object_by_value.m2()` where `fn m2(&self)`.The resulting error message already suggests that the user create a reference in order to match the `Receiver` trait, so this may be sufficient already, but we may add an additional note here.
296
+
- The current unstable arbitrary self types feature allows generic receivers. For instance,
297
+
```rust
298
+
implFoo {
299
+
fna<R:Deref<Target=Self>>(self:R) { }
300
+
}
301
+
```
302
+
We don't know a use-case for this. There are several cases where this can result in misleading diagnostics. (For instance, if such a method is called with an incorrect type (for example `smart_ptr.a::<&Foo>()` instead of `smart_ptr.a::<Foo>()`). We could attempt to find and fix all those cases. However, we feel that generic receiver types might risk subtle interactions with method resolutions and other parts of the language. We think it is a safer choice to generate an error on any declaration of a generic `self` type.
0 commit comments