One year later and I just come across this post. I have the following suggestion, not sure whether it is relevant or possible to implement or not: As far as I know, lifetime is used to match different references during assignment operator, so for struct, can we do something like bellow:
Case 1 : The struct only has one lifetime and all references inside the struct share that lifetime
struct Foo<'_> {
x : &i32,
y : &i32,
z : &i32,
}
And this should be equivalent to :
struct Foo<'a> {
x : &'a i32,
y : &'a i32,
z : &'a i32,
}
Some people have suggested something similar with this approach. The drawback is that all references inside the struct will be forced to have a same lifetime and that reduces the flexibility of all other data structs that shares some references with the above struct. This , however, covers quite a number of use cases, especially the simple cases.
Case 2 : Each reference in the struct has its own lifetime. In this case, the current explicit declaration of lifetime in struct can cause a viral effect, as we already know :
struct Foo<'a, 'b, 'c> {
x : &'a i32,
y : &'b i32,
z : &'c i32,
}
struct Bar<'a:'d, 'b:'d, 'c:'d, 'd> {
foo : &'d Foo<'a, 'b, 'c>
}
fn get_x<'a,'b,'c,'d>(bar : &Bar<'a, 'b, 'c, 'd>) -> &'a i32 {
bar.foo.x
}
With the (unstable) #![feature(underscore_lifetimes)]
, we can make it a bit more simple:
fn get_x<'a>(bar : &Bar<'a, '_, '_, '_>) -> &'a i32 {
bar.foo.x
}
This syntax is somehow similar to the following procedure style :
fn get_x<'a, 'b, 'c>(x : &'a i32, y : &'b i32, z : &'c i32) -> &'a i32 {
x
}
We know that the compiler needs lifetime declaration to check the correctness of reference assignment. In the above case, only lifetime 'a
is necessary to match the input and output lifetime of the function, and 'b
& &c
are redundant. Of coure, with procedure style, we can use lifetime elision:
fn get_x<'a>(x : &'a i32, y : &i32, z : &i32) -> &'a i32 {
x
}
Why shouldn't we try something similar to struct :
struct Foo {
x : & i32,
y : & i32,
z : & i32,
}
struct Bar {
foo : &Foo
}
fn get_x(bar : &Bar) -> &'a i32 where bar.foo.x : &'a {
bar.foo.x
}
, as the compiler only needs to match the lifetime of the element bar.foo.x
with the output result. Currently, the declaration bar : &Bar<'a, 'b, 'c, 'd>
or bar : &Bar<'a, '_, '_, '_>
makes it hard to deduce which element inside the struct does the lifetime annotation ('a
in this case) corresponds to.