Skip to content

Commit 2d313fe

Browse files
committed
Update docs to mention trait constraints; also fix failing doc tests
/cc #4217
1 parent b865b4b commit 2d313fe

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

doc/rust.md

+18-3
Original file line numberDiff line numberDiff line change
@@ -1195,8 +1195,19 @@ Values with a trait type can have [methods called](#method-call-expressions) on
11951195
for any method in the trait,
11961196
and can be used to instantiate type parameters that are bounded by the trait.
11971197

1198-
Trait methods may be static. Currently implementations of static methods behave like
1199-
functions declared in the implentation's module.
1198+
Trait methods may be static.
1199+
Currently, implementations of static methods behave like functions declared in the implementation's module.
1200+
1201+
Traits can have _constraints_ for example, in
1202+
1203+
~~~~
1204+
trait Shape { fn area() -> float; }
1205+
trait Circle : Shape { fn radius() -> float; }
1206+
~~~~
1207+
1208+
the syntax `Circle : Shape` means that types that implement `Circle` must also have an implementation for `Shape`.
1209+
In an implementation of `Circle` for a given type `T`, methods can refer to `Shape` methods,
1210+
since the typechecker checks that any type with an implementation of `Circle` also has an implementation of `Shape`.
12001211

12011212
### Implementations
12021213

@@ -1520,8 +1531,11 @@ To indicate that a field is mutable, the `mut` keyword is written before its nam
15201531
The following are examples of structure expressions:
15211532

15221533
~~~~
1534+
# struct Point { x: float, y: float }
1535+
# mod game { pub struct User { name: &str, age: uint, mut score: uint } }
1536+
# use game;
15231537
Point {x: 10f, y: 20f};
1524-
game::User {name: "Joe", age: 35u, mut score: 100_000};
1538+
let u = game::User {name: "Joe", age: 35u, mut score: 100_000};
15251539
~~~~
15261540

15271541
A structure expression forms a new value of the named structure type.
@@ -1532,6 +1546,7 @@ A new structure will be created, of the same type as the base expression, with t
15321546
and the values in the base record for all other fields.
15331547

15341548
~~~~
1549+
# struct Point3d { x: int, y: int, z: int }
15351550
let base = Point3d {x: 1, y: 2, z: 3};
15361551
Point3d {y: 0, z: 10, .. base};
15371552
~~~~

doc/tutorial.md

+33
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,39 @@ the preferred way to use traits polymorphically.
20762076

20772077
This usage of traits is similar to Haskell type classes.
20782078

2079+
## Trait constraints
2080+
2081+
We can write a trait declaration that is _constrained_ to only be implementable on types that
2082+
also implement some other trait.
2083+
2084+
For example, we can define a `Circle` trait that only types that also have the `Shape` trait can have:
2085+
2086+
~~~~
2087+
trait Shape { fn area() -> float; }
2088+
trait Circle : Shape { fn radius() -> float; }
2089+
~~~~
2090+
2091+
Now, implementations of `Circle` methods can call `Shape` methods:
2092+
2093+
~~~~
2094+
# trait Shape { fn area() -> float; }
2095+
# trait Circle : Shape { fn radius() -> float; }
2096+
# struct Point { x: float, y: float }
2097+
# use float::consts::pi;
2098+
# use float::sqrt;
2099+
# fn square(x: float) -> float { x * x }
2100+
struct CircleStruct { center: Point, radius: float }
2101+
impl CircleStruct: Circle {
2102+
fn radius() -> float { sqrt(self.area() / pi) }
2103+
}
2104+
impl CircleStruct: Shape {
2105+
fn area() -> float { pi * square(self.radius) }
2106+
}
2107+
~~~~
2108+
2109+
This is a silly way to compute the radius of a circle
2110+
(since we could just return the `circle` field), but you get the idea.
2111+
20792112
## Trait objects and dynamic method dispatch
20802113

20812114
The above allows us to define functions that polymorphically act on

0 commit comments

Comments
 (0)