Skip to content

Commit d9e6a59

Browse files
authored
Merge pull request #258 from matthewjasper/generic-parameters
Generic parameters
2 parents 465db1c + 00d5651 commit d9e6a59

10 files changed

+269
-63
lines changed

Diff for: src/SUMMARY.md

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- [Traits](items/traits.md)
3535
- [Implementations](items/implementations.md)
3636
- [External blocks](items/external-blocks.md)
37+
- [Type and lifetime parameters](items/generics.md)
3738
- [Associated Items](items/associated-items.md)
3839
- [Visibility and Privacy](visibility-and-privacy.md)
3940
- [Attributes](attributes.md)
@@ -66,6 +67,7 @@
6667
- [Type layout](type-layout.md)
6768
- [Interior mutability](interior-mutability.md)
6869
- [Subtyping and Variance](subtyping.md)
70+
- [Trait and lifetime bounds](trait-bounds.md)
6971
- [Type coercions](type-coercions.md)
7072
- [Destructors](destructors.md)
7173
- [Lifetime elision](lifetime-elision.md)

Diff for: src/items.md

-19
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,3 @@ as if the item was declared outside the scope — it is still a static item
3636
qualified by the name of the enclosing item, or is private to the enclosing
3737
item (in the case of functions). The grammar specifies the exact locations in
3838
which sub-item declarations may appear.
39-
40-
## Type Parameters
41-
42-
Functions, type aliases, structs, enumerations, unions, traits and
43-
implementations may be *parameterized* by type. Type parameters are given as a
44-
comma-separated list of identifiers enclosed in angle brackets (`<...>`), after
45-
the name of the item (except for implementations, where they come directly
46-
after `impl`) and before its definition.
47-
48-
The type parameters of an item are considered "part of the name", not part of
49-
the type of the item. A referencing [path] must (in principle) provide type
50-
arguments as a list of comma-separated types enclosed within angle brackets, in
51-
order to refer to the type-parameterized item. In practice, the type-inference
52-
system can usually infer such argument types from context. There are no general
53-
type-parametric types, only type-parametric items. That is, Rust has no notion
54-
of type abstraction: there are no higher-ranked (or "forall") types abstracted
55-
over other types, though higher-ranked types do exist for lifetimes.
56-
57-
[path]: paths.html

Diff for: src/items/enumerations.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ enum ZeroVariants {}
132132
```
133133

134134
[IDENTIFIER]: identifiers.html
135-
[_Generics_]: items.html#type-parameters
136-
[_WhereClause_]: items.html#type-parameters
135+
[_Generics_]: items/generics.html
136+
[_WhereClause_]: items/generics.html#where-clauses
137137
[_Expression_]: expressions.html
138138
[_TupleFields_]: items/structs.html
139139
[_StructFields_]: items/structs.html

Diff for: src/items/generics.md

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Type and Lifetime Parameters
2+
3+
> **<sup>Syntax</sup>**
4+
> _Generics_ :
5+
> &nbsp;&nbsp; `<` _GenericParams_ `>`
6+
>
7+
> _GenericParams_ :
8+
> &nbsp;&nbsp; &nbsp;&nbsp; _LifetimeParams_
9+
> &nbsp;&nbsp; | ( _LifetimeParam_ `,` )<sup>\*</sup> _TypeParams_
10+
>
11+
> _LifetimeParams_ :
12+
> &nbsp;&nbsp; ( _LifetimeParam_ `,` )<sup>\*</sup> _LifetimeParam_<sup>?</sup>
13+
>
14+
> _LifetimeParam_ :
15+
> &nbsp;&nbsp; [LIFETIME_OR_LABEL] `:` [_LifetimeBounds_]<sup>?</sup>
16+
>
17+
> _TypeParams_:
18+
> &nbsp;&nbsp; ( _TypeParam_ `,` )<sup>\*</sup> _TypeParam_ <sup>?</sup>
19+
>
20+
> _TypeParam_ :
21+
> &nbsp;&nbsp; [IDENTIFIER] ( `:` [_TypeParamBounds_] )<sup>?</sup> ( `=` [_Type_] )<sup>?</sup>
22+
23+
Functions, type aliases, structs, enumerations, unions, traits and
24+
implementations may be *parameterized* by types and lifetimes. These parameters
25+
are listed in angle <span class="parenthetical">brackets (`<...>`)</span>,
26+
usually immediately after and before its definition the name of the item. For
27+
implementations, which don't have a name, they come directly after `impl`.
28+
Lifetime parameters must be declared before type parameters. Some examples of
29+
items with type and lifetime parameters:
30+
31+
```rust
32+
fn foo<'a, T>() {}
33+
trait A<U> {}
34+
struct Ref<'a, T> where T: 'a { r: &'a T }
35+
```
36+
37+
[References], [raw pointers], [arrays], [slices][arrays], [tuples] and
38+
[function pointers] have lifetime or type parameters as well, but are not
39+
referred to with path syntax.
40+
41+
## Where clauses
42+
43+
> **<sup>Syntax</sup>**
44+
> _WhereClause_ :
45+
> &nbsp;&nbsp; `where` ( _WhereClauseItem_ `,` )<sup>\*</sup> _WhereClauseItem_ <sup>?</sup>
46+
>
47+
> _WhereClauseItem_ :
48+
> &nbsp;&nbsp; &nbsp;&nbsp; _LifetimeWhereClauseItem_
49+
> &nbsp;&nbsp; | _TypeBoundWhereClauseItem_
50+
>
51+
> _LifetimeWhereClauseItem_ :
52+
> &nbsp;&nbsp; [_Lifetime_] `:` [_LifetimeBounds_]
53+
>
54+
> _TypeBoundWhereClauseItem_ :
55+
> &nbsp;&nbsp; _ForLifetimes_<sup>?</sup> [_Type_] `:` [_TypeParamBounds_]<sup>?</sup>
56+
>
57+
> _ForLifetimes_ :
58+
> &nbsp;&nbsp; `for` `<` [_LifetimeParams_](#type-and-lifetime-parameters) `>`
59+
60+
*Where clauses* provide an another way to specify bounds on type and lifetime
61+
parameters as well as a way to specify bounds on types that aren't type
62+
parameters.
63+
64+
Bounds that don't use the item's parameters or higher-ranked lifetimes are
65+
checked when the item is defined. It is an error for such a bound to be false.
66+
67+
[`Copy`], [`Clone`] and [`Sized`] bounds are also checked for certain generic
68+
types when defining the item. It is an error to have `Copy` or `Clone`as a
69+
bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
70+
bound on a trait object or slice.
71+
72+
```rust,ignore
73+
struct A<T>
74+
where
75+
T: Iterator, // Could use A<T: Iterator> instead
76+
T::Item: Copy,
77+
String: PartialEq<T>,
78+
i32: Default, // Allowed, but not useful
79+
i32: Iterator, // Error: the trait bound is not satisfied
80+
[T]: Copy, // Error: the trait bound is not satisfied
81+
{
82+
f: T,
83+
}
84+
```
85+
86+
[IDENTIFIER]: identifiers.html
87+
[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
88+
89+
[_LifetimeBounds_]: trait-bounds.html
90+
[_Lifetime_]: trait-bounds.html
91+
[_Type_]: types.html
92+
[_TypeParamBounds_]: trait-bounds.html
93+
94+
[arrays]: types.html#array-and-slice-types
95+
[function pointers]: types.html#function-pointer-types
96+
[references]: types.html#shared-references-
97+
[raw pointers]: types.html#raw-pointers-const-and-mut
98+
[`Clone`]: special-types-and-traits.html#clone
99+
[`Copy`]: special-types-and-traits.html#copy
100+
[`Sized`]: special-types-and-traits.html#sized
101+
[tuples]: types.html#tuple-types
102+
[trait object]: types.html#trait-objects
103+
104+
[path]: ../paths.html
105+
[Trait]: traits.html#trait-bounds
106+
[_TypePath_]: paths.html

Diff for: src/items/structs.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ particular layout using the [`repr` attribute].
8282

8383
[_OuterAttribute_]: attributes.html
8484
[IDENTIFIER]: identifiers.html
85-
[_Generics_]: items.html#type-parameters
86-
[_WhereClause_]: items.html#type-parameters
85+
[_Generics_]: items/generics.html
86+
[_WhereClause_]: items/generics.html#where-clauses
8787
[_Visibility_]: visibility-and-privacy.html
8888
[_Type_]: types.html

Diff for: src/items/traits.md

+2-30
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,7 @@ any implementation must provide a definition.
2121

2222
## Trait bounds
2323

24-
Generic functions may use traits as _bounds_ on their type parameters. This
25-
will have three effects:
26-
27-
- Only types that have the trait may instantiate the parameter.
28-
- Within the generic function, the functions of the trait can be called on
29-
values that have the parameter's type. Associated types can be used in the
30-
function's signature, and associated constants can be used in expressions
31-
within the function body.
32-
- Generic functions and types with the same or weaker bounds can use the
33-
generic type in the function body or signature.
34-
35-
For example:
36-
37-
```rust
38-
# type Surface = i32;
39-
# trait Shape { fn draw(&self, Surface); }
40-
struct Figure<S: Shape>(S, S);
41-
fn draw_twice<T: Shape>(surface: Surface, sh: T) {
42-
sh.draw(surface);
43-
sh.draw(surface);
44-
}
45-
fn draw_figure<U: Shape>(surface: Surface, Figure(sh1, sh2): Figure<U>) {
46-
sh1.draw(surface);
47-
draw_twice(surface, sh2); // Can call this since U: Shape
48-
}
49-
```
24+
Generic items may use traits as [bounds] on their type parameters.
5025

5126
## Generic Traits
5227

@@ -140,10 +115,7 @@ let mycircle = Box::new(mycircle) as Box<Circle>;
140115
let nonsense = mycircle.radius() * mycircle.area();
141116
```
142117

143-
[`Send`]: ../std/marker/trait.Send.html
144-
[`Send`]: ../std/marker/trait.Sync.html
145-
[`UnwindSafe`]: ../std/panic/trait.UnwindSafe.html
146-
[`RefUnwindSafe`]: ../std/panic/trait.RefUnwindSafe.html
118+
[bounds]: trait-bounds.html
147119
[trait object]: types.html#trait-objects
148120
[explicit]: expressions/operator-expr.html#type-cast-expressions
149121
[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md

Diff for: src/items/type-aliases.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ let _: F = E::A; // OK
3030
```
3131

3232
[IDENTIFIER]: identifiers.html
33-
[_Generics_]: items.html#type-parameters
34-
[_WhereClause_]: items.html#type-parameters
33+
[_Generics_]: items/generics.html
34+
[_WhereClause_]: items/generics.html#where-clauses
3535
[_Type_]: types.html

Diff for: src/items/unions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,6 @@ More detailed specification for unions, including unstable bits, can be found
146146
in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897).
147147

148148
[IDENTIFIER]: identifiers.html
149-
[_Generics_]: items.html#type-parameters
150-
[_WhereClause_]: items.html#type-parameters
149+
[_Generics_]: items/generics.html
150+
[_WhereClause_]: items/generics.html#where-clauses
151151
[_StructFields_]: items/structs.html

Diff for: src/trait-bounds.md

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Trait and lifetime bounds
2+
3+
> **<sup>Syntax</sup>**
4+
> _TypeParamBounds_ :
5+
> &nbsp;&nbsp; _TypeParamBound_ ( `+` _TypeParamBound_ )<sup>\*</sup> `+`<sup>?</sup>
6+
>
7+
> _TypeParamBound_ :
8+
> &nbsp;&nbsp; &nbsp;&nbsp; _Lifetime_ | _TraitBound_
9+
>
10+
> _TraitBound_ :
11+
> &nbsp;&nbsp; &nbsp;&nbsp; `?`<sup>?</sup>
12+
> [_ForLifetimes_](#higher-ranked-trait-bounds)<sup>?</sup> [_TraitPath_]
13+
> &nbsp;&nbsp; | `(` `?`<sup>?</sup>
14+
> [_ForLifetimes_](#higher-ranked-trait-bounds)<sup>?</sup> [_TraitPath_] `)`
15+
>
16+
> _LifetimeBounds_ :
17+
> &nbsp;&nbsp; ( _Lifetime_ `+` )<sup>\*</sup> _Lifetime_<sup>?</sup>
18+
>
19+
> _Lifetime_ :
20+
> &nbsp;&nbsp; &nbsp;&nbsp; [LIFETIME_OR_LABEL]
21+
> &nbsp;&nbsp; | `'static`
22+
23+
[Trait] and lifetime bounds provide a way for [generic items][generic] to
24+
restrict which types and lifetimes are used as their parameters. Bounds can be
25+
provided on any type in a [where clause]. There are also shorter forms for
26+
certain common cases:
27+
28+
* Bounds written after declaring a [generic parameter][generic]:
29+
`fn f<A: Copy>() {}` is the same as `fn f<A> where A: Copy () {}`.
30+
* In trait declarations as [supertraits]: `trait Circle : Shape {}` is
31+
equivalent to `trait Circle where Self : Shape {}`.
32+
* In trait declarations as bounds on [associated types]:
33+
`trait A { type B: Copy; }` is equivalent to
34+
`trait A where Self::B: Copy { type B; }`.
35+
36+
Bounds on an item must be satisfied when using the item. When type checking and
37+
borrow checking a generic item, the bounds can be used to determine that a
38+
trait is implemented for a type. For example, given `Ty: Trait`
39+
40+
* In the body of a generic function, methods from `Trait` can be called on `Ty`
41+
values. Likewise associated constants on the `Trait` can be used.
42+
* Associated types from `Trait` can be used.
43+
* Generic functions and types with a `T: Trait` bounds can be used with `Ty`
44+
being used for `T`.
45+
46+
```rust
47+
# type Surface = i32;
48+
trait Shape {
49+
fn draw(&self, Surface);
50+
fn name() -> &'static str;
51+
}
52+
53+
fn draw_twice<T: Shape>(surface: Surface, sh: T) {
54+
sh.draw(surface); // Can call method because T: Shape
55+
sh.draw(surface);
56+
}
57+
58+
fn copy_and_draw_twice<T: Copy>(surface: Surface, sh: T) where T: Shape {
59+
let shape_copy = sh; // doesn't move sh because T: Copy
60+
draw_twice(surface, sh); // Can use generic function because T: Shape
61+
}
62+
63+
struct Figure<S: Shape>(S, S);
64+
65+
fn name_figure<U: Shape>(
66+
figure: Figure<U>, // Type Figure<U> is well-formed because U: Shape
67+
) {
68+
println!(
69+
"Figure of two {}",
70+
U::name(), // Can use associated function
71+
);
72+
}
73+
```
74+
75+
Trait and lifetime bounds are also used to name [trait objects].
76+
77+
## `?Sized`
78+
79+
`?` is only used to declare that the [`Sized`] trait may not be
80+
implemented for a type parameter or associated type. `?Sized` may
81+
not be used as a bound for other types.
82+
83+
## Lifetime bounds
84+
85+
Lifetime bounds can be applied to types or other lifetimes. The bound `'a: 'b`
86+
is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` lasts longer
87+
than `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid.
88+
89+
```rust
90+
fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b {
91+
y = x; // &'a i32 is a subtype of &'b i32 because 'a: 'b
92+
let r: &'b &'a i32 = &&0; // &'b &'a i32 is well formed because 'a: 'b
93+
}
94+
```
95+
96+
`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example if
97+
`'a` is an unconstrained lifetime parameter then `i32: 'static` and
98+
`&'static str: 'a` are satisfied but `Vec<&'a ()>: 'static` is not.
99+
100+
## Higher-ranked trait bounds
101+
102+
Type bounds may be *higher ranked* over lifetimes. These bounds specify a bound
103+
is true *for all* lifetimes. For example, a bound such as `for<'a> &'a T:
104+
PartialEq<i32>` would require an implementation like
105+
106+
```rust,ignore
107+
impl<'a> PartialEq<i32> for &'a T {
108+
// ...
109+
}
110+
```
111+
112+
and could then be used to compare a `&'a T` with any lifetime to an `i32`.
113+
114+
Only a higher-ranked bound can be used here as the lifetime of the reference is
115+
shorter than a lifetime parameter on the function:
116+
117+
```rust
118+
fn call_on_ref_zero<F>(f: F) where for<'a> F: Fn(&'a i32) {
119+
let zero = 0;
120+
f(&zero);
121+
}
122+
```
123+
124+
Higher-ranked lifetimes may also be specified just before the trait, the only
125+
end of the following trait instead of the whole bound. This function is
126+
difference is the scope of the lifetime parameter, which extends only to the
127+
equivalent to the last one.
128+
129+
```rust
130+
fn call_on_ref_zero<F>(f: F) where F: for<'a> Fn(&'a i32) {
131+
let zero = 0;
132+
f(&zero);
133+
}
134+
```
135+
136+
> Warning: lifetime bounds are allowed on lifetimes in a `for` binder, but have
137+
> no effect: `for<'a, 'b: 'a>` is no different to `for<'a, 'b>`.
138+
139+
[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
140+
[_TraitPath_]: paths.html
141+
[`Sized`]: special-types-and-traits.html#sized
142+
143+
[associated types]: items/associated-items.html#associated-types
144+
[supertraits]: items/traits.html#supertraits
145+
[generic]: items/generics.html
146+
[Trait]: traits.html#trait-bounds
147+
[trait objects]: types.html#trait-objects
148+
[where clause]: items/where-clauses.html

Diff for: src/types.md

+3-6
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,9 @@ Because captures are often by reference, the following general rules arise:
537537

538538
## Trait objects
539539

540-
> **<sup>Syntax</sup>**
541-
> _TraitObjectType_ :
542-
> &nbsp;&nbsp; `dyn`<sup>?</sup> _LifetimeOrPath_ ( `+` _LifetimeOrPath_ )<sup>\*</sup> `+`<sup>?</sup>
543-
>
544-
> _LifetimeOrPath_ :
545-
> &nbsp;&nbsp; [_Path_] | `(` [_Path_] `)` | [_LIFETIME_OR_LABEL_]
540+
> **<sup>Syntax</sup>**
541+
> _TraitObjectType_ :
542+
> &nbsp;&nbsp; `dyn`<sup>?</sup> _TypeParamBounds_
546543
547544
A *trait object* is an opaque value of another type that implements a set of
548545
traits. The set of traits is made up of an [object safe] *base trait* plus any

0 commit comments

Comments
 (0)