diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index f273f771c..23e243fdb 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -34,6 +34,7 @@
- [Traits](items/traits.md)
- [Implementations](items/implementations.md)
- [External blocks](items/external-blocks.md)
+ - [Type and lifetime parameters](items/generics.md)
- [Associated Items](items/associated-items.md)
- [Visibility and Privacy](visibility-and-privacy.md)
- [Attributes](attributes.md)
@@ -66,6 +67,7 @@
- [Type layout](type-layout.md)
- [Interior mutability](interior-mutability.md)
- [Subtyping and Variance](subtyping.md)
+ - [Trait and lifetime bounds](trait-bounds.md)
- [Type coercions](type-coercions.md)
- [Destructors](destructors.md)
- [Lifetime elision](lifetime-elision.md)
diff --git a/src/items.md b/src/items.md
index 75da8be93..4d10da30a 100644
--- a/src/items.md
+++ b/src/items.md
@@ -36,22 +36,3 @@ as if the item was declared outside the scope — it is still a static item
qualified by the name of the enclosing item, or is private to the enclosing
item (in the case of functions). The grammar specifies the exact locations in
which sub-item declarations may appear.
-
-## Type Parameters
-
-Functions, type aliases, structs, enumerations, unions, traits and
-implementations may be *parameterized* by type. Type parameters are given as a
-comma-separated list of identifiers enclosed in angle brackets (`<...>`), after
-the name of the item (except for implementations, where they come directly
-after `impl`) and before its definition.
-
-The type parameters of an item are considered "part of the name", not part of
-the type of the item. A referencing [path] must (in principle) provide type
-arguments as a list of comma-separated types enclosed within angle brackets, in
-order to refer to the type-parameterized item. In practice, the type-inference
-system can usually infer such argument types from context. There are no general
-type-parametric types, only type-parametric items. That is, Rust has no notion
-of type abstraction: there are no higher-ranked (or "forall") types abstracted
-over other types, though higher-ranked types do exist for lifetimes.
-
-[path]: paths.html
diff --git a/src/items/enumerations.md b/src/items/enumerations.md
index 014e6ac3c..a9419d750 100644
--- a/src/items/enumerations.md
+++ b/src/items/enumerations.md
@@ -132,8 +132,8 @@ enum ZeroVariants {}
```
[IDENTIFIER]: identifiers.html
-[_Generics_]: items.html#type-parameters
-[_WhereClause_]: items.html#type-parameters
+[_Generics_]: items/generics.html
+[_WhereClause_]: items/generics.html#where-clauses
[_Expression_]: expressions.html
[_TupleFields_]: items/structs.html
[_StructFields_]: items/structs.html
diff --git a/src/items/generics.md b/src/items/generics.md
new file mode 100644
index 000000000..8c9214c5b
--- /dev/null
+++ b/src/items/generics.md
@@ -0,0 +1,106 @@
+# Type and Lifetime Parameters
+
+> **Syntax**
+> _Generics_ :
+> `<` _GenericParams_ `>`
+>
+> _GenericParams_ :
+> _LifetimeParams_
+> | ( _LifetimeParam_ `,` )\* _TypeParams_
+>
+> _LifetimeParams_ :
+> ( _LifetimeParam_ `,` )\* _LifetimeParam_?
+>
+> _LifetimeParam_ :
+> [LIFETIME_OR_LABEL] `:` [_LifetimeBounds_]?
+>
+> _TypeParams_:
+> ( _TypeParam_ `,` )\* _TypeParam_ ?
+>
+> _TypeParam_ :
+> [IDENTIFIER] ( `:` [_TypeParamBounds_] )? ( `=` [_Type_] )?
+
+Functions, type aliases, structs, enumerations, unions, traits and
+implementations may be *parameterized* by types and lifetimes. These parameters
+are listed in angle brackets (`<...>`),
+usually immediately after and before its definition the name of the item. For
+implementations, which don't have a name, they come directly after `impl`.
+Lifetime parameters must be declared before type parameters. Some examples of
+items with type and lifetime parameters:
+
+```rust
+fn foo<'a, T>() {}
+trait A {}
+struct Ref<'a, T> where T: 'a { r: &'a T }
+```
+
+[References], [raw pointers], [arrays], [slices][arrays], [tuples] and
+[function pointers] have lifetime or type parameters as well, but are not
+referred to with path syntax.
+
+## Where clauses
+
+> **Syntax**
+> _WhereClause_ :
+> `where` ( _WhereClauseItem_ `,` )\* _WhereClauseItem_ ?
+>
+> _WhereClauseItem_ :
+> _LifetimeWhereClauseItem_
+> | _TypeBoundWhereClauseItem_
+>
+> _LifetimeWhereClauseItem_ :
+> [_Lifetime_] `:` [_LifetimeBounds_]
+>
+> _TypeBoundWhereClauseItem_ :
+> _ForLifetimes_? [_Type_] `:` [_TypeParamBounds_]?
+>
+> _ForLifetimes_ :
+> `for` `<` [_LifetimeParams_](#type-and-lifetime-parameters) `>`
+
+*Where clauses* provide an another way to specify bounds on type and lifetime
+parameters as well as a way to specify bounds on types that aren't type
+parameters.
+
+Bounds that don't use the item's parameters or higher-ranked lifetimes are
+checked when the item is defined. It is an error for such a bound to be false.
+
+[`Copy`], [`Clone`] and [`Sized`] bounds are also checked for certain generic
+types when defining the item. It is an error to have `Copy` or `Clone`as a
+bound on a mutable reference, [trait object] or [slice][arrays] or `Sized` as a
+bound on a trait object or slice.
+
+```rust,ignore
+struct A
+where
+ T: Iterator, // Could use A instead
+ T::Item: Copy,
+ String: PartialEq,
+ i32: Default, // Allowed, but not useful
+ i32: Iterator, // Error: the trait bound is not satisfied
+ [T]: Copy, // Error: the trait bound is not satisfied
+{
+ f: T,
+}
+```
+
+[IDENTIFIER]: identifiers.html
+[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
+
+[_LifetimeBounds_]: trait-bounds.html
+[_Lifetime_]: trait-bounds.html
+[_Type_]: types.html
+[_TypeParamBounds_]: trait-bounds.html
+
+[arrays]: types.html#array-and-slice-types
+[function pointers]: types.html#function-pointer-types
+[references]: types.html#shared-references-
+[raw pointers]: types.html#raw-pointers-const-and-mut
+[`Clone`]: special-types-and-traits.html#clone
+[`Copy`]: special-types-and-traits.html#copy
+[`Sized`]: special-types-and-traits.html#sized
+[tuples]: types.html#tuple-types
+[trait object]: types.html#trait-objects
+
+[path]: ../paths.html
+[Trait]: traits.html#trait-bounds
+[_TypePath_]: paths.html
diff --git a/src/items/structs.md b/src/items/structs.md
index 26f3421d5..362259095 100644
--- a/src/items/structs.md
+++ b/src/items/structs.md
@@ -82,7 +82,7 @@ particular layout using the [`repr` attribute].
[_OuterAttribute_]: attributes.html
[IDENTIFIER]: identifiers.html
-[_Generics_]: items.html#type-parameters
-[_WhereClause_]: items.html#type-parameters
+[_Generics_]: items/generics.html
+[_WhereClause_]: items/generics.html#where-clauses
[_Visibility_]: visibility-and-privacy.html
[_Type_]: types.html
diff --git a/src/items/traits.md b/src/items/traits.md
index 504ebb49d..fd814091d 100644
--- a/src/items/traits.md
+++ b/src/items/traits.md
@@ -21,32 +21,7 @@ any implementation must provide a definition.
## Trait bounds
-Generic functions may use traits as _bounds_ on their type parameters. This
-will have three effects:
-
-- Only types that have the trait may instantiate the parameter.
-- Within the generic function, the functions of the trait can be called on
- values that have the parameter's type. Associated types can be used in the
- function's signature, and associated constants can be used in expressions
- within the function body.
-- Generic functions and types with the same or weaker bounds can use the
- generic type in the function body or signature.
-
-For example:
-
-```rust
-# type Surface = i32;
-# trait Shape { fn draw(&self, Surface); }
-struct Figure(S, S);
-fn draw_twice(surface: Surface, sh: T) {
- sh.draw(surface);
- sh.draw(surface);
-}
-fn draw_figure(surface: Surface, Figure(sh1, sh2): Figure) {
- sh1.draw(surface);
- draw_twice(surface, sh2); // Can call this since U: Shape
-}
-```
+Generic items may use traits as [bounds] on their type parameters.
## Generic Traits
@@ -140,10 +115,7 @@ let mycircle = Box::new(mycircle) as Box;
let nonsense = mycircle.radius() * mycircle.area();
```
-[`Send`]: ../std/marker/trait.Send.html
-[`Send`]: ../std/marker/trait.Sync.html
-[`UnwindSafe`]: ../std/panic/trait.UnwindSafe.html
-[`RefUnwindSafe`]: ../std/panic/trait.RefUnwindSafe.html
+[bounds]: trait-bounds.html
[trait object]: types.html#trait-objects
[explicit]: expressions/operator-expr.html#type-cast-expressions
[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md
index 460d55f03..38f4276d5 100644
--- a/src/items/type-aliases.md
+++ b/src/items/type-aliases.md
@@ -30,6 +30,6 @@ let _: F = E::A; // OK
```
[IDENTIFIER]: identifiers.html
-[_Generics_]: items.html#type-parameters
-[_WhereClause_]: items.html#type-parameters
+[_Generics_]: items/generics.html
+[_WhereClause_]: items/generics.html#where-clauses
[_Type_]: types.html
diff --git a/src/items/unions.md b/src/items/unions.md
index 6c64ef82b..9e2b9c628 100644
--- a/src/items/unions.md
+++ b/src/items/unions.md
@@ -146,6 +146,6 @@ More detailed specification for unions, including unstable bits, can be found
in [RFC 1897 "Unions v1.2"](https://github.com/rust-lang/rfcs/pull/1897).
[IDENTIFIER]: identifiers.html
-[_Generics_]: items.html#type-parameters
-[_WhereClause_]: items.html#type-parameters
+[_Generics_]: items/generics.html
+[_WhereClause_]: items/generics.html#where-clauses
[_StructFields_]: items/structs.html
diff --git a/src/trait-bounds.md b/src/trait-bounds.md
new file mode 100644
index 000000000..e4278db91
--- /dev/null
+++ b/src/trait-bounds.md
@@ -0,0 +1,148 @@
+# Trait and lifetime bounds
+
+> **Syntax**
+> _TypeParamBounds_ :
+> _TypeParamBound_ ( `+` _TypeParamBound_ )\* `+`?
+>
+> _TypeParamBound_ :
+> _Lifetime_ | _TraitBound_
+>
+> _TraitBound_ :
+> `?`?
+> [_ForLifetimes_](#higher-ranked-trait-bounds)? [_TraitPath_]
+> | `(` `?`?
+> [_ForLifetimes_](#higher-ranked-trait-bounds)? [_TraitPath_] `)`
+>
+> _LifetimeBounds_ :
+> ( _Lifetime_ `+` )\* _Lifetime_?
+>
+> _Lifetime_ :
+> [LIFETIME_OR_LABEL]
+> | `'static`
+
+[Trait] and lifetime bounds provide a way for [generic items][generic] to
+restrict which types and lifetimes are used as their parameters. Bounds can be
+provided on any type in a [where clause]. There are also shorter forms for
+certain common cases:
+
+* Bounds written after declaring a [generic parameter][generic]:
+ `fn f() {}` is the same as `fn f where A: Copy () {}`.
+* In trait declarations as [supertraits]: `trait Circle : Shape {}` is
+ equivalent to `trait Circle where Self : Shape {}`.
+* In trait declarations as bounds on [associated types]:
+ `trait A { type B: Copy; }` is equivalent to
+ `trait A where Self::B: Copy { type B; }`.
+
+Bounds on an item must be satisfied when using the item. When type checking and
+borrow checking a generic item, the bounds can be used to determine that a
+trait is implemented for a type. For example, given `Ty: Trait`
+
+* In the body of a generic function, methods from `Trait` can be called on `Ty`
+ values. Likewise associated constants on the `Trait` can be used.
+* Associated types from `Trait` can be used.
+* Generic functions and types with a `T: Trait` bounds can be used with `Ty`
+ being used for `T`.
+
+```rust
+# type Surface = i32;
+trait Shape {
+ fn draw(&self, Surface);
+ fn name() -> &'static str;
+}
+
+fn draw_twice(surface: Surface, sh: T) {
+ sh.draw(surface); // Can call method because T: Shape
+ sh.draw(surface);
+}
+
+fn copy_and_draw_twice(surface: Surface, sh: T) where T: Shape {
+ let shape_copy = sh; // doesn't move sh because T: Copy
+ draw_twice(surface, sh); // Can use generic function because T: Shape
+}
+
+struct Figure(S, S);
+
+fn name_figure(
+ figure: Figure, // Type Figure is well-formed because U: Shape
+) {
+ println!(
+ "Figure of two {}",
+ U::name(), // Can use associated function
+ );
+}
+```
+
+Trait and lifetime bounds are also used to name [trait objects].
+
+## `?Sized`
+
+`?` is only used to declare that the [`Sized`] trait may not be
+implemented for a type parameter or associated type. `?Sized` may
+not be used as a bound for other types.
+
+## Lifetime bounds
+
+Lifetime bounds can be applied to types or other lifetimes. The bound `'a: 'b`
+is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` lasts longer
+than `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid.
+
+```rust
+fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b {
+ y = x; // &'a i32 is a subtype of &'b i32 because 'a: 'b
+ let r: &'b &'a i32 = &&0; // &'b &'a i32 is well formed because 'a: 'b
+}
+```
+
+`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example if
+`'a` is an unconstrained lifetime parameter then `i32: 'static` and
+`&'static str: 'a` are satisfied but `Vec<&'a ()>: 'static` is not.
+
+## Higher-ranked trait bounds
+
+Type bounds may be *higher ranked* over lifetimes. These bounds specify a bound
+is true *for all* lifetimes. For example, a bound such as `for<'a> &'a T:
+PartialEq` would require an implementation like
+
+```rust,ignore
+impl<'a> PartialEq for &'a T {
+ // ...
+}
+```
+
+and could then be used to compare a `&'a T` with any lifetime to an `i32`.
+
+Only a higher-ranked bound can be used here as the lifetime of the reference is
+shorter than a lifetime parameter on the function:
+
+```rust
+fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) {
+ let zero = 0;
+ f(&zero);
+}
+```
+
+Higher-ranked lifetimes may also be specified just before the trait, the only
+end of the following trait instead of the whole bound. This function is
+difference is the scope of the lifetime parameter, which extends only to the
+equivalent to the last one.
+
+```rust
+fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) {
+ let zero = 0;
+ f(&zero);
+}
+```
+
+> Warning: lifetime bounds are allowed on lifetimes in a `for` binder, but have
+> no effect: `for<'a, 'b: 'a>` is no different to `for<'a, 'b>`.
+
+[LIFETIME_OR_LABEL]: tokens.html#lifetimes-and-loop-labels
+[_TraitPath_]: paths.html
+[`Sized`]: special-types-and-traits.html#sized
+
+[associated types]: items/associated-items.html#associated-types
+[supertraits]: items/traits.html#supertraits
+[generic]: items/generics.html
+[Trait]: traits.html#trait-bounds
+[trait objects]: types.html#trait-objects
+[where clause]: items/where-clauses.html
diff --git a/src/types.md b/src/types.md
index caec02ead..1ecf4a829 100644
--- a/src/types.md
+++ b/src/types.md
@@ -537,12 +537,9 @@ Because captures are often by reference, the following general rules arise:
## Trait objects
-> **Syntax**
-> _TraitObjectType_ :
-> `dyn`? _LifetimeOrPath_ ( `+` _LifetimeOrPath_ )\* `+`?
->
-> _LifetimeOrPath_ :
-> [_Path_] | `(` [_Path_] `)` | [_LIFETIME_OR_LABEL_]
+> **Syntax**
+> _TraitObjectType_ :
+> `dyn`? _TypeParamBounds_
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