From my own understanding and experimentation this appears to be true, but I have yet to find an authoritative source that documents it. Rust by Example has a bounds section where it says:
T: 'a
: All references inT
must outlive lifetime'a
.#[derive(Debug)] struct Ref<'a, T: 'a>(&'a T); // `Ref` contains a reference to a generic type `T` that has // an unknown lifetime `'a`. `T` is bounded such that any // *references* in `T` must outlive `'a`. Additionally, the lifetime // of `Ref` may not exceed `'a`.
However, this looks like a poor demonstration since the T: 'a
bound does not seem to affect the behavior of Ref
. Any attempt I've made to construct a T
that is shorter than 'a
is thwarted with or without T: 'a
. Even more, a generic reference defined without the lifetime bound can be passed off as one with it:
fn f<'a, T>(r: &'a T) {
g(r) // this compiles
}
fn g<'a, T: 'a>(r: &'a T) {
// ...
}
The Rust Reference has a similar construction from some examples in the generic parameters section (struct Ref<'a, T> where T: 'a { r: &'a T }
), however it does not elaborate. I have looked through the documentation there, those on references, and on lifetimes and cannot find a link.
So does &'a T
imply T: 'a
? If so, where is this documented? And why do these resources have this unnecessary constraint? If not, what are the rules?
Yes, &'a T
does imply T: 'a
.
There was always the requirement that referent had to outlive the referenced lifetime since it is necessary for safety by-construction. However, before Rust 1.31 the bound was not inferred and would have to be provided explicitly as shown in these questions.
It was RFC #2093: infer outlives that let the compiler to infer these bounds and thus allowed the user to elide them. Since then, the Rust by Example and Rust Reference snippets are over-specified and the T: 'a
is no longer needed.
See elsewhere in the Reference on trait and lifetime bounds:
Lifetime bounds required for types to be well-formed are sometimes inferred.
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 ifT: 'a
holds.
There is at least one place where &'a T
does not automatically infer T: 'a
and that is when defining associated types for a trait (demo on the playground) but the compiler will guide you into adding it explicitly:
trait MakeRef<'a> {
type Type;
}
impl<'a, T> MakeRef<'a> for Vec<T> {
type Type = &'a T;
}
error[E0309]: the parameter type `T` may not live long enough
--> src/lib.rs:6:17
|
6 | type Type = &'a T;
| ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
5 | impl<'a, T: 'a> MakeRef<'a> for Vec<T> {
| ++++