From 851e7f9404b0deaafece4b0bd2fe04700a7ec1a1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 30 Nov 2019 08:16:13 -0800 Subject: [PATCH 1/3] Update for nested receivers. --- src/items/associated-items.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index c1f82f62ec05b..dc6c9faef4122 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -109,13 +109,15 @@ following types: - [`Arc`] - [`Pin

`] where `P` is one of the above types except `Self`. -The `Self` term can be replaced with the type being implemented. +The `Self` term can be replaced with the type being implemented, including +type aliases for the type, or any nested combination of the above types. ```rust # use std::rc::Rc; # use std::sync::Arc; # use std::pin::Pin; struct Example; +type Alias = Example; impl Example { fn by_value(self: Self) {} fn by_ref(self: &Self) {} @@ -126,6 +128,7 @@ impl Example { fn by_pin(self: Pin<&Self>) {} fn explicit_type(self: Arc) {} fn with_lifetime<'a>(self: &'a Self) {} + fn nested<'a>(self: &mut &'a Arc>>) {} } ``` @@ -360,4 +363,4 @@ fn main() { [function item]: ../types/function-item.md [method call operator]: ../expressions/method-call-expr.md [path]: ../paths.md -[regular function parameters]: functions.md#attributes-on-function-parameters +[regular function parameters]: functions.md#attributes-on-function-parameters From b3d68ee51c1be4d9b865f0211692b5f9714d66ce Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Dec 2019 11:22:25 -0800 Subject: [PATCH 2/3] Add elaboration of object-safe receivers. --- src/items/traits.md | 97 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/items/traits.md b/src/items/traits.md index 5427dbe652e06..b2132a7e8c697 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -95,6 +95,99 @@ Object safe traits can be the base trait of a [trait object]. A trait is * It must not have any associated constants. * All supertraits must also be object safe. +When there isn't a `Self: Sized` bound on a method, the type of a method +receiver must be one of the following types: + +* `&Self` +* `&mut Self` +* [`Box`] +* [`Rc`] +* [`Arc`] +* [`Pin

`] where `P` is one of the types above + +```rust +# use std::rc::Rc; +# use std::sync::Arc; +# use std::pin::Pin; +// Examples of object safe methods. +trait TraitMethods { + fn by_ref(self: &Self) {} + fn by_ref_mut(self: &mut Self) {} + fn by_box(self: Box) {} + fn by_rc(self: Rc) {} + fn by_arc(self: Arc) {} + fn by_pin(self: Pin<&Self>) {} + fn with_lifetime<'a>(self: &'a Self) {} + fn nested_pin(self: Pin>) {} +} +# struct S; +# impl TraitMethods for S {} +# let t: Box = Box::new(S); +``` + +```rust,compile_fail +// These are object-safe, but cannot be dispatched on a trait object. +trait NonDispatchable { + // Non-methods cannot be dispatched. + fn foo() where Self: Sized {} + // Self type isn't known until runtime. + fn returns(&self) -> Self where Self: Sized; + // `other` may be a different concrete type of the receiver. + fn param(&self, other: Self) where Self: Sized {} + // Generics are not compatible with vtables. + // Alternate solution is to use a trait object instead. + fn typed(&self, x: T) where Self: Sized {} +} + +struct S; +impl NonDispatchable for S { + fn returns(&self) -> Self where Self: Sized { S } +} +let obj: Box = Box::new(S); +obj.returns(); // ERROR: cannot call with Self return +obj.param(S); // ERROR: cannot call with Self parameter +obj.typed(1); // ERROR: cannot call with generic type +``` + +```rust,compile_fail +# use std::rc::Rc; +// Examples of non-object safe traits. +trait NotObjectSafe { + const CONST: i32 = 1; // ERROR: cannot have associated const + + fn foo() {} // ERROR: associated function without Sized + fn returns(&self) -> Self; // ERROR: Self in return type + fn typed(&self, x: T) {} // ERROR: has generic type parameters + fn nested(self: Rc>) {} // ERROR: nested receiver not yet supported +} + +struct S; +impl NotObjectSafe for S { + fn returns(&self) -> Self { S } +} +let obj: Box = Box::new(S); // ERROR +``` + +```rust,compile_fail +// Self: Sized traits are not object-safe. +trait TraitWithSize where Self: Sized {} + +struct S; +impl TraitWithSize for S {} +let obj: Box = Box::new(S); // ERROR +``` + +```rust,compile_fail +// Not object safe if `Self` is a type parameter. +trait Super {} +trait WithSelf: Super where Self: Sized {} + +struct S; +impl Super for S {} +impl WithSelf for S {} +let obj: Box = Box::new(S); // ERROR: cannot use `Self` type parameter +``` + ## Supertraits **Supertraits** are traits that are required to be implemented for a type to @@ -268,3 +361,7 @@ fn main() { [trait implementation]: implementations.md#trait-implementations [`Send`]: ../special-types-and-traits.md#send [`Sync`]: ../special-types-and-traits.md#sync +[`Arc`]: ../special-types-and-traits.md#arct +[`Box`]: ../special-types-and-traits.md#boxt +[`Pin

`]: ../special-types-and-traits.md#pinp +[`Rc`]: ../special-types-and-traits.md#rct From f183df7e64fac5e1f4b66639e1588502919303a2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 5 Feb 2020 18:32:16 -0800 Subject: [PATCH 3/3] Update from review. --- src/items/associated-items.md | 25 ++++++++++++++----------- src/items/traits.md | 5 ++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index dc6c9faef4122..eba9507c7fdfe 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -98,26 +98,28 @@ Associated functions whose first parameter is named `self` are called *methods* and may be invoked using the [method call operator], for example, `x.foo()`, as well as the usual function call notation. -If the type of the `self` parameter is specified, it is limited to one of the -following types: +If the type of the `self` parameter is specified, it is limited to semantic +types generated by the following grammar (where `'lt` denotes some arbitrary +lifetime): -- `Self` -- `&Self` -- `&mut Self` -- [`Box`] -- [`Rc`] -- [`Arc`] -- [`Pin

`] where `P` is one of the above types except `Self`. +```text +P = &'lt S | &'lt mut S | Box | Rc | Arc | Pin

+S = Self | P +``` -The `Self` term can be replaced with the type being implemented, including -type aliases for the type, or any nested combination of the above types. +The `Self` terminal in this grammar is the semantic `Self` type and can be +replaced with the type being implemented, including type aliases or associated +type projections for the type. ```rust # use std::rc::Rc; # use std::sync::Arc; # use std::pin::Pin; +// Examples of methods implemented on struct `Example`. struct Example; type Alias = Example; +trait Trait { type Output; } +impl Trait for Example { type Output = Example; } impl Example { fn by_value(self: Self) {} fn by_ref(self: &Self) {} @@ -129,6 +131,7 @@ impl Example { fn explicit_type(self: Arc) {} fn with_lifetime<'a>(self: &'a Self) {} fn nested<'a>(self: &mut &'a Arc>>) {} + fn via_projection(self: ::Output) {} } ``` diff --git a/src/items/traits.md b/src/items/traits.md index b2132a7e8c697..1a65c9239b6ad 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -126,7 +126,7 @@ trait TraitMethods { ``` ```rust,compile_fail -// These are object-safe, but cannot be dispatched on a trait object. +// This trait is object-safe, but these methods cannot be dispatched on a trait object. trait NonDispatchable { // Non-methods cannot be dispatched. fn foo() where Self: Sized {} @@ -135,7 +135,6 @@ trait NonDispatchable { // `other` may be a different concrete type of the receiver. fn param(&self, other: Self) where Self: Sized {} // Generics are not compatible with vtables. - // Alternate solution is to use a trait object instead. fn typed(&self, x: T) where Self: Sized {} } @@ -178,7 +177,7 @@ let obj: Box = Box::new(S); // ERROR ``` ```rust,compile_fail -// Not object safe if `Self` is a type parameter. +// Not object safe if `Self` is a type argument. trait Super {} trait WithSelf: Super where Self: Sized {}