From 04895846f052de936e27b807cfe8d74428827442 Mon Sep 17 00:00:00 2001 From: Havvy Date: Thu, 17 May 2018 02:30:49 -0700 Subject: [PATCH 1/3] Fix implementatoins links on traits item page --- src/items/traits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/items/traits.md b/src/items/traits.md index fd814091d..b785c2f18 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -121,3 +121,4 @@ let nonsense = mycircle.radius() * mycircle.area(); [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md [associated items]: items/associated-items.html [method]: items/associated-items.html#methods +[implementations]: items/implementations.html \ No newline at end of file From b09e52c3ab2a522d5dfc40ca6cc19030f63ded34 Mon Sep 17 00:00:00 2001 From: Havvy Date: Sat, 19 May 2018 14:58:09 -0700 Subject: [PATCH 2/3] Improve wording and examples about supertraits --- src/items/traits.md | 71 +++++++++++++++++++++++---------------------- src/types.md | 7 +++-- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/items/traits.md b/src/items/traits.md index b785c2f18..1ce3ddb68 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -10,7 +10,7 @@ interface consists of [associated items], which come in three varieties: All traits define an implicit type parameter `Self` that refers to "the type that is implementing this interface". Traits may also contain additional type parameters. These type parameters (including `Self`) may be constrained by -other traits and so forth as usual. +other traits and so forth [as usual]. Traits are implemented for specific types through separate [implementations]. @@ -48,71 +48,72 @@ Object safe traits can be the base trait of a [trait object]. A trait is and * Be a [method] that does not use `Self` except in the type of the receiver. * It must not have any associated constants. +* All supertraits must also be object safe. ## Supertraits -Trait bounds on `Self` are considered "supertraits". These are required to be -acyclic. Supertraits are somewhat different from other constraints in that -they affect what methods are available in the vtable when the trait is used as -a [trait object]. Consider the following example: +**Supertraits** are traits that are required to be implemented for a type to +implement a specific trait. Furthermore, anywhere a [generic] or [trait object] +is bounded by a trait, it has access to the associated items of its supertraits. + +Supertraits are declared by trait bounds on the `Self` type of a trait and +transitively the supertraits of the traits declared in those trait bounds. It is +an error for a trait to be its own supertrait. + +The following is an example of declaring `Shape` to be a supertrait of `Circle`. ```rust trait Shape { fn area(&self) -> f64; } trait Circle : Shape { fn radius(&self) -> f64; } ``` -The syntax `Circle : Shape` means that types that implement `Circle` must also -have an implementation for `Shape`. Multiple supertraits are separated by `+`, -`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a -given type `T`, methods can refer to `Shape` methods, since the typechecker -checks that any type with an implementation of `Circle` also has an -implementation of `Shape`: +And the following is the same example, except using [where clauses]. ```rust -struct Foo; - trait Shape { fn area(&self) -> f64; } -trait Circle : Shape { fn radius(&self) -> f64; } -impl Shape for Foo { - fn area(&self) -> f64 { - 0.0 - } -} -impl Circle for Foo { - fn radius(&self) -> f64 { - println!("calling area: {}", self.area()); +trait Circle where Self: Shape { fn radius(&self) -> f64; } +``` + +This next example gives `radius` a default implementation using the `area` +function from `Shape`. - 0.0 +```rust +# trait Shape { fn area(&self) -> f64; } +trait Circle where Self: Shape { + fn radius(&self) -> f64 { + // A = pi * r^2 + // so algebraically, + // r = sqrt(A / pi) + (self.area() /std::f64::consts::PI).sqrt() } } - -let c = Foo; -c.radius(); ``` In type-parameterized functions, methods of the supertrait may be called on -values of subtrait-bound type parameters. Referring to the previous example of +values of subtrait-bound type parameters. Continuing the example of `trait Circle : Shape`: ```rust # trait Shape { fn area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } -fn radius_times_area(c: T) -> f64 { - // `c` is both a Circle and a Shape - c.radius() * c.area() +fn print_area_and_radius(c: C) { + // Here we call the area method from the supertrait `Shape` of `Circle`. + println!("Area: {}", c.area()); + println!("Radius: {}", c.radius()); } ``` -Likewise, supertrait methods may also be called on trait objects. +Likewise, here is an example of calling supertrait methods on trait objects. ```rust # trait Shape { fn area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } +# struct UnitCircle; # impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } # impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } # let mycircle = 0i32; -let mycircle = Box::new(mycircle) as Box; -let nonsense = mycircle.radius() * mycircle.area(); +let circle = Box::new(mycircle) as Box; +let nonsense = circle.radius() * circle.area(); ``` [bounds]: trait-bounds.html @@ -121,4 +122,6 @@ let nonsense = mycircle.radius() * mycircle.area(); [RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md [associated items]: items/associated-items.html [method]: items/associated-items.html#methods -[implementations]: items/implementations.html \ No newline at end of file +[implementations]: items/implementations.html +[as usual]: items/generics.html +[where clauses]: items/generics.html#where-clauses \ No newline at end of file diff --git a/src/types.md b/src/types.md index 1ecf4a829..cf0a324d5 100644 --- a/src/types.md +++ b/src/types.md @@ -545,7 +545,7 @@ A *trait object* is an opaque value of another type that implements a set of traits. The set of traits is made up of an [object safe] *base trait* plus any number of [auto traits]. -Trait objects implement the base trait, its auto traits, and any super traits +Trait objects implement the base trait, its auto traits, and any [supertraits] of the base trait. Trait objects are written as the optional keyword `dyn` followed by a set of @@ -597,8 +597,8 @@ behind some type of pointer; for example `&dyn SomeTrait` or - a pointer to an instance of a type `T` that implements `SomeTrait` - a _virtual method table_, often just called a _vtable_, which contains, for - each method of `SomeTrait` that `T` implements, a pointer to `T`'s - implementation (i.e. a function pointer). + each method of `SomeTrait` and its [supertraits] that `T` implements, a + pointer to `T`'s implementation (i.e. a function pointer). The purpose of trait objects is to permit "late binding" of methods. Calling a method on a trait object results in virtual dispatch at runtime: that is, a @@ -712,3 +712,4 @@ impl Printable for String { [issue 33140]: https://github.com/rust-lang/rust/issues/33140 [_PATH_]: paths.html [_LIFETIME_OR_LABEL_]: tokens.html#lifetimes-and-loop-labels +[supertraits]: items/traits.html#supertraits \ No newline at end of file From d513b236c5f19ac984ae83aa9a84f03736c56e9a Mon Sep 17 00:00:00 2001 From: Havvy Date: Sun, 20 May 2018 02:06:04 -0700 Subject: [PATCH 3/3] More tweaks to supertraits --- src/items/traits.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/items/traits.md b/src/items/traits.md index 1ce3ddb68..e667670ee 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -9,8 +9,8 @@ interface consists of [associated items], which come in three varieties: All traits define an implicit type parameter `Self` that refers to "the type that is implementing this interface". Traits may also contain additional type -parameters. These type parameters (including `Self`) may be constrained by -other traits and so forth [as usual]. +parameters. These type parameters, including `Self`, may be constrained by +other traits and so forth [as usual][generics]. Traits are implemented for specific types through separate [implementations]. @@ -26,8 +26,7 @@ Generic items may use traits as [bounds] on their type parameters. ## Generic Traits Type parameters can be specified for a trait to make it generic. These appear -after the trait name, using the same syntax used in [generic -functions](items/functions.html#generic-functions). +after the trait name, using the same syntax used in [generic functions]. ```rust trait Seq { @@ -60,6 +59,8 @@ Supertraits are declared by trait bounds on the `Self` type of a trait and transitively the supertraits of the traits declared in those trait bounds. It is an error for a trait to be its own supertrait. +The trait with a supertrait is called a **subtrait** of its supertrait. + The following is an example of declaring `Shape` to be a supertrait of `Circle`. ```rust @@ -89,9 +90,7 @@ trait Circle where Self: Shape { } ``` -In type-parameterized functions, methods of the supertrait may be called on -values of subtrait-bound type parameters. Continuing the example of -`trait Circle : Shape`: +This next example calls a supertrait method on a generic parameter. ```rust # trait Shape { fn area(&self) -> f64; } @@ -103,16 +102,16 @@ fn print_area_and_radius(c: C) { } ``` -Likewise, here is an example of calling supertrait methods on trait objects. +Similarly, here is an example of calling supertrait methods on trait objects. ```rust # trait Shape { fn area(&self) -> f64; } # trait Circle : Shape { fn radius(&self) -> f64; } # struct UnitCircle; -# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } -# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } -# let mycircle = 0i32; -let circle = Box::new(mycircle) as Box; +# impl Shape for UnitCircle { fn area(&self) -> f64 { std::f64::consts::PI } } +# impl Circle for UnitCircle { fn radius(&self) -> f64 { 1.0 } } +# let circle = UnitCircle; +let circle = Box::new(circle) as Box; let nonsense = circle.radius() * circle.area(); ``` @@ -123,5 +122,6 @@ let nonsense = circle.radius() * circle.area(); [associated items]: items/associated-items.html [method]: items/associated-items.html#methods [implementations]: items/implementations.html -[as usual]: items/generics.html -[where clauses]: items/generics.html#where-clauses \ No newline at end of file +[generics]: items/generics.html +[where clauses]: items/generics.html#where-clauses +[generic functions]: items/functions.html#generic-functions \ No newline at end of file