1 00:00:01,540 --> 00:00:02,180 So far, 2 00:00:02,190 --> 00:00:04,229 we've only talked about immutably borrowing 3 00:00:04,230 --> 00:00:05,210 a value to read it. 4 00:00:05,740 --> 00:00:14,640 It's also possible to mutably borrow a value in order to change it without taking ownership. In this module, we'll show you how to create and use a mutable reference. 5 00:00:14,990 --> 00:00:16,880 We'll look at an example using a function, 6 00:00:16,950 --> 00:00:19,579 an example of a method where the first parameter is a mutable 7 00:00:19,580 --> 00:00:20,550 reference to self. 8 00:00:20,990 --> 00:00:22,580 In order to ensure memory-safety, 9 00:00:22,800 --> 00:00:24,789 the compiler enforces some rules around 10 00:00:24,790 --> 00:00:27,150 mutable references. We'll go over those. 11 00:00:27,600 --> 00:00:28,240 Lastly, 12 00:00:28,400 --> 00:00:32,180 we'll discuss an example of some code that doesn't compile because of the borrowing rules, 13 00:00:32,420 --> 00:00:40,250 and talk about the bug the compiler prevents in that situation. Let's get started with how to create and use a mutable reference. 14 00:00:41,740 --> 00:00:42,900 Recall from unit 1, 15 00:00:42,910 --> 00:00:43,700 module 3, 16 00:00:44,000 --> 00:00:45,790 that in order to make a variable mutable, 17 00:00:45,980 --> 00:00:48,350 we use the mut keyword in a let statement. 18 00:00:49,840 --> 00:00:50,630 Similarly, 19 00:00:50,680 --> 00:00:52,080 to create a mutable reference, 20 00:00:52,200 --> 00:00:54,250 we add mut after the ampersand. 21 00:00:55,820 --> 00:01:07,050 Let's look at an example of a function that needs to use mutable references. In this example, we have to find a struct named Bucket that has a liters field to store how much liquid is in the bucket. 22 00:01:08,070 --> 00:01:14,550 The [derive(Debug)] annotation on the struct definition enables us to print out the values of a Bucket for inspection later. 23 00:01:15,140 --> 00:01:21,350 We've also defined a function named pour that takes references to a source and target bucket, indicated with the ampersand. 24 00:01:22,290 --> 00:01:25,650 The function also takes an amount to transfer from the source to the target. 25 00:01:26,690 --> 00:01:34,969 The body of the function subtracts the amount from the source bucket's liters field and adds the amount to the target bucket's liters. 26 00:01:34,970 --> 00:01:35,309 In the main function, we instantiate 27 00:01:35,310 --> 00:01:41,150 two buckets and then pass references as arguments to the pour function, again, using the ampersand. 28 00:01:42,640 --> 00:01:43,750 If we compile this, 29 00:01:44,850 --> 00:01:49,550 we'll get errors that say we cannot assign to the liters field of immutable binding. 30 00:01:50,240 --> 00:01:54,220 The compiler also suggests that we change from an immutable reference to a mutable one. 31 00:01:55,840 --> 00:02:06,050 We replaced the ampersands in the definition of pour with &mut; the same replacement when we call pour and make each of the buckets mutable using the mut keyword. 32 00:02:07,440 --> 00:02:08,560 When we run this code, 33 00:02:08,750 --> 00:02:09,699 we can see that calling 34 00:02:09,700 --> 00:02:13,079 the pour function has moved three liters from Bucket 1 to Bucket 2. 35 00:02:14,940 --> 00:02:21,150 Another common way mutable references are used is as the first parameter of methods, as &mut self 36 00:02:21,540 --> 00:02:24,450 so that these methods can modify the current instance. 37 00:02:26,010 --> 00:02:28,750 We touched on this briefly in unit 1, module 9, 38 00:02:28,810 --> 00:02:30,150 but here's another example. 39 00:02:30,840 --> 00:02:34,750 We've defined a CarPool struct to model people sharing rides to work. 40 00:02:35,240 --> 00:02:36,839 The struct holds a vector of strings, 41 00:02:36,840 --> 00:02:39,950 representing the names of the passengers currently in the vehicle. 42 00:02:41,040 --> 00:02:45,920 We've defined a method named pick_up on CarPool that takes a mutable reference to itself 43 00:02:46,190 --> 00:02:49,539 so that this method can change the fields of the current CarPool 44 00:02:49,540 --> 00:02:50,200 instance. 45 00:02:51,040 --> 00:02:53,050 The method also takes the name of a passenger, 46 00:02:53,260 --> 00:02:55,399 and the body pushes the name into the passengers 47 00:02:55,400 --> 00:02:58,689 vector. In the main function, we've instantiated 48 00:02:58,690 --> 00:03:02,860 a new mutable instance of a CarPool, named monday_car_pool, 49 00:03:03,060 --> 00:03:04,650 that doesn't have any passengers. 50 00:03:05,340 --> 00:03:08,450 Then, we've called the pick_up method to add passengers to the vehicle. 51 00:03:10,440 --> 00:03:11,450 When we run this, 52 00:03:11,460 --> 00:03:13,159 we can see that the CarPool accumulates 53 00:03:13,160 --> 00:03:13,699 passengers 54 00:03:13,700 --> 00:03:15,150 as we call the pick_up method. 55 00:03:16,890 --> 00:03:18,770 Notice that because of the way methods work, 56 00:03:18,940 --> 00:03:22,350 we don't have to create a mutable reference to monday_car_pool explicitly 57 00:03:22,360 --> 00:03:23,329 with &mut 58 00:03:23,330 --> 00:03:24,250 when we call pick_up. 59 00:03:25,090 --> 00:03:27,860 Rust creates the reference automatically for the self parameter, 60 00:03:28,050 --> 00:03:29,850 and it knows to make it mutable as well. 61 00:03:31,310 --> 00:03:34,250 This may make it hard to tell which methods mutate self, 62 00:03:34,640 --> 00:03:39,450 but you can always find out by looking at the signature of the methods in the API documentation. 63 00:03:40,990 --> 00:03:44,340 The compiler enforces some rules involving mutable references. 64 00:03:44,520 --> 00:03:45,950 Let's explore those now. 65 00:03:47,480 --> 00:03:49,370 The rules are that, when you have a reference, 66 00:03:49,380 --> 00:03:55,950 you can either have any number of immutable references to a value or a single mutable reference to that value. 67 00:03:57,500 --> 00:03:59,650 To understand why these rules are necessary, 68 00:03:59,760 --> 00:04:04,310 imagine an art class where the students are painting a bowl of fruit set up in the middle of the room. 69 00:04:05,840 --> 00:04:09,850 Any number of students can look at the bowl of fruit at the same time to work on their painting. 70 00:04:10,240 --> 00:04:12,500 Because none of the students are changing the fruit setup, 71 00:04:12,620 --> 00:04:14,050 they don't interfere with each other. 72 00:04:14,440 --> 00:04:17,550 This is like having many immutable references to the same value. 73 00:04:19,040 --> 00:04:22,550 If someone comes in in the middle of a class and rearranges the fruit, 74 00:04:22,940 --> 00:04:27,550 none of the students would be able to finish their paintings because the scene they were referencing is now different. 75 00:04:28,440 --> 00:04:33,500 This is what would happen if a mutable reference was allowed at the same time that there were immutable references, 76 00:04:33,700 --> 00:04:34,850 which would cause bugs. 77 00:04:36,090 --> 00:04:41,150 Changing the fruit's position should only happen before or after class, when there are no students. 78 00:04:42,690 --> 00:04:42,919 Even 79 00:04:42,920 --> 00:04:45,080 if there weren't any students trying to paint at the time, 80 00:04:45,220 --> 00:04:48,250 if multiple people were changing the fruit setup at the same time, 81 00:04:48,570 --> 00:04:51,350 they could also conflict with each other and cause problems. 82 00:04:51,740 --> 00:04:54,750 This is why only one mutable reference is allowed at a time. 83 00:04:56,240 --> 00:04:59,090 Let's look at some code that doesn't compile because of these rules, 84 00:04:59,180 --> 00:05:01,850 to better understand the problems that Rust prevents. 85 00:05:03,340 --> 00:05:07,550 Here, we have a vector named list that contains the values 1, 2, and 3. 86 00:05:08,540 --> 00:05:13,300 We also have a for loop that iterates over the values in the list. For each value, 87 00:05:13,360 --> 00:05:18,550 the body of the loop prints out the current item and then adds to the list the current item plus one. 88 00:05:20,140 --> 00:05:23,920 If this code was allowed to compile and run, on the first iteration of the loop, 89 00:05:23,960 --> 00:05:26,049 i would be 1. The code 90 00:05:26,050 --> 00:05:29,080 would print out i is 1 and then would push 2 under the list, making the list 1, 2, 3, 2. 91 00:05:29,140 --> 00:05:36,490 Continuing to execute the code would make the vector grow continuously, 92 00:05:36,520 --> 00:05:41,210 and we'd have an infinite loop. This is likely not what we intended to happen with this code, 93 00:05:41,450 --> 00:05:43,150 but that's not even the real problem. 94 00:05:44,640 --> 00:05:47,609 Let's look at the error message the compiler gives us when we try to compile 95 00:05:47,610 --> 00:05:52,389 this code. It says, cannot borrow `list` as mutable because it is also borrowed 96 00:05:52,390 --> 00:05:53,250 as immutable. 97 00:05:54,040 --> 00:05:56,450 The immutable borrow of list occurs in the for loop, 98 00:05:56,840 --> 00:05:59,619 and the mutable borrow of list occurs when we call list.push. 99 00:05:59,620 --> 00:06:02,189 Another way 100 00:06:02,190 --> 00:06:06,090 we could have figured out that the push method takes a mutable reference to its target 101 00:06:06,190 --> 00:06:07,950 is by looking at its documentation. 102 00:06:08,370 --> 00:06:11,750 The signature shows that this method takes a mutable reference to self. 103 00:06:13,240 --> 00:06:17,110 The real problem has to do with the management of the memory backing the vector, 104 00:06:17,120 --> 00:06:18,550 which looks something like this. 105 00:06:19,440 --> 00:06:26,510 Here's the immutable borrow that the for loop takes and the mutable borrow that the push method takes. When you have a mutable borrow, 106 00:06:26,730 --> 00:06:31,350 one of the aspects of the vector's data structure that could change is the pointer to the heap data. 107 00:06:31,990 --> 00:06:34,030 If the vector has been filled to capacity, 108 00:06:34,140 --> 00:06:35,950 and we call push to add a new value, 109 00:06:36,270 --> 00:06:41,750 the implementation of push may need to allocate more memory, and change the pointer to point to the new storage location. 110 00:06:42,670 --> 00:06:43,440 At this point, 111 00:06:43,710 --> 00:06:48,150 the immutable reference that the for loop has to the vector now points to invalid memory. 112 00:06:48,840 --> 00:06:51,470 This is memory unsafety that could cause seg faults, 113 00:06:51,500 --> 00:06:58,690 but the Rust compiler prevents that. This particular bug is called iterator invalidation and is a problem in many languages, 114 00:06:58,700 --> 00:06:59,750 but not in Rust. 115 00:07:01,140 --> 00:07:04,250 We've now covered how borrowing and mutability interact. 116 00:07:04,740 --> 00:07:07,910 We've shown how to use mutable references in functions and methods. 117 00:07:08,540 --> 00:07:14,500 We've talked about the borrowing rules that say you can either have multiple immutable references or one mutable reference. 118 00:07:15,240 --> 00:07:26,390 And we've looked at an iterator invalidation bug that Rust disallows by enforcing the borrowing rules. In the next module, we'll demonstrate some common code patterns that arise due to borrowing.