Expand description

Type Coercion

Under certain circumstances we will coerce from one type to another, for example by auto-borrowing. This occurs in situations where the compiler has a firm ‘expected type’ that was supplied from the user, and where the actual type is similar to that expected type in purpose but not in representation (so actual subtyping is inappropriate).

Reborrowing

Note that if we are expecting a reference, we will reborrow even if the argument provided was already a reference. This is useful for freezing mut things (that is, when the expected type is &T but you have &mut T) and also for avoiding the linearity of mut things (when the expected is &mut T and you have &mut T). See the various src/test/ui/coerce/*.rs tests for examples of where this is useful.

Subtle note

When inferring the generic arguments of functions, the argument order is relevant, which can lead to the following edge case:

fn foo<T>(a: T, b: T) {
    // ...
}

foo(&7i32, &mut 7i32);
// This compiles, as we first infer `T` to be `&i32`,
// and then coerce `&mut 7i32` to `&7i32`.

foo(&mut 7i32, &7i32);
// This does not compile, as we first infer `T` to be `&mut i32`
// and are then unable to coerce `&7i32` to `&mut i32`.

Structs

Coerce 🔒
CoerceMany encapsulates the pattern you should use when you have many expressions that are all getting coerced to a common type. This arises, for example, when you have a match (the result of each arm is coerced to a common type). It also arises in less obvious places, such as when you have many break foo expressions that target the same loop, or the various return expressions in a function.

Enums

Traits

Something that can be converted into an expression to which we can apply a coercion.

Functions

Coercing a mutable reference to an immutable works, while coercing &T to &mut T should be forbidden.
identity 🔒
Do not require any adjustments, i.e. coerce x -> x.
simple 🔒
success 🔒
This always returns Ok(...).

Type Definitions

The type of a CoerceMany that is storing up the expressions into a buffer. We use this in check/mod.rs for things like break.