Move the list of coercions to the reference

pull/294/head
Yuki Okushi 3 years ago committed by Alexis Beingessner
parent ff25fa253d
commit c162bb71e9

@ -5,48 +5,9 @@ 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:
For an exhaustive list of all the types of coercions, see the [Coercion types] section on the reference.
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<U>`
* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref<Target=U>`)
* 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<Pointer<U>> for Pointer<T> where T: Unsize<U>` 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<U>`
* `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<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
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 }`
## Cases where coercions do not perform
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
@ -69,18 +30,17 @@ fn main() {
```text
error[E0277]: the trait bound `&mut i32: Trait` is not satisfied
--> src/main.rs:9:5
--> src/main.rs:9:9
|
3 | fn foo<X: Trait>(t: X) {}
| ----- required by this bound in `foo`
...
9 | foo(t);
| ^^^ the trait `Trait` is not implemented for `&mut i32`
| ^ 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<X: Trait>(t: X) {}
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
= note: `Trait` is implemented for `&i32`, but not for `&mut i32`
```
[Coercion types]: ../reference/type-coercions.html#coercion-types

Loading…
Cancel
Save