Skip to content

Commit c47dfbb

Browse files
committed
Guide: ownership
1 parent 0f09f51 commit c47dfbb

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

src/doc/guide.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3642,6 +3642,173 @@ In order to truly understand this error, we have to learn a few new concepts:
36423642

36433643
## Ownership, borrowing, and lifetimes
36443644

3645+
Whenever a resource of some kind is created, something must be responsible
3646+
for destroying that resource as well. Given that we're discussing pointers
3647+
right now, let's discuss this in the context of memory allocation, though
3648+
it applies to other resources as well.
3649+
3650+
When you allocate heap memory, you need a mechanism to free that memory. Many
3651+
languages let the programmer control the allocation, and then use a garbage
3652+
collector to handle the deallocation. This is a valid, time-tested strategy,
3653+
but it's not without its drawbacks. Because the programmer does not have to
3654+
think as much about deallocation, allocation becomes something commonplace,
3655+
because it's easy. And if you need precise control over when something is
3656+
deallocated, leaving it up to your runtime can make this difficult.
3657+
3658+
Rust chooses a different path, and that path is called **ownership**. Any
3659+
binding that creates a resource is the **owner** of that resource. Being an
3660+
owner gives you three privileges, with two restrictions:
3661+
3662+
1. You control when that resource is deallocated.
3663+
2. You may lend that resource, immutably, to as many borrowers as you'd like.
3664+
3. You may lend that resource, mutably, to a single borrower. **BUT**
3665+
4. Once you've done so, you may not also lend it out otherwise, mutably or
3666+
immutably.
3667+
5. You may not lend it out mutably if you're currently lending it to someone.
3668+
3669+
What's up with all this 'lending' and 'borrowing'? When you allocate memory,
3670+
you get a pointer to that memory. This pointer allows you to manipulate said
3671+
memory. If you are the owner of a pointer, then you may allow another
3672+
binding to temporarily borrow that pointer, and then they can manipulate the
3673+
memory. The length of time that the borrower is borrowing the pointer
3674+
from you is called a **lifetime**.
3675+
3676+
If two distinct bindings share a pointer, and the memory that pointer points to
3677+
is immutable, then there are no problems. But if it's mutable, both pointers
3678+
can attempt to write to the memory at the same time, causing a **race
3679+
condition**. Therefore, if someone wants to mutate something that they've
3680+
borrowed from you, you must not have lent out that pointer to anyone else.
3681+
3682+
Rust has a sophisticated system called the **borrow checker** to make sure that
3683+
everyone plays by these rules. At compile time, it verifies that none of these
3684+
rules are broken. If there's no problem, our program compiles successfully, and
3685+
there is no runtime overhead for any of this. The borrow checker works only at
3686+
compile time. If the borrow checker did find a problem, it will report a
3687+
**lifetime error**, and your program will refuse to compile.
3688+
3689+
That's a lot to take in. It's also one of the _most_ important concepts in
3690+
all of Rust. Let's see this syntax in action:
3691+
3692+
```{rust}
3693+
{
3694+
let x = 5i; // x is the owner of this integer, which is memory on the stack.
3695+
3696+
// other code here...
3697+
3698+
} // privilege 1: when x goes out of scope, this memory is deallocated
3699+
3700+
/// this function borrows an integer. It's given back automatically when the
3701+
/// function returns.
3702+
fn foo(x: &int) -> &int { x }
3703+
3704+
{
3705+
let x = 5i; // x is the owner of this integer, which is memory on the stack.
3706+
3707+
// privilege 2: you may lend that resource, to as many borrowers as you'd like
3708+
let y = &x;
3709+
let z = &x;
3710+
3711+
foo(&x); // functions can borrow too!
3712+
3713+
let a = &x; // we can do this alllllll day!
3714+
}
3715+
3716+
{
3717+
let mut x = 5i; // x is the owner of this integer, which is memory on the stack.
3718+
3719+
let y = &mut x; // privilege 3: you may lend that resource to a single borrower,
3720+
// mutably
3721+
}
3722+
```
3723+
3724+
If you are a borrower, you get a few privileges as well, but must also obey a
3725+
restriction:
3726+
3727+
1. If the borrow is immutable, you may read the data the pointer points to.
3728+
2. If the borrow is mutable, you may read and write the data the pointer points to.
3729+
3. You may lend the pointer to someone else in an immutable fashion, **BUT**
3730+
4. When you do so, they must return it to you before you must give your own
3731+
borrow back.
3732+
3733+
This last requirement can seem odd, but it also makes sense. If you have to
3734+
return something, and you've lent it to someone, they need to give it back to
3735+
you for you to give it back! If we didn't, then the owner could deallocate
3736+
the memory, and the person we've loaned it out to would have a pointer to
3737+
invalid memory. This is called a 'dangling pointer.'
3738+
3739+
Let's re-examine the error that led us to talk about all of this, which was a
3740+
violation of the restrictions placed on owners who lend something out mutably.
3741+
The code:
3742+
3743+
```{rust,ignore}
3744+
let mut x = 5i;
3745+
let y = &mut x;
3746+
let z = &mut x;
3747+
```
3748+
3749+
The error:
3750+
3751+
```{notrust,ignore}
3752+
error: cannot borrow `x` as mutable more than once at a time
3753+
let z = &mut x;
3754+
^
3755+
note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
3756+
let y = &mut x;
3757+
^
3758+
note: previous borrow ends here
3759+
fn main() {
3760+
let mut x = 5i;
3761+
let y = &mut x;
3762+
let z = &mut x;
3763+
}
3764+
^
3765+
```
3766+
3767+
This error comes in three parts. Let's go over each in turn.
3768+
3769+
```{notrust,ignore}
3770+
error: cannot borrow `x` as mutable more than once at a time
3771+
let z = &mut x;
3772+
^
3773+
```
3774+
3775+
This error states the restriction: you cannot lend out something mutable more
3776+
than once at the same time. The borrow checker knows the rules!
3777+
3778+
```{notrust,ignore}
3779+
note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
3780+
let y = &mut x;
3781+
^
3782+
```
3783+
3784+
Some compiler errors come with notes to help you fix the error. This error comes
3785+
with two notes, and this is the first. This note informs us of exactly where
3786+
the first mutable borrow occurred. The error showed us the second. So now we
3787+
see both parts of the problem. It also alludes to rule #3, by reminding us that
3788+
we can't change `x` until the borrow is over.
3789+
3790+
```{notrust,ignore}
3791+
note: previous borrow ends here
3792+
fn main() {
3793+
let mut x = 5i;
3794+
let y = &mut x;
3795+
let z = &mut x;
3796+
}
3797+
^
3798+
```
3799+
3800+
Here's the second note, which lets us know where the first borrow would be over.
3801+
This is useful, because if we wait to try to borrow `x` after this borrow is
3802+
over, then everything will work.
3803+
3804+
These rules are very simple, but that doesn't mean that they're easy. For more
3805+
advanced patterns, please consult the [Lifetime Guide](guide-lifetimes.html).
3806+
You'll also learn what this type signature with the `'a` syntax is:
3807+
3808+
```{rust,ignore}
3809+
pub fn as_maybe_owned(&self) -> MaybeOwned<'a> { ... }
3810+
```
3811+
36453812
## Boxes
36463813

36473814
All of our references so far have been to variables we've created on the stack.

0 commit comments

Comments
 (0)