From 48ac001e8d8cf473489ba66e4353d8ae545da30d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 20 May 2016 18:30:41 +0200 Subject: [PATCH 1/5] new RFC: static_lifetime_in_statics --- text/0000-static.md | 70 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 text/0000-static.md diff --git a/text/0000-static.md b/text/0000-static.md new file mode 100644 index 000000000..76e51b751 --- /dev/null +++ b/text/0000-static.md @@ -0,0 +1,70 @@ +- Feature Name: static_lifetime_in_statics +- Start Date: 2016-05-20 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Let's default lifetimes in static and const declarations to `'static`. + +# Motivation +[motivation]: #motivation + +Currently, having references in `static` and `const` declarations is cumbersome +due to having to explicitly write `&'static ..`. On the other hand anything but +static is likely either useless, unsound or both. Also the long lifetime name +causes substantial rightwards drift, which makes it hard to format the code +to be visually appealing. + +For example, having a `'static` default for lifetimes would turn this: +``` +static my_awesome_tables: &'static [&'static HashMap, u32>] = .. +``` +into this: +``` +static my_awesome_table: &[&HashMap, u32>] = .. +``` + +The type declaration still causes some rightwards drift, but at least all the +contained information is useful. + +# Detailed design +[design]: #detailed-design + +The same default that RFC #599 sets up for trait object is to be used for +statics and const declarations. In those declarations, the compiler will assume +`'static` when a lifetime is not explicitly given in both refs and generics. + +Note that this RFC does not forbid writing the lifetimes, it only sets a +default when no is given. Thus the change is unlikely to cause any breakage and +should be deemed backwards-compatible. It's also very unlikely that +implementing this RFC will restrict our design space for `static` and `const` +definitions down the road. + +# Drawbacks +[drawbacks]: #drawbacks + +There are no known drawbacks to this change. + +# Alternatives +[alternatives]: #alternatives + +* Leave everything as it is. Everyone using static references is annoyed by +having to add `'static` without any value to readability. People will resort to +writing macros if they have many resources. +* Write the aforementioned macro. This is inferior in terms of UX. Depending on +the implementation it may or may not be possible to default lifetimes in +generics. +* Infer types for statics. The absence of types makes it harder to reason about +the code, so even if type inference for statics was to be implemented, +defaulting lifetimes would have the benefit of pulling the cost-benefit +relation in the direction of more explicit code. Thus it is advisable to +implement this change even with the possibility of implementing type inference +later. + +# Unresolved questions +[unresolved]: #unresolved-questions + +* Does this change requires changing the grammar? +* Are there other Rust-code handling programs that need to be updated? From 2c875d74ef8d993ff3a26c4c9215a8db49f3d4a0 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 20 May 2016 19:11:06 +0200 Subject: [PATCH 2/5] include @nikomatsakis' examples, clarify lifetime elision precedence --- text/0000-static.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/text/0000-static.md b/text/0000-static.md index 76e51b751..1bfd6f507 100644 --- a/text/0000-static.md +++ b/text/0000-static.md @@ -27,7 +27,8 @@ static my_awesome_table: &[&HashMap, u32>] = .. ``` The type declaration still causes some rightwards drift, but at least all the -contained information is useful. +contained information is useful. There is one exception to the rule: lifetime +elision for function signatures will work as it does now (see example below). # Detailed design [design]: #detailed-design @@ -42,6 +43,24 @@ should be deemed backwards-compatible. It's also very unlikely that implementing this RFC will restrict our design space for `static` and `const` definitions down the road. +The `'static` default does *not* override lifetime elision in function +signatures, but work alongside it: + +```rust +static foo: fn(&u32) -> &u32 = ...; // for<'a> fn(&'a u32) -> &'a u32 +static bar: &Fn(&u32) -> &u32 = ...; // &'static for<'a> Fn(&'a u32) -> &'a u32 +``` + +With generics, it will work as anywhere else. Notably, writing out the lifetime +is still possible. + +``` +trait SomeObject<'a> { ... } +static foo: &SomeObject = ...; // &'static SomeObject<'static> +static bar: &for<'a> SomeObject<'a> = ...; // &'static for<'a> SomeObject<'a> +static baz: &'static [u8] = ...; +``` + # Drawbacks [drawbacks]: #drawbacks From 315101a0c21b715c9ad019faf483fb5d2399173c Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 20 May 2016 19:12:33 +0200 Subject: [PATCH 3/5] drop confusing sentence in motivation --- text/0000-static.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/text/0000-static.md b/text/0000-static.md index 1bfd6f507..902dc4fd3 100644 --- a/text/0000-static.md +++ b/text/0000-static.md @@ -12,8 +12,7 @@ Let's default lifetimes in static and const declarations to `'static`. [motivation]: #motivation Currently, having references in `static` and `const` declarations is cumbersome -due to having to explicitly write `&'static ..`. On the other hand anything but -static is likely either useless, unsound or both. Also the long lifetime name +due to having to explicitly write `&'static ..`. Also the long lifetime name causes substantial rightwards drift, which makes it hard to format the code to be visually appealing. From 93b685e9e4b029ac7a24d52d6d1be24581a99020 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 20 May 2016 19:14:58 +0200 Subject: [PATCH 4/5] clarify zero breakage, remove answered question --- text/0000-static.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/0000-static.md b/text/0000-static.md index 902dc4fd3..7b5c82df0 100644 --- a/text/0000-static.md +++ b/text/0000-static.md @@ -37,10 +37,10 @@ statics and const declarations. In those declarations, the compiler will assume `'static` when a lifetime is not explicitly given in both refs and generics. Note that this RFC does not forbid writing the lifetimes, it only sets a -default when no is given. Thus the change is unlikely to cause any breakage and -should be deemed backwards-compatible. It's also very unlikely that -implementing this RFC will restrict our design space for `static` and `const` -definitions down the road. +default when no is given. Thus the change will not cause any breakage and is +thus backwards-compatible. It's also very unlikely that implementing this RFC +will restrict our design space for `static` and `const` definitions down the +road. The `'static` default does *not* override lifetime elision in function signatures, but work alongside it: @@ -84,5 +84,5 @@ later. # Unresolved questions [unresolved]: #unresolved-questions -* Does this change requires changing the grammar? -* Are there other Rust-code handling programs that need to be updated? +* Are there third party Rust-code handling programs that need to be updated to +deal with this change? From 2526483e8fff9d3cca3d092f7d5b49a46c67c9e3 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Tue, 24 May 2016 18:45:41 +0200 Subject: [PATCH 5/5] clarify interaction with elisions --- text/0000-static.md | 48 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/text/0000-static.md b/text/0000-static.md index 7b5c82df0..1ac65277a 100644 --- a/text/0000-static.md +++ b/text/0000-static.md @@ -17,11 +17,11 @@ causes substantial rightwards drift, which makes it hard to format the code to be visually appealing. For example, having a `'static` default for lifetimes would turn this: -``` +```rust static my_awesome_tables: &'static [&'static HashMap, u32>] = .. ``` into this: -``` +```rust static my_awesome_table: &[&HashMap, u32>] = .. ``` @@ -34,13 +34,14 @@ elision for function signatures will work as it does now (see example below). The same default that RFC #599 sets up for trait object is to be used for statics and const declarations. In those declarations, the compiler will assume -`'static` when a lifetime is not explicitly given in both refs and generics. +`'static` when a lifetime is not explicitly given in all reference lifetimes, +including reference lifetimes obtained via generic substitution. Note that this RFC does not forbid writing the lifetimes, it only sets a default when no is given. Thus the change will not cause any breakage and is -thus backwards-compatible. It's also very unlikely that implementing this RFC -will restrict our design space for `static` and `const` definitions down the -road. +therefore backwards-compatible. It's also very unlikely that implementing this +RFC will restrict our design space for `static` and `const` definitions down +the road. The `'static` default does *not* override lifetime elision in function signatures, but work alongside it: @@ -50,16 +51,40 @@ static foo: fn(&u32) -> &u32 = ...; // for<'a> fn(&'a u32) -> &'a u32 static bar: &Fn(&u32) -> &u32 = ...; // &'static for<'a> Fn(&'a u32) -> &'a u32 ``` -With generics, it will work as anywhere else. Notably, writing out the lifetime +With generics, it will work as anywhere else, also differentiating between +function lifetimes and reference lifetimes. Notably, writing out the lifetime is still possible. -``` -trait SomeObject<'a> { ... } +```rust +trait SomeObject<'a> { .. } static foo: &SomeObject = ...; // &'static SomeObject<'static> static bar: &for<'a> SomeObject<'a> = ...; // &'static for<'a> SomeObject<'a> static baz: &'static [u8] = ...; + +struct SomeStruct<'a, 'b> { + foo: &'a Foo, + bar: &'a Bar, + f: for<'b> Fn(&'b Foo) -> &'b Bar +} + +static blub: &SomeStruct = ...; // &'static SomeStruct<'static, 'b> for any 'b ``` +It will still be an error to omit lifetimes in function types *not* eligible +for elision, e.g. + +```rust +static blobb: FnMut(&Foo, &Bar) -> &Baz = ...; //~ ERROR: missing lifetimes for + //^ &Foo, &Bar, &Baz +``` + +This ensures that the really hairy cases that need the full type documented +aren't unduly abbreviated. + +It should also be noted that since statics and constants have no `self` type, +elision will only work with distinct input lifetimes or one input+output +lifetime. + # Drawbacks [drawbacks]: #drawbacks @@ -74,6 +99,11 @@ writing macros if they have many resources. * Write the aforementioned macro. This is inferior in terms of UX. Depending on the implementation it may or may not be possible to default lifetimes in generics. +* Make all non-elided lifetimes `'static`. This has the drawback of creating +hard-to-spot errors (that would also probably occur in the wrong place) and +confusing users. +* Make all non-declared lifetimes `'static`. This would not be backwards +compatible due to interference with lifetime elision. * Infer types for statics. The absence of types makes it harder to reason about the code, so even if type inference for statics was to be implemented, defaulting lifetimes would have the benefit of pulling the cost-benefit