Depending on how you interpret the meaning of “lifetime”, neither might be correct. Besides the lifetime as denoted by
'i, there’s the time the original
i32 lives/exists, and there’s also the time the returned reference exists. The lifetime denoted by
'i can be
- shorter than the time the original
- longer than the time the reference actually happens to exist.
The point of the lifetime argument
'i of a reference however is that it always must
- be longer than (or equal to) the time the reference actually exists
- be shorter than (or equal to) the time the target
i32 variable exists
- and in fact also throughout the time indicated by
'i, the target
i32 must not be mutably accessed.
So to relate as much as possible to your question’s wording, arguable, it is the case that
'i denotes an upper bound to the lifetime of the reference (the caller cannot keep the returned reference alive for longer than
- the function returns a reference to an
i32 value whose lifetime is at least
'i (so that if the caller does keep the reference alive for up to
'i, it’s safe to use and pointing to a valid target all the time).
The reason why it’s not indicating exactly either of the actual run-time “life-times” of the target or the reference is that borrow-checking is a static (i.e. compile-time) thing, and thus lifetimes denoted by lifetime parameters must be a particular “region of code” determined at compile time; while the time of actual “life” of a value or reference is something that ultimately only gets decided at run-time, and might depend on input, if there’s e.g.
match expressions acting on the value or reference conditionally.
Some more concrete examples of how
'i can differ from either as described above:
For references existing shorter than their lifetime: you often have
&'static str value in Rust from string literals, and while the underlying target string data lives for the
'static duration, i.e. for the whole duration of the program, the
&'static str references themself very often live a lot shorter.
On values existing longer than a reference’s lifetimes pointing to them: Reference lifetimes can be shortened through coercion. A
&'long T reference can be converted into a
&'short T reference. But of course, even after this conversion, the underlying value will still exist for at least the
'long lifetime; just the new
&'short T reference does not reveal this fact to its users anymore.
And, as I mentioned before, functions like
foo that require two references with the same lifetime parameter can be called with references that originally had different lifetime parameters, by coercing one (or both) arguments to a common sub-lifetime, i.e. a lifetime parameter shorter (or equal) than both original ones. The actual targets of the longer-lived original references, which might become targets of the return value of
foo, too, would of course still be actually alife for (at least) as long as their original lifetime arguments indicated. Or
foo might just as well return a reference into static memory, something that was originally a
&'static i32; and with Rust’s language features (implicit constant promotion) doing so is actually quite straightforward, and as simple as writing something like “