]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/type-coercions.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / reference / src / type-coercions.md
1 # Type coercions
2
3 Coercions are defined in [RFC 401]. [RFC 1558] then expanded on that.
4 A coercion is implicit and has no syntax.
5
6 [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
7 [RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md
8
9 ## Coercion sites
10
11 A coercion can only occur at certain coercion sites in a program; these are
12 typically places where the desired type is explicit or can be derived by
13 propagation from explicit types (without type inference). Possible coercion
14 sites are:
15
16 * `let` statements where an explicit type is given.
17
18 For example, `42` is coerced to have type `i8` in the following:
19
20 ```rust
21 let _: i8 = 42;
22 ```
23
24 * `static` and `const` statements (similar to `let` statements).
25
26 * Arguments for function calls
27
28 The value being coerced is the actual parameter, and it is coerced to
29 the type of the formal parameter.
30
31 For example, `42` is coerced to have type `i8` in the following:
32
33 ```rust
34 fn bar(_: i8) { }
35
36 fn main() {
37 bar(42);
38 }
39 ```
40
41 * Instantiations of struct or variant fields
42
43 For example, `42` is coerced to have type `i8` in the following:
44
45 ```rust
46 struct Foo { x: i8 }
47
48 fn main() {
49 Foo { x: 42 };
50 }
51 ```
52
53 * Function results, either the final line of a block if it is not
54 semicolon-terminated or any expression in a `return` statement
55
56 For example, `42` is coerced to have type `i8` in the following:
57
58 ```rust
59 fn foo() -> i8 {
60 42
61 }
62 ```
63
64 If the expression in one of these coercion sites is a coercion-propagating
65 expression, then the relevant sub-expressions in that expression are also
66 coercion sites. Propagation recurses from these new coercion sites.
67 Propagating expressions and their relevant sub-expressions are:
68
69 * Array literals, where the array has type `[U; n]`. Each sub-expression in
70 the array literal is a coercion site for coercion to type `U`.
71
72 * Array literals with repeating syntax, where the array has type `[U; n]`. The
73 repeated sub-expression is a coercion site for coercion to type `U`.
74
75 * Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
76 Each sub-expression is a coercion site to the respective type, e.g. the
77 zeroth sub-expression is a coercion site to type `U_0`.
78
79 * Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then
80 the sub-expression is a coercion site to `U`.
81
82 * Blocks: if a block has type `U`, then the last expression in the block (if
83 it is not semicolon-terminated) is a coercion site to `U`. This includes
84 blocks which are part of control flow statements, such as `if`/`else`, if
85 the block has a known type.
86
87 ## Coercion types
88
89 Coercion is allowed between the following types:
90
91 * `T` to `U` if `T` is a subtype of `U` (*reflexive case*)
92
93 * `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
94 (*transitive case*)
95
96 Note that this is not fully supported yet
97
98 * `&mut T` to `&T`
99
100 * `*mut T` to `*const T`
101
102 * `&T` to `*const T`
103
104 * `&mut T` to `*mut T`
105
106 * `&T` to `&U` if `T` implements `Deref<Target = U>`. For example:
107
108 ```rust
109 use std::ops::Deref;
110
111 struct CharContainer {
112 value: char,
113 }
114
115 impl Deref for CharContainer {
116 type Target = char;
117
118 fn deref<'a>(&'a self) -> &'a char {
119 &self.value
120 }
121 }
122
123 fn foo(arg: &char) {}
124
125 fn main() {
126 let x = &mut CharContainer { value: 'y' };
127 foo(x); //&mut CharContainer is coerced to &char.
128 }
129 ```
130
131 * `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`.
132
133 * TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of
134 - `&T`
135 - `&mut T`
136 - `*const T`
137 - `*mut T`
138 - `Box<T>`
139
140 and where
141 - coerce_inner(`[T, ..n]`) = `[T]`
142 - coerce_inner(`T`) = `U` where `T` is a concrete type which implements the
143 trait `U`.
144
145 <!--In the future, coerce_inner will be recursively extended to tuples and
146 structs. In addition, coercions from sub-traits to super-traits will be
147 added. See [RFC 401] for more details.-->
148
149 * Non capturing closures to `fn` pointers