- Feature Name: Lifetime elision 1.1
- Start Date: 2017-03-04
- RFC PR:
- Rust Issue:
Summary
Let the user have the option to elide the lifetime in a reference field in a struct, if that struct has exactly one reference field in it.
Motivation
As of today, specifying lifetimes for structs with one reference parameter is useless. Consider the following example -
struct Foo {
a: String
}
impl Foo {
fn new(a: String) -> Foo {
Foo {a: a}
}
}
struct Bar {
foo: Foo
}
Imagine now that we realized that the a field in Foo didnât need to be owned, so we should use a 'str
.
That would mean that the code now would look like this:
struct Foo<'a> {
a: &'a str
}
impl<'a> Foo<'a> {
fn new(a: &str) -> Foo {
Foo {a: a}
}
}
struct Bar<'a> {
foo: Foo<'a>
}
Just for this simple change, Foo needed 4 lifetime annotations.
Moreso, any struct that uses Foo is now âpoisonedâ and also need to have a lifetime parameter now.
Now, of course this change would make sense if those annotations supplied us with important information - like if there were multiple fields and we would have to know the relations of their lifetimes.
But when it comes to the case of one reference field, there are two options -
- Use a special lifetime, like 'static - which is the special, non-common case
- Use a generic lifetime parameter - which is the common case.
The problem is, that since there is only one lifetime parameter, the only thing that the annotation says is âthis reference has a lifetimeâ, and without any other lifetimes to use it with, this is useless information.
If we look at this change using the parameters in ergonomic initiative blogpost:
- Applicability - structs that contain references are incredibly common in rust because of the strong ownership gurantees.
- Power - since in the simple cases there is only one way to fill it anyways, it doesnât change anything.
- Context-dependence - The lifetime annotations donât add information and clutter the code. Removing them would make the code cleaner and wonât remove information.
Detailed design
Comparison with Lifetime Elisions 2.0
This RFC is a subset of the RFC Lifetime Elisions 2.0
While that RFC proposes many changes that change the language and syntax, this rfc only aims to get in the simplest and commonly needed change, to âopen the doorâ for struct elision changes.
The rule
This RFC proposes one rule in addition to the existing lifetime elision rules -
If a struct contains exactly one parameter that is a reference, the lifetime to this reference may be elided, and the compiler should consider this reference an unnamed generic lifetime.
Since the struct is no longer needed within the struct, it could also be dropped in the impl blocks, and in containing structs.
Otherwise, this elision rule behaves the same as all other currently implemented elision rules.
Examples:
//expanded
struct Foo<'a> {
a: &'a str
}
impl<'a> Foo<'a> {
fn new(a: &str) -> Foo {
Foo {a: a}
}
}
struct Bar<'a> {
foo: Foo<'a>
}
//elided
struct Foo {
a: &str
}
impl Foo {
fn new(a: &str) -> Foo {
Foo {a: a}
}
}
struct Bar {
foo: Foo
}
(NOTE: Iâm not sure if Bar in this:
struct Foo<'a> {
a: &'a str
}
impl<'a> Foo<'a> {
fn new(a: &str) -> Foo {
Foo {a: a}
}
}
struct Bar<'a,'b> {
foo: Foo<'a>,
baz : &'b str
}
Can be safetly elided to this:
struct Bar {
foo: Foo,
baz : &str
}
Or should it be this:
struct Bar<'a> {
foo: Foo,
baz : &'a str
//or this
struct Bar<'a> {
foo: Foo<'a>,
baz : & str
}
It looks to me that the first example is fine, but I hope someone with more knowledge than me could clarify. )
How We Teach This
The same way we teach lifetime elision for functions - start explaining what structs are and what references in struct mean, and only introduce lifetimes when they are needed for the more complex cases.
None that this RFC answers one of the common questions begginers have, coming from languages with no lifetimes - âWhy do I have to annotate the lifetime if there is only one way I can do it?â.
Drawbacks
Adds implicitness to the language - some people may prefer that any reference that is stored in a struct will always be explicitly lifetimed.
Alternatives
- Lifetime Elisions 2.0 - Contains a lot more useful changes, and maybe we should wait to have all of them in thougether.
- Not changing the way lifetimes work today
Unresolved questions
Can lifetimes be elided in more complex struct examples?