-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Hierarchic anonymous life-time #2949
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
8c8324d
8a3bb00
3ff7ef8
4558622
bb9b711
5044d33
04a88c3
0260279
233839a
f6caad2
585fb1f
cf4f0c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,136 @@ | ||||||||||||||||||
| - Feature Name: Hierarchic anonymous life-time | ||||||||||||||||||
| - Start Date: 2020-06-24 | ||||||||||||||||||
| - RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) | ||||||||||||||||||
| - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) | ||||||||||||||||||
|
|
||||||||||||||||||
| # Summary | ||||||||||||||||||
|
|
||||||||||||||||||
| New use of anonymous life-time '_ that implicitly added to current structure | ||||||||||||||||||
|
|
||||||||||||||||||
| # Motivation | ||||||||||||||||||
|
|
||||||||||||||||||
| Motivation is to simplify iterative development and improving refactoring of the code | ||||||||||||||||||
|
|
||||||||||||||||||
| Sometimes during refactoring such code: | ||||||||||||||||||
| ```rust | ||||||||||||||||||
| struct CompositeObject { | ||||||||||||||||||
| obj: SomeType, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct BigObject { | ||||||||||||||||||
| composite_obj: CompositeObject, | ||||||||||||||||||
| count: i32, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct Application { | ||||||||||||||||||
| big_obj: BigObject, | ||||||||||||||||||
| } | ||||||||||||||||||
redradist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| developer decides to make obj of SomeType as reference in CompositeObject type: | ||||||||||||||||||
| ```rust | ||||||||||||||||||
| struct CompositeObject<'a> { | ||||||||||||||||||
| obj: &'a SomeType, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct BigObject<'a> { | ||||||||||||||||||
| composite_obj: CompositeObject<'a>, | ||||||||||||||||||
| count: i32, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct Application<'a> { | ||||||||||||||||||
| big_obj: BigObject<'a>, | ||||||||||||||||||
| } | ||||||||||||||||||
redradist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
| ``` | ||||||||||||||||||
| Everywhere in composition hierarchy I need to write 'a ... most of the times it is just boilerplate code ... | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| What if instead of writing manually we will specify reference fields with anonymous life-time: | ||||||||||||||||||
| ```rust | ||||||||||||||||||
| struct CompositeObject { | ||||||||||||||||||
| obj: &'_ SomeType, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct BigObject { | ||||||||||||||||||
| composite_obj: CompositeObject, | ||||||||||||||||||
| count: i32, | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| struct Application { | ||||||||||||||||||
| big_obj: BigObject, | ||||||||||||||||||
| } | ||||||||||||||||||
redradist marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
| ``` | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that you need some notation on each point of use to specify that a lifetime was elided. That is, But even this wouldn't be sufficient: this feature wants to abstract away the number of lifetime parameters too (we could have two fields with elided lifetimes). So maybe Now, you perhaps need some notation in the struct definitions too to specify that there are N elided lifetimes. For symmetry, With those additions, the feature seems less appealing. But without them, it's confusing. |
||||||||||||||||||
|
|
||||||||||||||||||
| Code much simpler and more maintainable than fighting with named life-times in composite hierarchy | ||||||||||||||||||
|
||||||||||||||||||
| Code much simpler and more maintainable than fighting with named life-times in composite hierarchy | |
| Code much simpler and easier to refactor throughout hierarchy of named lifetimes | |
| by being less maintainable and more implicit |
It is not true that it is more maintainable, I would say it is harder to maintain but being easier to refactor, being easy to refactor is one part, being maintainable but being implicit makes it harder to maintain.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the following code is generated, how will a reader knows that
struct BigObject {
composite_obj: CompositeObject,
count: i32,
}have an implicit CompositeObject<'anon> by reading the documentation generated for BigObject?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the following code is generated, how will a reader knows that
struct BigObject { composite_obj: CompositeObject, count: i32, }have an implicit
CompositeObject<'anon>by reading the documentation generated forBigObject?
@pickfire Actually thinking ... what explicit life-time gives you ? You just need to know how to initialize CompositeObject ... all other job should be done by CompositeObject, it is level of abstraction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it has been quite helpful to see explicit lifetimes because then I know that there is a lifetime being tracked inside the structure. In that way, it is a very helpful kind of documentation. One that is also always up-to-date, which is not a common feature of documentation in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it has been quite helpful to see explicit lifetimes because then I know that there is a lifetime being tracked inside the structure. In that way, it is a very helpful kind of documentation. One that is also always up-to-date, which is not a common feature of documentation in general.
@felix91gr You answer a question: "... it is a very helpful kind of documentation ...", it is mix of multiple stuffs in one ... it breakage of lot of pattern like SOLID - Single Responsibility
Lets not mix life-time with good documentation ... from my point you should only know how to initialize CompositeObject that is all
Responsibility of proper handling life-time is responsibility of CompositeObject and developer that written it
Bypassing life-time from "low-level" structures to "high-level" structures (logically) is violation of layers responsibilities
Each abstract layer souls be responsible for its stuff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it breakage of lot of pattern like SOLID - Single Responsibility
Those patterns were created as heuristics for Object-Oriented Programming, not as tips for general design.
In this case, having two responsibilities is good - it puts the information in exactly one place, instead of two. Keeping the documentation of what this lifetime is affecting becomes trivial once you have to keep it written, doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the lifetime needs to be in the docs. It is necessary for the user to know about the lifetime as it massively affects the usage of the struct. You need to design your code in a way that is compatible with the struct's lifetime semantics. Hiding those is incredibly dangerous in that it might mislead the developer into designing code that might not compile at all. Hiding lifetimes has already been deprecated, you are supposed to use at least
'_nowadays, as it clarifies that a lifetime relationship is going on. So the absolute minimum that might make this RFC acceptable would bestruct Foo<'_>.<'_ ...>probably is not working either, as that either just means the same thing as<'_>or it is incredibly fragile.
Take a look at examples above with syntax like this:
struct CompositeObject& {
obj0: &SomeType, # Deduce life-time for this reference
obj1: &SomeType, # Deduce life-time for this reference
}or even just notification that in future structure will use references:
struct CompositeObject& { // No references inside, but may will be in future
obj0: SomeType,
obj1: SomeType,
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe at this point the RFC is basically lifetime elision in type declarations with & instead of '_ (which imo there's no reason to introduce new syntax when we already have '_ for this. And additionally it introduces automatic elision for 'static which is probably a bit more controversial (and should probably be a separate RFC afterwards).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe at this point the RFC is basically lifetime elision in type declarations with
&instead of'_(which imo there's no reason to introduce new syntax when we already have'_for this. And additionally it introduces automatic elision for'staticwhich is probably a bit more controversial (and should probably be a separate RFC afterwards).
There is on big difference '_ works and show only that in structure used only one reference with one life-time, but CompositeObject& shows that in structure used some references without explicitly declared life-time and number of fields could be different: 2, 3 ... whatever
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't, you can use a single lifetime but many references. Having more than one lifetime in a type's definition is only useful for disambiguating them for the user, but you can't do that with & anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't, you can use a single lifetime but many references. Having more than one lifetime in a type's definition is only useful for disambiguating them for the user, but you can't do that with & anyway.
Okay, will it be possible to use '_ life-time without reference inside ?
struct CompositeObject<'_> { // No references inside, but may will be in future
obj0: SomeType,
obj1: SomeType,
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| struct CompositeObject { | |
| obj0: &'_ SomeType, | |
| obj1: &'_ SomeType, | |
| } | |
| struct CompositeObject<'_> { | |
| obj0: &SomeType, | |
| obj1: &SomeType, | |
| } |
Hidden lifetimes are deprecated, you also don't ever want '_ on references, as that's implied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CryZe
Why they deprecated ?
What if the obj0 and obj1 would have different life-times ? How it will work with single anonymous life-time in declaration ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@redradist Why not? Both of them could depend on the same lifetime and life as long as each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@redradist Why not? Both of them could depend on the same lifetime and life as long as each other.
@pickfire But what would be semantic of struct CompositeObject<'_> ? Does '_ mean one life-time or it mean several different life-times ? What if obj0 and obj1 has different life-times ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true even though it is uncommon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several drawbacks mentioned in the corresponding thread on IRLO and the comments on this PR. It would be helpful to list them here to get a better overview.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pythoneer I will add ;)
Uh oh!
There was an error while loading. Please reload this page.