Feedback on the new "borrowing" section

Hi all, I'd love to get some feedback on

First, any feedback in general would be great.

Second: one of the things that this section is missing in motivation is why there are distinct &T and &mut T. So I'd like to come up with an example.

The issue is, the only owned data structure we've introduced so far is String. And since we don't have slices yet, we can't really get a pointer to the interior of String, which would show off one nice example of why we separate mutable and immutable borrows.

Any thoughts or ideas on this?

I'm from the "don't use Rust a ton but I read the last one" camp.

Like the last one, this gave me the information I was interested in without getting bogged down. I read through this and it stayed interesting. It's also succinct enough that I could see myself referencing this as I wrote some code to answer a question about an error I was getting.

Probably because I've never had it explained to me, but the motivation why there's distinct &T and &mut T seemed to be covered fine with the "we expect an immutable reference to not be changed out from under us". Coming at Rust from Elixir I'm used to not having mutable at all and the idea of making it explicit is comforting, but that's probably not a huge demographic.

1 Like

With low level languages I find it helpful to visualize how the things are implemented. Particularly, the question "how much bytes does this thing occupy" can be enlightening. So, it may be nice to say something like
"These &s are called ‘references’, and they allow you to refer to some value without taking ownership of it. References are implemented as pointers, and occupy 4 or 8 bytes". Reference == pointer is also an important bit.

Just like with real life, if I own something, you can borrow it from me. When you’re done, you have to give it back.

Ah, this can be really confusing, because in real live you can't lend a thing twice, but in Rust you can! This is an excellent metaphor for &mut though.

I find the explanation "We have let x = and let mut x = , so we need & and &mut" good enough. What is missing is why we need "shared ^ mutable" rule, and this is tricky :slight_smile: The most compelling example for me is

fn push_all(xs: &mut Vec<i32>, ys: &Vec<i32>) {
  for y in ys {

which segfaults miserably in C++ when xs is ys, and doesn't compile in Rust in that case. You can do the same thing with strings: fn concant(x: &mut String, y: &String)

1 Like

It's good. I have two suggestions.

  1. I think it would be more informative if the examples were explicit about taking a reference to the strings in the examples.

let s2 = &s1;
let len = calculate_length(s2);

Having talked to a few people that are coming to Rust from backgrounds that don't include the pleasure of dealing with pointers, it has become clear many don't understand that one is actually creating a new binding which is a reference when you & directly in a function call.

  1. I think adding a blurb about whether the returned String is copied on return in the last no_dangle example would help answer that question which I think is pretty common. However it may be a little off topic for this section.
1 Like

Outstanding. It is especially important that you showed the example of typical error messages in the documentation, because as someone new to Rust, I find myself often trying to work backwards from a borrow checker error to examples that show me the error of my ways. Many times I end up in stackoverflow responses that refer to pre-1.0 syntax or very narrow examples that aren't helpful because they provide a solution to a question rather than an explanation of the behavior. To be able to directly link the error to a clear example of the right way, and an explanation of what is going on, is invaluable, and I hope this type of documentation rises in the Google PageRank to be an authoritative source. I would suggest looking for other areas of common confusion in compilation and go into similar detail in the corresponding doc.

Here's a crazy idea I had at the end of last week which crosses documentation with the compiler. I wish I had the time and knowledge to implement it, and I'm not even sure it makes sense, but what if there was a way to extend the compiler with lints that linked specific error messages to crowdsourced (vetted, upvoted and curated) examples of the patterns and antipatterns leading to those error messages? Kind of like an optional verbose compiler mode on steroids.