]> git.proxmox.com Git - rustc.git/blame - src/doc/nomicon/coercions.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / doc / nomicon / coercions.md
CommitLineData
c1a9b12d
SL
1% Coercions
2
3Types can implicitly be coerced to change in certain contexts. These changes are
4generally just *weakening* of types, largely focused around pointers and
5lifetimes. They mostly exist to make Rust "just work" in more cases, and are
6largely harmless.
7
8Here's all the kinds of coercion:
9
10Coercion is allowed between the following types:
11
12* Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to
13 `T_3`
14* Pointer Weakening:
15 * `&mut T` to `&T`
16 * `*mut T` to `*const T`
17 * `&T` to `*const T`
18 * `&mut T` to `*mut T`
19* Unsizing: `T` to `U` if `T` implements `CoerceUnsized<U>`
20
21`CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U>` is implemented
22for all pointer types (including smart pointers like Box and Rc). Unsize is
23only implemented automatically, and enables the following transformations:
24
e9174d1e 25* `[T; n]` => `[T]`
c1a9b12d
SL
26* `T` => `Trait` where `T: Trait`
27* `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
28 * `T: Unsize<U>`
29 * `Foo` is a struct
30 * Only the last field of `Foo` has type `T`
31 * `T` is not part of the type of any other fields
32
33Coercions occur at a *coercion site*. Any location that is explicitly typed
34will cause a coercion to its type. If inference is necessary, the coercion will
35not be performed. Exhaustively, the coercion sites for an expression `e` to
36type `U` are:
37
38* let statements, statics, and consts: `let x: U = e`
39* Arguments to functions: `takes_a_U(e)`
40* Any expression that will be returned: `fn foo() -> U { e }`
41* Struct literals: `Foo { some_u: e }`
42* Array literals: `let x: [U; 10] = [e, ..]`
43* Tuple literals: `let x: (U, ..) = (e, ..)`
44* The last expression in a block: `let x: U = { ..; e }`
45
46Note that we do not perform coercions when matching traits (except for
47receivers, see below). If there is an impl for some type `U` and `T` coerces to
48`U`, that does not constitute an implementation for `T`. For example, the
49following will not type check, even though it is OK to coerce `t` to `&T` and
50there is an impl for `&T`:
51
52```rust,ignore
53trait Trait {}
54
55fn foo<X: Trait>(t: X) {}
56
57impl<'a> Trait for &'a i32 {}
58
59
60fn main() {
61 let t: &mut i32 = &mut 0;
62 foo(t);
63}
64```
65
66```text
54a0048b 67<anon>:10:5: 10:8 error: the trait bound `&mut i32 : Trait` is not satisfied [E0277]
c1a9b12d
SL
68<anon>:10 foo(t);
69 ^~~
70```