Skip to content

Commit 397f118

Browse files
guswynnbjorn3
andcommitted
Clarify object safety rules for methods striked from the vtable
When trying to figure out how `async_trait` object safety worked and thinking about `Stream::next`'s object safety, I found it very hard to understand This clarifies that object-safety can still be possible even if a method is striked from the vtable, and that `self` and `where `Self: Sized` are the ONLY ways to do that. This was only really explained clearly in the examples below, so this includes this clarification in the object safety rules in the beginning of the section --- Separately, NonDispatchable seems like you are out of luck, but this pattern: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=5529e6424895cccda19d4dd81f389b69, where we impl the trait for &T where T: Trait + ?Sized is actually quite common in the std (albeit with `self` parameter's so you don't need the `(&obj_ref)` dance to get method resolution to be happy, see https://rust-lang.zulipchat.com/#narrow/stream/249502-wg-async-foundations.2Fstream-trait-rfc/topic/Object.20safety/near/226749056 for more info). This seems like a pattern we should explain somewhere, but is the reference the right place for it? I have not mentioned it in this PR, but would be curious what people think Co-authored-by: bjorn3 <[email protected]>
1 parent 361367c commit 397f118

File tree

1 file changed

+17
-16
lines changed

1 file changed

+17
-16
lines changed

src/items/traits.md

+17-16
Original file line numberDiff line numberDiff line change
@@ -67,23 +67,23 @@ trait Seq<T> {
6767
Object safe traits can be the base trait of a [trait object]. A trait is
6868
*object safe* if it has the following qualities (defined in [RFC 255]):
6969

70-
* It must not require `Self: Sized`
71-
* All associated functions must either have a `where Self: Sized` bound, or
72-
* Not have any type parameters (although lifetime parameters are allowed),
73-
and
74-
* Be a [method] that does not use `Self` except in the type of the receiver.
70+
* All [supertraits] must also be object safe.
71+
* It must not require `Self: Sized` (i.e. `Sized` must not be a [supertrait][supertraits])
7572
* It must not have any associated constants.
76-
* All supertraits must also be object safe.
77-
78-
When there isn't a `Self: Sized` bound on a method, the type of a method
79-
receiver must be one of the following types:
80-
81-
* `&Self`
82-
* `&mut Self`
83-
* [`Box<Self>`]
84-
* [`Rc<Self>`]
85-
* [`Arc<Self>`]
86-
* [`Pin<P>`] where `P` is one of the types above
73+
* All associated functions must "dispatchable from a trait object" or "explicitly non-dispatchable from a trait object":
74+
* Dispatchable functions require:
75+
* Not have any type parameters (although lifetime parameters are allowed),
76+
* Be a [method] that does not use `Self` except in the type of the receiver.
77+
* Have a receiver with one of the following types:
78+
* `&Self` (i.e. `&self`)
79+
* `&mut Self` (i.e `&mut self`)
80+
* [`Box<Self>`]
81+
* [`Rc<Self>`]
82+
* [`Arc<Self>`]
83+
* [`Pin<P>`] where `P` is one of the types above
84+
* Does not have a `where Self: Sized` bound (reciever type of `Self` (i.e. `self`) implies this).
85+
* Non-Dispatchable functions require:
86+
* Have a `where Self: Sized` bound (reciever type of `Self` (i.e. `self`) implies this).
8787

8888
```rust
8989
# use std::rc::Rc;
@@ -325,6 +325,7 @@ fn main() {
325325
[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
326326
[associated items]: associated-items.md
327327
[method]: associated-items.md#methods
328+
[supertraits]: #supertraits
328329
[implementations]: implementations.md
329330
[generics]: generics.md
330331
[where clauses]: generics.md#where-clauses

0 commit comments

Comments
 (0)