One: If you have an unconstrained generic lifetime on your function like this, the caller chooses the lifetime, so it could be anything -- including 'static
("forever"). So when you're testing upper boundaries like this, you might as well test with 'static
. Rewriting your example:
struct U;
fn test() {
let x = U;
let y: &'static _ = &x;
}
Two: If you have a variable with a certain scope of existence -- let's say, it doesn't get returned from the current function -- you can still put references with longer lifetimes into that variable, so long as they are valid:
// Compiles
fn test() {
let y: &'static str = "";
}
That is, a variable doesn't have to exist as long as the references you put in it.
Three: Shortening the lifetime/existence of y
is not going to help you. It's already shorter than the reference and making y
shorter -- or longer! -- is not going to change the lifetime of the borrow in this scenario. Once you say the borrow must be 'static
or some caller-chosen 'a
, there is no changing the length of the borrow.
And that's the problem with the example: the thing you cannot do is take a reference for longer than the variable behind the reference exists. That's what you're running into -- x
doesn't live long enough; x
is not 'static
; 'a
can be longer than x
exists for.
You need to shorten the length of the borrow (reference) stored inside y
, or lengthen the lifetime of the variable being borrowed (x
).
y
doesn't really have anything to do with it.
// We already saw making `y` shorter doesn't help.
// No `y` and this function "lives forever", but this is still an error too
fn borrow_statically(_: &'static U) {}
fn test() {
let x = U;
borrow_statically(&x);
}
// This one is fine; `X` lives long enough
fn test() {
static X: U = U;
borrow_statically(&X);
}
// So is this
fn test<'a>() {
static X: U = U;
let y: &'a _ = &X;
}
// So is this (the borrow is short enough / not forced to be long)
fn test() {
let x = U;
let y = &x;
}