-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Better temporary lifetimes (tracking issue for RFC 66) #15023
Comments
This comment has been minimized.
This comment has been minimized.
I've got an example which seems related. Apparently as of 470dbef a |
This comment has been minimized.
This comment has been minimized.
Is there any reason we can't just rewrite: foo().bar().baz(&bip().bop().boop()) as: let mut tmp = foo();
let mut tmp = foo.bar();
{
let mut tmp2 = bip();
let mut tmp2 = tmp2.bop();
let mut tmp2 = tmp2.boop();
let mut tmp2 = &tmp2;
tmp.baz(tmp2)
} And let the optimizer do it's thing? Given that rust's move semantics, I can't see how this could cause any problems. This is just a sanity check; I'd be happy with a "no, it's complicated". This would fix the |
The thing is that destructors sometimes have side-effects (for On Wed, Mar 02, 2016 at 09:22:19AM -0800, Steven Allen wrote:
|
Assuming you mean "when a temporary would be referenced by a let-bound variable", I see why this is more complicated. |
I just want to leave my 2c that this is a very frustrating issue for newbies. I didn't think of myself as a newbie, having written two fairly stable libraries in rust, but today I was trying to write a memory manager for micro-controllers, learning about Thinking it was something I did with the internals, I began to question my entire way of doing things. Long story short it took me the better part of 4 hours to finally realize that nothing was wrong with my library. No -- what was wrong is that I hadn't put a I wish I had listened to the compiler better... maybe that is the lesson I really should learn here. |
@nikomatsakis What's the status of this issue? |
@brson no change at all. But I've had it on my list of things to write up instructions for. In fact, I was just coming to take a stab at that. |
OK, so, it's taking me a lot longer to prepare those instructions than I expected. In part this is because the original RFC is not very well specified. I've started a "amendment" (basically a rewrite) that both specifies the current behavior and tries to more precisely specify what RFC 66 should do. This will hopefully get done soon, you can see a draft here. My basic plan (at a very high level) is to:
|
I'm wondering about how this feature will interact with non-lexical lifetimes. Consider the following: fn main() {
let x;
{
x = &String::from("foo");
}
} Currently, this results in an error: My question: with NLLs, the lifetime of the reference in fn main() {
let x;
{
x = &String::from("foo");
// `x` is dead here
// Is the `String` dropped here?
}
// Or is it dropped here?
} Should the lifetime of the temporary created by |
Just throwing my opinion at this one. It's been one of the more frustrating issues with getting myself acquainted with Rust. A lot of popular languages now actually encourage method chaining. C#'s LINQ being the prime example. var peopleOldEnough = people.Where(p => p.Age >= 18).Select(p => p.FirstName); Not being able to call methods in a way that, at this point, feels natural when there's not a compelling reason why it needs to be that way only serves to act as a barrier between programmers and the language. I would love if this RFC got more attention. I bet this issue would be generating a lot of buzz if people knew
I understand why this isn't a high-priority issue. But, the beginner experience should be considered one of the most crucial things to nail down to drive Rust adoption. And, as a beginner, this is a bit of a roadblock. |
Yes, I hit it few times per week and get upset when I need to write a sequence of let statements instead of a chain. Chain emphasizes that the final result is the most important thing in a statement. It reduces pressure on brain for a programmer / reader. A sequence of let identifiers makes every let defined variable equally important for a reader to follow, and it is only to finally realise that all except the last variable do not really matter. Clear productivity loss even for experienced programmers, in my opinion. Longer it is open, more loss is accumulated. |
Does thinking about this as sets of constraints help? It certainly would make Rust a lot more approachable if a variable lived for as long as it was needed. We could use tooling to make it clear where an expression's lifetime ends. While we loose a little on explicitness, we gain a lot on on readability and coding ergonomics. |
Note that we are not proposing that — or at least, we are not proposing that we use lifetime inference to decide when a destructor runs. That would prevent us from making improvements like NLL without changing the runtime semantics of code, which is not good. This RFC is actually much more limited — it runs before any inference etc has been done. I've not carved out any time for my expanded version of the RFC -- I should at least push it somewhere I guess -- but I still think this is a good idea =) |
Forum discussion of cases where this is a semantic breaking change: |
We discussed this in today's @rust-lang/lang meeting, and this needs some further design work in order to be actionable. We still think this is a good idea, but it needs an owner and some specific design work. |
Some implementation notes and other thoughts here: |
@dingxiangfei2009 and I just had a call discussing how to implement this RFC. We settled on an implementation plan like this:
We can compute the information in rust/compiler/rustc_typeck/src/check/mod.rs Lines 465 to 469 in 461e807
It needs to be accessed by the "compute generator interiors" code, so it must happen sometime before that. It should happen right around the point where we analyze closure upvars, so that type info is available. This initial PR would not affect semantics. Once it is done, we can modify the code to examine type signatures and extend the lifetime of call arguments. |
…r=nikomatsakis Move the extended lifetime resolution into typeck context Related to rust-lang#15023 This PR is based on the [idea](rust-lang#15023 (comment)) of rust-lang#15023 by `@nikomatsakis.` This PR specifically proposes to - Delay the resolution of scopes of rvalues to a later stage, so that enough type information is available to refine those scopes based on relationships of lifetimes. - Highlight relevant parts that would help future reviews on the next installments of works to fully implement a solution to RFC 66.
If you just want to avoid having a bunch of let bindings everywhere, I realized you can get around that by doing it in a macro. macro_rules! baz {
( $x:ident ) => {
let mut k= foo();
let mut $x = k.bar();
};
} |
Tracking issue for rust-lang/rfcs#66: better temporary lifetimes.
Some unresolved questions to be settled when implementing:
Some examples where this matters:
My take: Probably we should just consider the fully inferred type.
Unresolved questions
The text was updated successfully, but these errors were encountered: