In Rust, generic parameters can be either early bound or late bound. This distinction affects how and when the compiler determines the parameter's value.
Early Bound Parameters
Early bound parameters are determined by the compiler during monomorphization. Type parameters are always early bound. Because they must be resolved at the time of monomorphization, you cannot have a value whose type has an unresolved type parameter.
fn m<T>() {}
fn main() {
let m1 = m::<u8>; // ok
let m2 = m; // error: cannot infer type for `T`
}
Late Bound Parameters
Lifetime parameters are often late bound, meaning the actual choice of lifetime depends on how the function is called at the call site. Because the lifetime can be different for each call, you cannot specify the lifetime explicitly on the function itself before it is called.
// error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
let m2 = m::<'static>;
// error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
let m3 = m::<'_>;
Higher Ranked Trait Bounds (HRTB)
// error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
let m2 = m::<'static>;
// error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
let m3 = m::<'_];