diff --git a/src/trait-bounds.md b/src/trait-bounds.md index 0a6731288..a7cd5a7d9 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -156,6 +156,79 @@ fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { } ``` +## Implied bounds + +Lifetime bounds required for types to be well-formed are sometimes inferred. + +```rust +fn requires_t_outlives_a<'a, T>(x: &'a T) {} +``` +The type parameter `T` is required to outlive `'a` for the type `&'a T` to be well-formed. +This is inferred because the function signature contains the type `&'a T` which is +only valid if `T: 'a` holds. + +Implied bounds are added for all parameters and outputs of functions. Inside of `requires_t_outlives_a` +you can assume `T: 'a` to hold even if you don't explicitly specify this: + +```rust +fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} + +fn requires_t_outlives_a<'a, T>(x: &'a T) { + // This compiles, because `T: 'a` is implied by + // the reference type `&'a T`. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +```rust,compile_fail,E0309 +# fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} +fn not_implied<'a, T>() { + // This errors, because `T: 'a` is not implied by + // the function signature. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +Only lifetime bounds are implied, trait bounds still have to be explicitly added. +The following example therefore causes an error: + +```rust,compile_fail,E0277 +use std::fmt::Debug; +struct IsDebug(T); +// error[E0277]: `T` doesn't implement `Debug` +fn doesnt_specify_t_debug(x: IsDebug) {} +``` + +Lifetime bounds are also inferred for type definitions and impl blocks for any type: + +```rust +struct Struct<'a, T> { + // This requires `T: 'a` to be well-formed + // which is inferred by the compiler. + field: &'a T, +} + +enum Enum<'a, T> { + // This requires `T: 'a` to be well-formed, + // which is inferred by the compiler. + // + // Note that `T: 'a` is required even when only + // using `Enum::OtherVariant`. + SomeVariant(&'a T), + OtherVariant, +} + +trait Trait<'a, T: 'a> {} + +// This would error because `T: 'a` is not implied by any type +// in the impl header. +// impl<'a, T> Trait<'a, T> for () {} + +// This compiles as `T: 'a` is implied by the self type `&'a T`. +impl<'a, T> Trait<'a, T> for &'a T {} +``` + + [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels [_GenericParams_]: items/generics.md [_TypePath_]: paths.md#paths-in-types