Transcript from the "References & Borrowing" Lesson
>> So first we're gonna talk about references and how they interact with borrowing, they're gonna talk about mutable references and finally slices. Okay, so, we talked about previously we had our example of printing years function which takes years and then we iterate through each of the years and at the end to deallocate.
[00:00:17] Years because yours is not returned. And we talked about how this is a problem, because if I want to call print yours twice in a row passing the same years, I Got a compiler error, specifically a use after move error. And we talked about how, one way we can fix this is with clone and what we could do is with this, returning the the vec, just for purposes of satisfying the compiler.
[00:00:36] Here's another way we can fix it. Loop, we just add three ampersands on the screen, which are highlighted in hot pink. So this actually also solves it and it makes it so that, this compiles and runs and everything works great. There's no cloning, there's no need to return like those extra do that sort of returning dance.
[00:00:55] This is sort of the solution to the problem that we had in the previous exercise. Okay, so what's going on here, let's talk about it. A couple things are going on. So first, let's look at this thing. This right here inside this box, is a new type that we haven't seen before.
[00:01:10] This is called a reference type and it begins with an ampersand. So this is not a vec of i32, is rather it is a reference to a vec of i32s, and we'll talk about the rules behind references later. So, a reference, is basically something that says, I want to have access to this thing, but I don't actually own it.
[00:01:31] I'm not going to clean it up, I'm just going to look at it. So, access to it but not ownership means, something different than ownership especially when it comes to deallocating memory. So here's another, a really common example of reference you can find. In this case we have ampersand self.
[00:01:48] So this is a reference to self. And this is what you see inside the length function of vectors as well as strings as well as other data structures like that. And basically it says, hey, when you're asking me for my lenth, that's not like transferring ownership, I'm not saying I'm gonna delete self, I'm gonna deallocate it after I'm done telling you the length.
[00:02:08] Of course not, that would be ridiculous. Instead, what it's gonna say is, yeah, just give me a reference to self, I'll go look at it, and figure out what its length is and return that. And then, we're not going to do anything having to do with who's responsible for deallocating this thing.
[00:02:21] The caller is still just as responsible as before, or the original owner is still responsible for deallocating this thing. I just want to take a look at it and then whoever, was originally going to deallocate it, they're still responsible for doing that. Yeah, so this is a reference to a vec i32, this is a reference to a self.
[00:02:39] So basically, you can think of what is happening here with this ampersand and here is it saying, hey, I temporarily want to give print years access two years. And ampersand years in this case where we're outside of the type signature, we're inside an actual value. This is basically called a borrow.
[00:02:55] So I'm saying I want to borrow years. So the metaphor years, it's not a perfect metaphor, but, it's basically the concept of like, okay, I have this thing, and I'm not giving it to you. I'm not transferring ownership from me to you. I'm just letting you borrow it.
[00:03:09] So I'm still responsible for it, it's still mine. And you're going to give it back to me at some point, there's sort of an implicit understanding there. But I am [COUGH] temporarily allowing you to have access to it, you can borrow it. So, when we write it like this, what we're basically saying is, okay, when I call print years, not going to transfer ownership, main is still responsible for main still owns years.
[00:03:32] Which means main is still responsible for deallocating it. We're just handing temporary ownership, sorry, we're handing temporary reference to it, to print here. So print yours is able to do some things with it, but not necessarily everything. So, in the context of this use after move compiler that we saw, the reason that this is called a borrow checker error.
[00:03:52] Is because typically, this is like the this sort of checking to see if all the borrows are done properly, is kind of the the uniquely rust thing. This is the thing that you don't really find in other languages. So it's colloquially called the borrow checker even though it also has to do with ownership errors, or as we'll see in the next section, lifetime errors.
[00:04:11] One really important thing to know about the borrow checker is you can't turn it off, I mentioned this because, it's a thing. It's a common misconception that people say, Rust has this borrow checker. But don't worry, you can turn it off using this keyword called unsafe. False, that is absolutely not true.
[00:04:26] In fact, it is so false that you can't turn off the borrow checker in Rust, is the exact title of a blog post, by a Rust core team member, who wrote this entire blog post, in order to try and dispel this myth. There is no way to drop the borrow checker.
[00:04:40] When you see an error like this, you got to figure out some way to deal with it, either by using clone or by using return or by introducing a borrow or something like that. There is no way to get around these things. So really important to note, that's why we're learning this [LAUGH] because, when you encounter an error like this, you got to figure out some way to deal with it.