See also threads like this: https://internals.rust-lang.org/t/accepting-nested-method-ca...
See also threads like this: https://internals.rust-lang.org/t/accepting-nested-method-ca...
As it was, I felt as though I were manipulating a child in order to get it to do what I wanted.
But yeah, we should improve this.
Just pointing out that this isn't as major a problem when actually using Rust once you've picked it up.
I found once I grasped the model that the borrow checker uses that I rarely fight it and instead find it catching many things that I miss.
Right now, the rules are very simple to explain. But that means your code gets a little more complex at times.
And more awkward in places due to convincing the checker that what you're doing is ok.
It's initially quite intuitive and makes sense. But as you use the language more you start questioning why it doesn't make sense and you eventually have to learn how rvalues work.
Atleast steveklabnik had the good sense to acknowledge the issue rather than blame it on the developer.
I'm merely pointing out that this is not always an issue when programming in Rust, just mostly for newcomers, which means that if you're willing to bear with it for a while whilst learning it won't be a problem later. This isn't an ideal situation and is one we should fix. But it's not as bad as a problem that plagues you whenever you are writing Rust code.
Some of these problems persist as awkwardness in even idiomatic code. Most go away. I write Rust code every day, and I've seen or written borrowck-induced awkward Rust code maybe twice this month.
All of this is not to say that it isn't a problem we should be fixing -- it is and we are. But it's less of an annoyance in everyday Rust programming than one initially gets the impression it will be.
Which is exactly what I was describing, why are you continuing to argue against the point?
I'm not implying that the problem is with the developer. I strongly feel that this is something we should fix. I strongly feel that programmers -- new or otherwise -- shouldn't have to deal with this.
I've said all this multiple times, go back and read my comments.. You're the one arguing the same point over and over.
I'm just pointing out that with some experience it ceases to be a problem. My point is simply this: This is not a problem that will plague you once you've been programming Rust for a while, so it's not one of those persistent annoyances that will stick with you no matter how much you program in a language. I'm only making that distinction. That it's not that bad. It's bad. We're fixing it. It's not the developer's fault. But neither is it a problem that will always plague you. It goes away as you start writing more idiomatic code. That should not be necessary, agreed, and we should fix that, but it is true.
I said as much in https://news.ycombinator.com/item?id=13415585
I'm starting to feel you're not commenting in good faith here. I'm not going to repeat the same thing over and over.
You claim it's not the developers issue all the while claiming the problem goes away once you get more experienced with Rust (hint: that means it's a developer issue).
What you really mean is that this issue affects people's non-local code design and that people will eventually get enough experience to head off the issues before they crop up.
What I'm saying, and what others have said, is that's a problem with rust and it needs to be fixed so it stops affecting such design.
I have found myself rewriting entire functions to get rid of awkwardness due to this issue, and having the experience to write it that way the first time doesn't mean it isn't an issue, and it doesn't mean that it should be idiomatic rust.
You keep trying to push this onto the developer, even while claiming you're not doing that.
This is _not_ shifting the blame to the developer. This is accepting the blame in the right place. The blame has been accepted. The rest of the point is not about blame (which has already been attributed), it's about hope.
Having accepted the blame, I'm saying that one should not feel too discouraged by this issue because most people eventually pick up a programming style that's less prone to this.
I'm not saying developers should have to. I'm not saying it's their fault that they haven't. It's totally our fault, and we should fix it. I'm just pointing out what usually happens for most folks learning Rust, so one should be optimistic about this problem and hopefully not be too discouraged by it :)
You're interpreting "The developer can avoid this by improving X" as a way of shifting blame to the developer. That is not the intention. It is merely pointing out that the developer can avoid the problem; the ability to avoid the problem does not imply that they are to be blamed for it. It's a comment to instil optimism about the issue. The blame for the issue has already been attributed.
I don't disagree that this is a problem with Rust. I don't disagree that Rust should fix it. It's being worked on. In the meantime, I'm advocating optimism for newcomers hitting this issue. One can do both.
Regardless of intention, it's a reasonable interpretation. Your initial response came across as defensive.
This particular issue was the final straw that made me decide to stop using Rust and wait. It makes the language feel sophomoric and not ready. I'm glad you guys are fixing the issue and maybe at some point I'll try Rust again but probably not before the borrow checker gets more sophisticated.
The ones who are not emotionally involved in Rust are not going to simply be hopeful that they'll eventually learn how to work around the deficiencies in the borrow checker.
Either way, we're beating a dead horse at this point so we may as well drop it.
Hope you find the time/inclination to pick up rust again! I'm sure these issues will be fixed eventually (hoping that is soon)
Others are due to not-immediately-obvious issues with code. One of the most common borrowck complaints I've seen is about the fact that you can't have mutable and immutable aliases operating simultaneously, even if you don't have threads involved. There's a reason behind that (http://manishearth.github.io/blog/2015/05/17/the-problem-wit...).
Take http://manishearth.github.io/blog/2015/05/17/the-problem-wit... for example...
fn main() {
let mut x = 0;
let y = &x;
println!("{}", y);
x += 1;
println!("{}", x);
}
It still doesn't pass the borrow checker.What I do mean is, many times we have people drop by IRC and say "the borrow checker is dumb, I want to do X, and it won't let me" and the reply is something like "have you considered threading" and they go "ohhhhh I see." There was a good quote of the week about this at some point, but I can't find it right now.
I don't happen to run into patterns like the above code in real Rust code, personally. That doesn't mean that they don't happen, but I'm interested in _real world_ cases where this becomes an issue. We've got a bunch of them, which is why we're pursuing non-lexical lifetimes, but it seems like for many, this is a _constant_ struggle, and I run into a NLL situation maybe once every two months. Figuring out that disconnect is very interesting to me. It matters because I'm going to be responsible for teaching it, so real examples are way better than contrived ones. Moving that focus is the point of my current re-write of these docs :)
Your argument that for real world programs the borrow checkers conservatism does not create technical problems is completely plausible to me. The issue lies somewhere else.
There is a psychological component to this. People struggle with the borrow checker, or at least they feel like they did. This is negative for rust.
My point is that it would be better if it weren't trivial to write short, safe programs that are not accepted by the compiler.
Where can one expect the line to be drawn? I don't know. I worked with Isabelle/HOL to formalize mathematical proofs and there I saw that we can indeed expect a computer to be reasonably clever in abstract reasoning. I'm not saying that the rust compiler is dumb, however, there is room for improvement.
Thanks for your(plural) work on rust, btw.
(I even tried to get unsafe renamed to "trusted"... that didn't work out.)
Recently I was parsing a line-oriented, whitespace delimited file and had to introduce a temporary ("line", below):
let f = File::open(path)?;
let reader = BufReader::new(f);
for line_result in reader.lines() {
let line = line_result?;
let mut word_iter = line.split_whitespace();
because I think something didn't live long enough when I did line_result?.split_whitespace(). I forget exactly what the code was like before I got it past the borrow checker, though.For me, it seems like every time I dip a toe into rust I run into borrow/NLL issues right off the bat.
Ah, see, I'd go straight for Entry in the hash case. Which might be what you're referring to.
yeah, that later one isn't NLL: it's that
line_result?.split_whitespace()
^ ^
the ? will return your String, but then split_whitespace returns &strs to that String. Since it's not bound anywhere, the String would be deallocated at the end of the line, which would make the iterator dangling. NLL won't fix that.Thanks for the clarification about the second case not being solved by NLL. Those examples were the ones I had in my mental "code I would like the borrow checker to accept" bucket.
Would Niko's proposals in that internals thread you linked ("Accepting nested method calls with an `&mut self` receiver") eliminate the need for the temporary in that second example?
{
let mut x = 1;
let y = &x;
do_stuff_with(y);
x += 1 // not allowed right now because y is still active
// no use of y here. possible uses of x
}
The lexical scope of y is the entire block (well, starting at the declaration of y). The actual scope of liveness ends after do_stuff_with -- y is no longer used at this point and x could be mutated. Right now you have to introduce an explicit scope block to make this work, but it's not a fundamental restriction in the language design.