Skip to content

Commit 83a31a6

Browse files
committed
Add elaboration of object-safe receivers.
1 parent 68e4157 commit 83a31a6

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

src/items/traits.md

+97
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,99 @@ Object safe traits can be the base trait of a [trait object]. A trait is
9595
* It must not have any associated constants.
9696
* All supertraits must also be object safe.
9797

98+
When there isn't a `Self: Sized` bound on a method, the type of a method
99+
receiver must be one of the following types:
100+
101+
* `&Self`
102+
* `&mut Self`
103+
* [`Box<Self>`]
104+
* [`Rc<Self>`]
105+
* [`Arc<Self>`]
106+
* [`Pin<P>`] where `P` is one of the types above
107+
108+
```rust
109+
# use std::rc::Rc;
110+
# use std::sync::Arc;
111+
# use std::pin::Pin;
112+
// Examples of object safe methods.
113+
trait TraitMethods {
114+
fn by_ref(self: &Self) {}
115+
fn by_ref_mut(self: &mut Self) {}
116+
fn by_box(self: Box<Self>) {}
117+
fn by_rc(self: Rc<Self>) {}
118+
fn by_arc(self: Arc<Self>) {}
119+
fn by_pin(self: Pin<&Self>) {}
120+
fn with_lifetime<'a>(self: &'a Self) {}
121+
fn nested_pin(self: Pin<Arc<Self>>) {}
122+
}
123+
# struct S;
124+
# impl TraitMethods for S {}
125+
# let t: Box<dyn TraitMethods> = Box::new(S);
126+
```
127+
128+
```rust,compile_fail
129+
// These are object-safe, but cannot be dispatched on a trait object.
130+
trait NonDispatchable {
131+
// Non-methods cannot be dispatched.
132+
fn foo() where Self: Sized {}
133+
// Self type isn't known until runtime.
134+
fn returns(&self) -> Self where Self: Sized;
135+
// `other` may be a different concrete type of the receiver.
136+
fn param(&self, other: Self) where Self: Sized {}
137+
// Generics are not compatible with vtables.
138+
// Alternate solution is to use a trait object instead.
139+
fn typed<T>(&self, x: T) where Self: Sized {}
140+
}
141+
142+
struct S;
143+
impl NonDispatchable for S {
144+
fn returns(&self) -> Self where Self: Sized { S }
145+
}
146+
let obj: Box<dyn NonDispatchable> = Box::new(S);
147+
obj.returns(); // ERROR: cannot call with Self return
148+
obj.param(S); // ERROR: cannot call with Self parameter
149+
obj.typed(1); // ERROR: cannot call with generic type
150+
```
151+
152+
```rust,compile_fail
153+
# use std::rc::Rc;
154+
// Examples of non-object safe traits.
155+
trait NotObjectSafe {
156+
const CONST: i32 = 1; // ERROR: cannot have associated const
157+
158+
fn foo() {} // ERROR: associated function without Sized
159+
fn returns(&self) -> Self; // ERROR: Self in return type
160+
fn typed<T>(&self, x: T) {} // ERROR: has generic type parameters
161+
fn nested(self: Rc<Box<Self>>) {} // ERROR: nested receiver not yet supported
162+
}
163+
164+
struct S;
165+
impl NotObjectSafe for S {
166+
fn returns(&self) -> Self { S }
167+
}
168+
let obj: Box<dyn NotObjectSafe> = Box::new(S); // ERROR
169+
```
170+
171+
```rust,compile_fail
172+
// Self: Sized traits are not object-safe.
173+
trait TraitWithSize where Self: Sized {}
174+
175+
struct S;
176+
impl TraitWithSize for S {}
177+
let obj: Box<dyn TraitWithSize> = Box::new(S); // ERROR
178+
```
179+
180+
```rust,compile_fail
181+
// Not object safe if `Self` is a type parameter.
182+
trait Super<A> {}
183+
trait WithSelf: Super<Self> where Self: Sized {}
184+
185+
struct S;
186+
impl<A> Super<A> for S {}
187+
impl WithSelf for S {}
188+
let obj: Box<dyn WithSelf> = Box::new(S); // ERROR: cannot use `Self` type parameter
189+
```
190+
98191
## Supertraits
99192

100193
**Supertraits** are traits that are required to be implemented for a type to
@@ -231,3 +324,7 @@ trait T {
231324
[trait implementation]: implementations.md#trait-implementations
232325
[`Send`]: ../special-types-and-traits.md#send
233326
[`Sync`]: ../special-types-and-traits.md#sync
327+
[`Arc<Self>`]: ../special-types-and-traits.md#arct
328+
[`Box<Self>`]: ../special-types-and-traits.md#boxt
329+
[`Pin<P>`]: ../special-types-and-traits.md#pinp
330+
[`Rc<Self>`]: ../special-types-and-traits.md#rct

0 commit comments

Comments
 (0)