3 Types can implicitly be coerced to change in certain contexts. These changes are
4 generally just *weakening* of types, largely focused around pointers and
5 lifetimes. They mostly exist to make Rust "just work" in more cases, and are
8 Here's all the kinds of coercion:
10 Coercion is allowed between the following types:
12 * Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to
16 * `*mut T` to `*const T`
18 * `&mut T` to `*mut T`
19 * Unsizing: `T` to `U` if `T` implements `CoerceUnsized<U>`
20 * Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref<Target=U>`)
22 `CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U>` is implemented
23 for all pointer types (including smart pointers like Box and Rc). Unsize is
24 only implemented automatically, and enables the following transformations:
27 * `T` => `Trait` where `T: Trait`
28 * `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
31 * Only the last field of `Foo` has type involving `T`
32 * `T` is not part of the type of any other fields
33 * `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
35 Coercions occur at a *coercion site*. Any location that is explicitly typed
36 will cause a coercion to its type. If inference is necessary, the coercion will
37 not be performed. Exhaustively, the coercion sites for an expression `e` to
40 * let statements, statics, and consts: `let x: U = e`
41 * Arguments to functions: `takes_a_U(e)`
42 * Any expression that will be returned: `fn foo() -> U { e }`
43 * Struct literals: `Foo { some_u: e }`
44 * Array literals: `let x: [U; 10] = [e, ..]`
45 * Tuple literals: `let x: (U, ..) = (e, ..)`
46 * The last expression in a block: `let x: U = { ..; e }`
48 Note that we do not perform coercions when matching traits (except for
49 receivers, see below). If there is an impl for some type `U` and `T` coerces to
50 `U`, that does not constitute an implementation for `T`. For example, the
51 following will not type check, even though it is OK to coerce `t` to `&T` and
52 there is an impl for `&T`:
57 fn foo<X: Trait>(t: X) {}
59 impl<'a> Trait for &'a i32 {}
62 let t: &mut i32 = &mut 0;
68 error[E0277]: the trait bound `&mut i32: Trait` is not satisfied
72 | ^^^ the trait `Trait` is not implemented for `&mut i32`
74 = help: the following implementations were found:
76 note: required by `foo`
79 3 | fn foo<X: Trait>(t: X) {}
80 | ^^^^^^^^^^^^^^^^^^^^^^
82 error: aborting due to previous error