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
When declaring a method, users can declare the type of the `self` receiver to be any type `T` where `T: Receiver<Target = Self>`.
30
+
When declaring a method, users can declare the type of the `self` receiver to be any type `T` where `T: Receiver<Target = Self>` or `Self`.
31
31
32
32
The `Receiver` trait is simple and only requires to specify the `Target` type to be resolved to:
33
33
@@ -39,7 +39,7 @@ trait Receiver {
39
39
40
40
The `Receiver` trait is already implemented for a few types from the standard, i.e.
41
41
- smart pointer: `Arc<Self>`, `Box<Self>`, `Pin<Self>` and `Rc<Self>`
42
-
- references: `&Self`, `&mut Self` and `Self`
42
+
- references: `&Self` and `&mut Self`
43
43
- raw pointer: `*const Self` and `*mut Self`
44
44
45
45
Shorthand exists for references, so that `self` with no ascription is of type `Self`, `&self` is of type `&Self` and `&mut self` is of type `&mut Self`.
@@ -65,7 +65,7 @@ impl<T> Receiver for CustomPtr<T> {
65
65
66
66
## Recursive arbitrary receivers
67
67
68
-
Receivers are recursive and therefore allowed to be nested. If type `T` implements `Receiver<Target=U>`, and type `U` implements `Deref<Target=Self>`, `T` is a valid receiver (and so on outward).
68
+
Receivers are recursive and therefore allowed to be nested. If type `T` implements `Receiver<Target=U>`, and type `U` implements `Receiver<Target=Self>`, `T` is a valid receiver (and so on outward).
69
69
70
70
For example, this self type is valid:
71
71
@@ -75,17 +75,39 @@ impl MyType {
75
75
}
76
76
```
77
77
78
-
## Object safety
79
-
80
-
TODO:
81
-
- DispatchFromDyn
82
-
- What is the relation with Lukas' [RFC "Unsize and CoerceUnsize v2"](https://github.com/ferrous-systems/unsize-experiments)?
The `Receiver` trait is made public (removing its `#[doc(hidden)])` attribute), exposing it under `core::ops`.
82
+
This trait marks types that can be used as receivers other than the `Self` type of an impl or trait definition.
83
+
84
+
```rust
85
+
pubtraitReceiver {
86
+
typeTarget:?Sized;
87
+
}
88
+
```
89
+
90
+
For a type to be a valid receiver for a given impl, the `Self` type of the impl or trait has to appear in its receiver chain.
91
+
92
+
The receiver chain is constructed as follows:
93
+
1. Add the receiver type `T` to the chain.
94
+
2. If `T` implements `Receiver`, add `<T as Receiver>::Target` to the chain.
95
+
3. Repeat step 2 with the `<T as Receiver>::Target` as `T`.
96
+
97
+
## Method Resolution
98
+
99
+
Method resolution will be adjusted to take into account a receiver's receiver chain by taking looking through all impls for all types appearing in the receiver chain.
100
+
101
+
## core lib changes
102
+
103
+
The implementations of the hidden `Receiver` trait will be adjusted by removing the `#[doc(hidden)]` attribute and having their corresponding `Target` associated type added.
104
+
105
+
## Lifetime Elision
106
+
87
107
TODO
88
108
109
+
## Diagnostics
110
+
89
111
TODO ensure we include some analysis of extra diagnostics required. Known gotchas:
90
112
- In a trait, using `self: SomeSmartPointerWhichOnlySupportsSizedTypes<Self>` without using `where Self: Sized` on the trait definition results in poor diagnostics.
91
113
@@ -102,25 +124,64 @@ The section should return to the examples given in the previous section, and exp
102
124
103
125
Why should we *not* do this?
104
126
127
+
- Implementations of this trait may obscure what method is being called where in similar ways to deref coercions obscuring it.
128
+
- The use of this feature together with `Deref` implementations may cause ambiguious situations,
129
+
```rs
130
+
131
+
pubstructPtr<T>(T);
132
+
133
+
impl<T> Deref<T> {
134
+
typeTarget=T;
135
+
136
+
fnderef(&self) ->&T {
137
+
&self.0
138
+
}
139
+
}
140
+
141
+
impl<T> Ptr<T> {
142
+
pubfnfoo(&self) {}
143
+
}
144
+
145
+
pubstructBar;
146
+
147
+
implBar {
148
+
fnfoo(self:&Ptr<Self>) {}
149
+
}
150
+
```
151
+
invoking `Ptr(Bar).foo()` herewillrequiretheuse of fully qualified paths (`Bar::foo` vs `Ptr::foo` or `Ptr::<T>::foo`) to disambiguate the call.
152
+
153
+
## Object safety
154
+
155
+
Receivers remain object safe as before, if they implement the `core::ops::DispatchFromDyn` trait they are object safe.
156
+
As not all receivers might want to permit object safety (or are even unable to support it), object safety should remain being encoded in a different trait than the here proposed `Receiver` trait.
157
+
158
+
105
159
TODO.To include:
106
160
107
-
- object safety
108
161
- compatibility concerns / does this break semver?
109
-
- does it cause any risk that folks implementing `Deref` for other reasons will also be forced into new behavior? ("scoping")
110
162
- method shadowing
111
-
- if we later implement `MethodReceiver` to allow
112
163
- all the other concerns discussed in https://github.com/rust-lang/rust/issues/44874#issuecomment-1306142542
-An alternative proposal is to use `Deref` and it's associated `Target` type instead.This comes with the problem that not all types that wish to be receivers are able to implement `Deref`, a simple example being raw pointers.
170
+
-Change the trait definition to
171
+
```rust
172
+
pubtraitReceiver<T:?Sized> {}
173
+
```
174
+
to allow an impl of the form `implReceiver<T> forT` which would enable `Self` to be used as is by the traitimpl rule instead of a special case.
175
+
176
+
177
+
TODO:
178
+
118
179
-Why is this design the best in the space of possible designs?
119
180
-What other designs have been considered and what is the rationale for not choosing them?
120
181
-What is the impact of not doing this?
121
182
-If this is a language proposal, could this be done in a library or macro instead?Does the proposed change make Rust code easier or harder to read, understand, and maintain?
122
183
123
-
TODO. To include:
184
+
To include:
124
185
125
186
-Argumentsfor/against doing this as a new `MethodReceiver` trait
126
187
-Argumentsfor/against stabilizing the unstable `Receiver` trait instead of this
@@ -130,6 +191,10 @@ TODO. To include:
130
191
# Prior art
131
192
[prior-art]: #prior-art
132
193
194
+
A previous PR based on the `Deref` alternative has been proposed before https://github.com/rust-lang/rfcs/pull/2362.
195
+
196
+
TODO:
197
+
133
198
Discuss prior art, both the good and the bad, in relation to this proposal.
134
199
A few examples of what this can include are:
135
200
@@ -144,17 +209,36 @@ If there is no prior art, that is fine - your ideas are interesting to us whethe
144
209
Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC.
145
210
Please also take into consideration that rust sometimes intentionally diverges from common language features.
146
211
147
-
TODO
148
-
149
212
# Unresolved questions
150
213
[unresolved-questions]: #unresolved-questions
151
214
215
+
-There is the option of doing a blanket impl of the `Receiver` trait based on `Deref` impls delegating the `Target` types.
216
+
217
+
-With the proposed design, it is not possible to be generic over the receiver while permitting the plain `Self` to be slotted in:
218
+
```rs
219
+
usestd::ops::Receiver;
220
+
221
+
structFoo(u32);
222
+
implFoo {
223
+
fnget<R:Receiver<Target=Self>>(self:R) ->u32 {
224
+
self.0
225
+
}
226
+
}
227
+
228
+
fnmain() {
229
+
letmutfoo=Foo(1);
230
+
foo.get::<&Foo>(); // Error
231
+
}
232
+
```
233
+
Thisfails, because `T:Receiver<Target=T>` generallydoesnothold.
0 commit comments