@@ -9,8 +9,8 @@ interface consists of [associated items], which come in three varieties:
9
9
10
10
All traits define an implicit type parameter ` Self ` that refers to "the type
11
11
that is implementing this interface". Traits may also contain additional type
12
- parameters. These type parameters ( including ` Self ` ) may be constrained by
13
- other traits and so forth as usual.
12
+ parameters. These type parameters, including ` Self ` , may be constrained by
13
+ other traits and so forth [ as usual] [ generics ] .
14
14
15
15
Traits are implemented for specific types through separate [ implementations] .
16
16
@@ -26,8 +26,7 @@ Generic items may use traits as [bounds] on their type parameters.
26
26
## Generic Traits
27
27
28
28
Type parameters can be specified for a trait to make it generic. These appear
29
- after the trait name, using the same syntax used in [ generic
30
- functions] ( items/functions.html#generic-functions ) .
29
+ after the trait name, using the same syntax used in [ generic functions] .
31
30
32
31
``` rust
33
32
trait Seq <T > {
@@ -48,71 +47,72 @@ Object safe traits can be the base trait of a [trait object]. A trait is
48
47
and
49
48
* Be a [ method] that does not use ` Self ` except in the type of the receiver.
50
49
* It must not have any associated constants.
50
+ * All supertraits must also be object safe.
51
51
52
52
## Supertraits
53
53
54
- Trait bounds on ` Self ` are considered "supertraits". These are required to be
55
- acyclic. Supertraits are somewhat different from other constraints in that
56
- they affect what methods are available in the vtable when the trait is used as
57
- a [ trait object] . Consider the following example:
54
+ ** Supertraits** are traits that are required to be implemented for a type to
55
+ implement a specific trait. Furthermore, anywhere a [ generic] or [ trait object]
56
+ is bounded by a trait, it has access to the associated items of its supertraits.
57
+
58
+ Supertraits are declared by trait bounds on the ` Self ` type of a trait and
59
+ transitively the supertraits of the traits declared in those trait bounds. It is
60
+ an error for a trait to be its own supertrait.
61
+
62
+ The trait with a supertrait is called a ** subtrait** of its supertrait.
63
+
64
+ The following is an example of declaring ` Shape ` to be a supertrait of ` Circle ` .
58
65
59
66
``` rust
60
67
trait Shape { fn area (& self ) -> f64 ; }
61
68
trait Circle : Shape { fn radius (& self ) -> f64 ; }
62
69
```
63
70
64
- The syntax ` Circle : Shape ` means that types that implement ` Circle ` must also
65
- have an implementation for ` Shape ` . Multiple supertraits are separated by ` + ` ,
66
- ` trait Circle : Shape + PartialEq { } ` . In an implementation of ` Circle ` for a
67
- given type ` T ` , methods can refer to ` Shape ` methods, since the typechecker
68
- checks that any type with an implementation of ` Circle ` also has an
69
- implementation of ` Shape ` :
71
+ And the following is the same example, except using [ where clauses] .
70
72
71
73
``` rust
72
- struct Foo ;
73
-
74
74
trait Shape { fn area (& self ) -> f64 ; }
75
- trait Circle : Shape { fn radius (& self ) -> f64 ; }
76
- impl Shape for Foo {
77
- fn area (& self ) -> f64 {
78
- 0.0
79
- }
80
- }
81
- impl Circle for Foo {
82
- fn radius (& self ) -> f64 {
83
- println! (" calling area: {}" , self . area ());
75
+ trait Circle where Self : Shape { fn radius (& self ) -> f64 ; }
76
+ ```
84
77
85
- 0.0
78
+ This next example gives ` radius ` a default implementation using the ` area `
79
+ function from ` Shape ` .
80
+
81
+ ``` rust
82
+ # trait Shape { fn area (& self ) -> f64 ; }
83
+ trait Circle where Self : Shape {
84
+ fn radius (& self ) -> f64 {
85
+ // A = pi * r^2
86
+ // so algebraically,
87
+ // r = sqrt(A / pi)
88
+ (self . area () / std :: f64 :: consts :: PI ). sqrt ()
86
89
}
87
90
}
88
-
89
- let c = Foo ;
90
- c . radius ();
91
91
```
92
92
93
- In type-parameterized functions, methods of the supertrait may be called on
94
- values of subtrait-bound type parameters. Referring to the previous example of
95
- ` trait Circle : Shape ` :
93
+ This next example calls a supertrait method on a generic parameter.
96
94
97
95
``` rust
98
96
# trait Shape { fn area (& self ) -> f64 ; }
99
97
# trait Circle : Shape { fn radius (& self ) -> f64 ; }
100
- fn radius_times_area <T : Circle >(c : T ) -> f64 {
101
- // `c` is both a Circle and a Shape
102
- c . radius () * c . area ()
98
+ fn print_area_and_radius <C : Circle >(c : C ) {
99
+ // Here we call the area method from the supertrait `Shape` of `Circle`.
100
+ println! (" Area: {}" , c . area ());
101
+ println! (" Radius: {}" , c . radius ());
103
102
}
104
103
```
105
104
106
- Likewise, supertrait methods may also be called on trait objects.
105
+ Similarly, here is an example of calling supertrait methods on trait objects.
107
106
108
107
``` rust
109
108
# trait Shape { fn area (& self ) -> f64 ; }
110
109
# trait Circle : Shape { fn radius (& self ) -> f64 ; }
111
- # impl Shape for i32 { fn area (& self ) -> f64 { 0.0 } }
112
- # impl Circle for i32 { fn radius (& self ) -> f64 { 0.0 } }
113
- # let mycircle = 0i32 ;
114
- let mycircle = Box :: new (mycircle ) as Box <Circle >;
115
- let nonsense = mycircle . radius () * mycircle . area ();
110
+ # struct UnitCircle ;
111
+ # impl Shape for UnitCircle { fn area (& self ) -> f64 { std :: f64 :: consts :: PI } }
112
+ # impl Circle for UnitCircle { fn radius (& self ) -> f64 { 1.0 } }
113
+ # let circle = UnitCircle ;
114
+ let circle = Box :: new (circle ) as Box <dyn Circle >;
115
+ let nonsense = circle . radius () * circle . area ();
116
116
```
117
117
118
118
[ bounds ] : trait-bounds.html
@@ -121,3 +121,7 @@ let nonsense = mycircle.radius() * mycircle.area();
121
121
[ RFC 255 ] : https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
122
122
[ associated items ] : items/associated-items.html
123
123
[ method ] : items/associated-items.html#methods
124
+ [ implementations ] : items/implementations.html
125
+ [ generics ] : items/generics.html
126
+ [ where clauses ] : items/generics.html#where-clauses
127
+ [ generic functions ] : items/functions.html#generic-functions
0 commit comments