-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
'fn lifetime ascription #1847
'fn lifetime ascription #1847
Conversation
In llogiq#1 added and unresolved question for |
|
'fn is an implicitly bound lifetime that is equivalent, borrow checker wise, to the following code in today's Rust: fn foo<'fn>() {
...
} No changes from the behavior of the code above with respect to borrow checker are needed.
Destroyed before the function returns, just as if the respective
Not without #1808. |
Add unresolved question of `break 'fn ..`
Also a nit on terminology. With type ascription, we constrain the type of an expression with an annotation, but here we are binding new lifetime identifier. I'd think that actual lifetime ascription would be using an explicit (already bound) lifetime with the |
@Ericson2314 Having function-local bindings (in this case lifetimes) apply to nested items would be a significant change, albeit one that I'd like to see. @whitequark Yes, but how is that implemented? Shall there be an implicit linked list of allocaed values to call destructors on? ...Actually, scratch that; this doesn't even make sense for values with destructors because there's no way to translate the strictly-outlives rule. I don't see how you'd prevent a situation where two structs with Drop impls have 'fn references pointing to each other. |
@comex excellent points. I might argue however that the latter is a prexisting problem we just duck by not allowing the user to ask for specific lifetimes. |
Also fix type error with missing & operator
This helps make diffs more readable because there is no longer manual rewrapping every time. I propose this as a general policy in rust-lang#1811, but absent one right now I think its fine to do this already.
Hmm. So currently @whitequark's desugaring doesn't work very well: https://is.gd/7vWrMK. But according my formalization in https://internals.rust-lang.org/t/a-stateful-mir-for-rust/3596 or (if you squint) @nikomatsakis's outlives-at relation (where I got the idea), it's OK to borrow for an already-entered lifetime. This would make that example valid. But this is some thorny stuff to figure out for our type system (actual axioms for lifetimes, not just a magic borrow checking algorithm we trust!), so perhaps it is easier to start with full named lexical lifetimes. |
Why not just move to full lifetime ascription? It seems to me that we could have an RFC for it that says we'll implement some parts before others as opposed to this and presumably an RFC for that in future. I'm kind of assuming that something about this proposal is easy to implement. What about compatibility concerns with |
@Ericson2314 Hrm, can you clarify "OK to borrow for an already-entered lifetime"? Normally of course if you have an |
@camlorn that is the long-term plan, but the |
@llogiq
It's consistent in that it's the same, at least supposing the syntax is |
@camlorn the syntax that labels use (and we don't want to change it) is |
Also, yes, |
@comex so let b = ..;
'a: {
let x: &'a _ = &b;
} is for sure OK, but we want to effectively do 'a: {
let b = ..;
let x: &'a _ = &b;
} where the lifetime of b only properly outlives |
@comex hmm this may still be irredeemable because I think we ought to treat the destruction of |
```rust | ||
struct Node<T> { | ||
data: T, | ||
next: Option<&'fn Node>, |
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.
Uhm, this can't possibly work, you need to make it a parameter of Node
otherwise you end up with C++-level handwavey rules that are (approximately) checked through invasive heuristics.
Either that or the compiler injects the parametricity but that's much harder to do and get right than the existing lifetime system that we already have.
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.
@eddyb are you treating this as a item defined in a function body (concrete 'fn
lifetime), or as some late-bound placeholder? Certainly the latter in untenable, but the former could possibly work.
3 things (one per commit)
(moved from diff comment) @Ericson2314 If we had nested generics (which we don't), the former requires injecting an extra parameter, which is supplied by uses in the surrounding function, which is my second point. That is, |
@eddyb Makes sense. Here fn foo<'a>() {
let x;
{
x = Box::new(1u32);
let a = Box::new(&x);
}
}
fn bar<'a>() {
{
let b = Box::new(&'fn Box::new(1u32));
}
} @llogiq sorry I should have thought more about the motivations for this coming from the alloca RFC. |
@Ericson2314 That looks about right, and if you decide to go with a dynamic per-stack-frame "drop list" (which I believe is what Go has w/ |
With the current semantics of Rust, forcing borrows to some lifetime won't help you - lifetimes don't affect the destruction order of locals. What you do want is to create locals without a corresponding fn foo() {
// here we ascribe the `'fn` lifetime to `next`
let leak start = Node { data: 0, None };
let mut head = &start;
for i in iter {
let leak cur = Node { data: i, Some(head) };
head = &cur;
}
} |
Looking at your alloca versions, the only borrow checker change needed would be to have it ignore borrows on "previous" instantiations of a local when looking at borrows for the current instantiation - and the only reason you care about borrows of "previous" instantiations is for destructors, which I'm not sure we want. Basically the "dropless" version is equivalent to supporting: let mut x0 = 0;
let mut x1 = 1;
let mut x_ = &mut x0;
let z = &mut *x_;
x_ = &mut x1;
use(z); Adding |
@arielb1 I have some doubts the "dropless" version will be accepted, seeing as it's quite non-orthogonal. |
Sorry, @whitequark, but I ran out of steam before completing the lifetime ascription RFC. There are a few interactions we may want to think about (for example ascription should be able to extend, but not restrict the lifetime). |
@arielb1 My intention with EDIT: This is also why I don't use the syntax |
Another suggestion is roughly |
Forbidding types with destructors seems like a smarter choice then leaking, indeed. |
This RFC has gone quiet, without much clear conclusion. @whitequark, what's your current thinking here? How do we make progress on this front? |
@aturon It seems like this is the result of:
I'd like to hear from other @rust-lang/lang team members whether the overall set of parts that ought to eventually fit together seems acceptable. If it is... personally I won't have time to get an RFC through in at least 1-2 months, perhaps @llogiq could take another stab. I am still quite interested in the features and going to participate in the design process, of course. |
@whitequark Thanks much! I propose that we hold a dedicated meeting with various interested stakeholders, and try to hammer out some of these questions at high bandwidth. (Either as a lang team meeting or a separate ad hoc one.) Anyone who would like to be included in such a meeting, please let me know. |
@aturon Sounds good! |
@whitequark @nikomatsakis @eddyb any pointers on the stakeholders to include? I believe this was discussed at the compiler sprint? |
Well, we discussed primarily the "unsized rvalues" RFC (#1909), which is certainly a way to support alloca, though it is somewhat orthogonal from this RFC I believe. I think that what I personally want out of this RFC is not necessarily the same as what @Ericson2314 wanted. I am primarily interested in a better way to teach Rust and to teach lifetimes in particular. To that end, I think that having explicit syntax can be a great way to expose the mechanics. So I'd like to be able to give names to blocks and so forth (e.g., So, I suppose in terms of "stakeholders", I could see two groups. If we're talking about allocas, then I would include @arielb1, who put a lot of effort into #1909, and naturally @eddyb. If we're talking about teaching lifetimes, I might include other people (@wycats, perhaps). |
I'm interested in better ways of teaching lifetimes. |
@nikomatsakis I think our interests are closer than you might imagine :). If nothing else, my desire for move and out pointers leads me to be wary of the sublety of unsized rvalues and friends without them. I think the teaching portions of all of this (and IRC I originally thought this RFC was sidestepping the allocation stuff) are wanted by everyone, so let's factor them out and expedite them. I absolutely agree with @whitequark's division of labor—I'd just rearrange the teaching ones first. I do like breaking out of all blocks, and |
I'm going to propose we postpone this RFC; we don't have bandwidth to convene the full stakeholders ahead of the impl period, and should revisit this area in 2018. @rfcbot fcp postpone |
Team member @aturon has proposed to postpone this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
For the record, I'm fine with this, hopefully I have the energy to revisit it next year. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
1 similar comment
🔔 This is now entering its final comment period, as per the review above. 🔔 |
I'm going to close this RFC as postponed for the time being, as per previous comments; we hope to revisit after various other dust has settled! Thanks @llogiq! |
This is a much reduced version of lifetime ascription that gives us none of the great teachability of full lifetime ascription, but rather extends the power of the lifetime system by allowing to ascribe a
'fn
lifetime.(rendered)