Inference
Inference occurs when the compiler can deduce certain semantic info without it being explicitly specified in the source code. Inference applies to types, impls and generic arguments.
Places where inference is enabled:
-
Type inference on
let
missing statement type clauses. -
Impl inference on method calls.
-
Impl inference when calling by trait.
-
Generic argument inference.
Examples:
let x = 1_u8; // x is inferred to be u8
let y = Option<_>::Some(x); // _ is inferred as u8, and y is inferred as Option<u8>
let u: u32 = Into::<u8, u32>::into(x); // concrete impl for Into<u8, u32> is inferred
let u: u32 = x.into(); // The generic arguments for Into<?,?> and the concrete impl
// are inferred
Complex impl example
trait Display<T> {
fn display(x: T) -> Array<u8>;
}
impl IntoArrayU8Display<T, impl TIntoArrayU8: Into<T, Array<u8>>> of Display<T> {
fn display(x: T) -> Array<u8> {
x.into() // Inferred as TIntoArrayU8::into(x)
}
}
impl U32IntoArrayU8 of Into<u32, Array<u8>> {
fn into(x: u32) -> Array<u8> {
// ...
}
}
fn main() {
let x = 1_u32;
let y = Display::display(x); // Inferred as IntoArrayU8Display<u32, U32IntoArrayU8>::display(x)
}
Search locations for impl
When inferring an impl of a trait, the compiler will search for the impl in the following locations:
* Defined generic parameters in the current scope.
* The current module.
* The core module.
* Defining module of the trait.
* Defining module of each of the generic arguments of the trait. For example, the impl for
Display<usize>
will be searched for in the module where usize
is defined.