# Coercions Types can implicitly be coerced to change in certain contexts. These changes are generally just *weakening* of types, largely focused around pointers and lifetimes. They mostly exist to make Rust "just work" in more cases, and are largely harmless. Here's all the kinds of coercion: Coercion is allowed between the following types: * Transitivity: `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` * Pointer Weakening: * `&mut T` to `&T` * `*mut T` to `*const T` * `&T` to `*const T` * `&mut T` to `*mut T` * Unsizing: `T` to `U` if `T` implements `CoerceUnsized` * Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref`) * Non-capturing closure to a function pointer ([RFC 1558], e.g. `|| 8usize` to `fn() -> usize`) [RFC 1558]: https://rust-lang.github.io/rfcs/1558-closure-to-fn-coercion.html `CoerceUnsized> for Pointer where T: Unsize` is implemented for all pointer types (including smart pointers like Box and Rc). Unsize is only implemented automatically, and enables the following transformations: * `[T; n]` => `[T]` * `T` => `dyn Trait` where `T: Trait` * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: * `T: Unsize` * `Foo` is a struct * Only the last field of `Foo` has type involving `T` * `T` is not part of the type of any other fields * `Bar: Unsize>`, if the last field of `Foo` has type `Bar` Coercions occur at a *coercion site*. Any location that is explicitly typed will cause a coercion to its type. If inference is necessary, the coercion will not be performed. Exhaustively, the coercion sites for an expression `e` to type `U` are: * let statements, statics, and consts: `let x: U = e` * Arguments to functions: `takes_a_U(e)` * Any expression that will be returned: `fn foo() -> U { e }` * Struct literals: `Foo { some_u: e }` * Array literals: `let x: [U; 10] = [e, ..]` * Tuple literals: `let x: (U, ..) = (e, ..)` * The last expression in a block: `let x: U = { ..; e }` Note that we do not perform coercions when matching traits (except for receivers, see below). If there is an impl for some type `U` and `T` coerces to `U`, that does not constitute an implementation for `T`. For example, the following will not type check, even though it is OK to coerce `t` to `&T` and there is an impl for `&T`: ```rust,compile_fail trait Trait {} fn foo(t: X) {} impl<'a> Trait for &'a i32 {} fn main() { let t: &mut i32 = &mut 0; foo(t); } ``` ```text error[E0277]: the trait bound `&mut i32: Trait` is not satisfied --> src/main.rs:9:5 | 9 | foo(t); | ^^^ the trait `Trait` is not implemented for `&mut i32` | = help: the following implementations were found: <&'a i32 as Trait> note: required by `foo` --> src/main.rs:3:1 | 3 | fn foo(t: X) {} | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error ```