1 00:00:06,336 --> 00:00:07,470 - In this section, 2 00:00:07,470 --> 00:00:09,510 we are going to discuss copying 3 00:00:09,510 --> 00:00:11,400 and moving in Rust, 4 00:00:11,400 --> 00:00:14,250 a concept that most languages don't have. 5 00:00:14,250 --> 00:00:16,230 So there are concepts that we need to learn 6 00:00:16,230 --> 00:00:17,250 and syntax, well, 7 00:00:17,250 --> 00:00:19,140 the syntax is actually quite straightforward. 8 00:00:19,140 --> 00:00:22,410 It's the concept that's the tricky part. 9 00:00:22,410 --> 00:00:23,640 It's all about what happens 10 00:00:23,640 --> 00:00:25,290 when you assign one variable to another. 11 00:00:25,290 --> 00:00:27,210 You'd think it would be straightforward. 12 00:00:27,210 --> 00:00:28,299 Take the value of B, 13 00:00:28,299 --> 00:00:29,891 copy the value into A, 14 00:00:29,891 --> 00:00:32,730 what could possibly be difficult about that? 15 00:00:32,730 --> 00:00:35,966 It turns out to be quite tricky actually. 16 00:00:35,966 --> 00:00:39,120 What happens, it all centers around 17 00:00:39,120 --> 00:00:41,040 a trait called copy. 18 00:00:41,040 --> 00:00:42,486 So if you remember in Rust, 19 00:00:42,486 --> 00:00:45,877 a trait is like an interface in other languages, 20 00:00:45,877 --> 00:00:48,781 and there's a special predefined trait 21 00:00:48,781 --> 00:00:52,350 called copy, which determines how values 22 00:00:52,350 --> 00:00:53,970 get assigned and copied, 23 00:00:53,970 --> 00:00:54,900 when you have an assignment 24 00:00:54,900 --> 00:00:56,940 like we've got here. 25 00:00:56,940 --> 00:00:58,882 So, this copy trait, 26 00:00:58,882 --> 00:01:02,910 if you have a data type which implements copy, 27 00:01:02,910 --> 00:01:04,500 it means that you can copy 28 00:01:04,500 --> 00:01:05,670 from one variable to another 29 00:01:05,670 --> 00:01:07,860 just by doing a bit copy. 30 00:01:07,860 --> 00:01:08,940 You can just copy the bits 31 00:01:08,940 --> 00:01:11,247 from one value into another. 32 00:01:11,247 --> 00:01:13,920 Right, so for simple types, 33 00:01:13,920 --> 00:01:15,450 like integers and floats 34 00:01:15,450 --> 00:01:17,040 and bullions, et cetera, 35 00:01:17,040 --> 00:01:19,620 they do implement the copy trait, 36 00:01:19,620 --> 00:01:21,392 and that means when you assign 37 00:01:21,392 --> 00:01:22,912 one variable to another, 38 00:01:22,912 --> 00:01:24,360 it just does a bit copy, 39 00:01:24,360 --> 00:01:28,342 and both variables end up having the same value. 40 00:01:28,342 --> 00:01:29,175 Okay? 41 00:01:29,175 --> 00:01:34,005 So, if B was 42 and I said, 42 00:01:34,005 --> 00:01:35,198 so that's that, 43 00:01:35,198 --> 00:01:40,198 and then I said A equals B. 44 00:01:40,260 --> 00:01:44,943 Then A would just be a bit copy, 42. 45 00:01:46,110 --> 00:01:48,888 Okay, so it'll copy from B into A 46 00:01:48,888 --> 00:01:50,550 just by doing a bit copy. 47 00:01:50,550 --> 00:01:52,920 They both end up being 42. 48 00:01:52,920 --> 00:01:54,960 That's quite straightforward. 49 00:01:54,960 --> 00:01:58,050 So you know, if that was the end of the story, 50 00:01:58,050 --> 00:02:00,240 that would be the end of the video. 51 00:02:00,240 --> 00:02:04,383 But most types in Rust don't implement copy. 52 00:02:05,280 --> 00:02:06,113 Okay? 53 00:02:06,113 --> 00:02:07,980 A good example of that is a string. 54 00:02:07,980 --> 00:02:08,880 We'll have a look at an example 55 00:02:08,880 --> 00:02:09,990 of this in a moment. 56 00:02:09,990 --> 00:02:13,833 So imagine I've got a string, B, 57 00:02:14,880 --> 00:02:16,410 and it holds this text. 58 00:02:16,410 --> 00:02:17,243 Hello. 59 00:02:19,260 --> 00:02:20,093 Like that. 60 00:02:20,093 --> 00:02:22,444 So B basically holds a pointer 61 00:02:22,444 --> 00:02:26,370 towards the address of that text. 62 00:02:26,370 --> 00:02:28,147 That's basically what happens. 63 00:02:28,147 --> 00:02:32,490 Now the string structure doesn't implement copy. 64 00:02:32,490 --> 00:02:37,020 So if you said A equals B, 65 00:02:37,020 --> 00:02:38,310 all it will do, 66 00:02:38,310 --> 00:02:40,320 well, It still does a bit copy, 67 00:02:40,320 --> 00:02:42,240 but it does a bit copy of the pointer. 68 00:02:42,240 --> 00:02:45,000 It's like a shallow copy, like that. 69 00:02:45,000 --> 00:02:46,925 So it'll just copy the pointer 70 00:02:46,925 --> 00:02:49,530 into A, if that's A, yeah. 71 00:02:49,530 --> 00:02:53,189 So A also ends up pointing to the same place. 72 00:02:53,189 --> 00:02:55,080 What it also does though 73 00:02:55,080 --> 00:02:58,920 is it basically unhinges object B. 74 00:02:58,920 --> 00:02:59,753 Okay? 75 00:02:59,753 --> 00:03:00,870 It automatically does that. 76 00:03:00,870 --> 00:03:03,030 When you assign for types 77 00:03:03,030 --> 00:03:04,445 that don't implement copy, 78 00:03:04,445 --> 00:03:06,600 when you assign one to another, 79 00:03:06,600 --> 00:03:08,644 it transfers ownership from that object 80 00:03:08,644 --> 00:03:10,710 into that object, 81 00:03:10,710 --> 00:03:13,560 and you can't use the original object afterwards. 82 00:03:13,560 --> 00:03:15,060 You can't use B, 83 00:03:15,060 --> 00:03:17,610 because it no longer owns the text. 84 00:03:17,610 --> 00:03:19,398 You have moved ownership. 85 00:03:19,398 --> 00:03:22,800 So for types that don't implement copy, 86 00:03:22,800 --> 00:03:26,820 like string, the value of B is moved into A. 87 00:03:26,820 --> 00:03:28,470 The value that B used to have 88 00:03:28,470 --> 00:03:31,290 is now effectively owned by A. 89 00:03:31,290 --> 00:03:34,830 A has acquired ownership and B has lost ownership, 90 00:03:34,830 --> 00:03:36,300 and you can't use B afterwards. 91 00:03:36,300 --> 00:03:39,705 If you try to, you get a compiler error. 92 00:03:39,705 --> 00:03:41,520 So let's have a look at 93 00:03:41,520 --> 00:03:43,890 simple types that do implement copy, 94 00:03:43,890 --> 00:03:45,120 like integers, 95 00:03:45,120 --> 00:03:47,580 and then types that don't implement copy, 96 00:03:47,580 --> 00:03:48,413 like strings. 97 00:03:48,413 --> 00:03:50,923 So here's an example with integers. 98 00:03:50,923 --> 00:03:52,920 Int, 32. 99 00:03:52,920 --> 00:03:55,740 They all implement the copy interface. 100 00:03:55,740 --> 00:03:57,030 So, a copy trait. 101 00:03:57,030 --> 00:04:01,590 So here, A is originally this bit pattern, 102 00:04:01,590 --> 00:04:04,080 and then I assign A into B. 103 00:04:04,080 --> 00:04:05,970 That's a simple bit copy, 104 00:04:05,970 --> 00:04:09,660 because I32 implements the copy trait. 105 00:04:09,660 --> 00:04:11,598 So just do a simple bit copy, 106 00:04:11,598 --> 00:04:14,250 A and B are both 42, 107 00:04:14,250 --> 00:04:16,320 nothing much to see here. 108 00:04:16,320 --> 00:04:19,050 So the assignment copies the value 109 00:04:19,050 --> 00:04:22,590 from A into B, as we've seen. 110 00:04:22,590 --> 00:04:24,300 You can use A afterwards, 111 00:04:24,300 --> 00:04:25,650 it hasn't lost ownership, 112 00:04:25,650 --> 00:04:27,929 it's just effectively cloned itself. 113 00:04:27,929 --> 00:04:30,750 So you can use A and B quite happily 114 00:04:30,750 --> 00:04:32,557 after that event. 115 00:04:32,557 --> 00:04:33,813 Simple. 116 00:04:35,190 --> 00:04:36,810 Right, moving a value, 117 00:04:36,810 --> 00:04:39,300 for types which don't implement copy, 118 00:04:39,300 --> 00:04:41,160 like string. 119 00:04:41,160 --> 00:04:42,150 Have a look what we've got here. 120 00:04:42,150 --> 00:04:45,570 So S1 is a string object, 121 00:04:45,570 --> 00:04:47,400 which means that, you know, 122 00:04:47,400 --> 00:04:50,820 basically it holds a pointer to some text. 123 00:04:50,820 --> 00:04:51,653 Hello. 124 00:04:54,000 --> 00:04:56,700 Then we have an assignment. 125 00:04:56,700 --> 00:04:58,443 This assignment, S2, 126 00:04:59,400 --> 00:05:02,730 is gonna be here and all it does, 127 00:05:02,730 --> 00:05:05,550 it doesn't do any kind of cloning, 128 00:05:05,550 --> 00:05:06,930 because that would be inefficient. 129 00:05:06,930 --> 00:05:07,950 It just basically copies 130 00:05:07,950 --> 00:05:10,200 whatever's in there into here. 131 00:05:10,200 --> 00:05:11,033 Okay? 132 00:05:11,033 --> 00:05:14,430 So, basically whatever pointer value 133 00:05:14,430 --> 00:05:16,290 used to be in here, 134 00:05:16,290 --> 00:05:18,570 that pointer value is also here. 135 00:05:18,570 --> 00:05:20,640 So S2 points there, 136 00:05:20,640 --> 00:05:23,880 but S1 has now lost ownership. 137 00:05:23,880 --> 00:05:24,713 Okay? 138 00:05:24,713 --> 00:05:26,850 So ownership of the text has moved, 139 00:05:26,850 --> 00:05:28,677 S1 has lost ownership, 140 00:05:28,677 --> 00:05:31,350 and S2 has acquired ownership. 141 00:05:31,350 --> 00:05:34,950 So, S2 will be hello, 142 00:05:34,950 --> 00:05:36,433 but you can't use S1. 143 00:05:37,437 --> 00:05:38,270 Okay? 144 00:05:38,270 --> 00:05:39,600 S1 has lost ownership. 145 00:05:39,600 --> 00:05:42,030 Ownership has been moved into S2. 146 00:05:42,030 --> 00:05:44,970 You can't use S1 afterwards, 147 00:05:44,970 --> 00:05:46,590 and that's actually enforced by the compiler. 148 00:05:46,590 --> 00:05:48,210 If you do try to use S1, 149 00:05:48,210 --> 00:05:49,530 you'll get a compiler error. 150 00:05:49,530 --> 00:05:51,000 It'll say you've lost ownership. 151 00:05:51,000 --> 00:05:54,540 Ownership has been moved away to S2. 152 00:05:54,540 --> 00:05:57,840 A move occurs when you move ownership 153 00:05:57,840 --> 00:05:59,970 of the data from S1 into S2. 154 00:05:59,970 --> 00:06:03,346 You can't then use S1 afterwards. 155 00:06:03,346 --> 00:06:07,397 So the assignment operator moves the value 156 00:06:07,397 --> 00:06:09,810 from S1 into S2. 157 00:06:09,810 --> 00:06:13,230 The pointer is copied into here. 158 00:06:13,230 --> 00:06:14,063 So effectively, 159 00:06:14,063 --> 00:06:16,881 ownership of that text is now owned by S2, 160 00:06:16,881 --> 00:06:18,417 not by S1. 161 00:06:18,417 --> 00:06:20,763 And you can't use S1 afterwards. 162 00:06:21,600 --> 00:06:24,000 Right, well let's see the example in our demo, 163 00:06:24,000 --> 00:06:26,280 project lesson six, scope ownership. 164 00:06:26,280 --> 00:06:28,500 Demo copying versus moving. 165 00:06:28,500 --> 00:06:29,370 Let's have a look at that, 166 00:06:29,370 --> 00:06:30,470 and then we'll run it. 167 00:06:31,350 --> 00:06:34,320 Okay, so first of all, in main, 168 00:06:34,320 --> 00:06:36,990 let's uncomment the bit of the demo 169 00:06:36,990 --> 00:06:37,890 that we want to cover. 170 00:06:37,890 --> 00:06:40,710 Demo copying versus moving. 171 00:06:40,710 --> 00:06:42,783 And it's here. 172 00:06:43,890 --> 00:06:45,210 So, for simple types, 173 00:06:45,210 --> 00:06:48,690 A is 42, B will also be 42, 174 00:06:48,690 --> 00:06:50,430 it'll print 42. 175 00:06:50,430 --> 00:06:51,263 42. 176 00:06:52,320 --> 00:06:53,670 Okay, good. 177 00:06:53,670 --> 00:06:55,320 For types which don't implement 178 00:06:55,320 --> 00:06:57,420 the copy trait, like strings, 179 00:06:57,420 --> 00:07:00,270 S1 is currently hello, 180 00:07:00,270 --> 00:07:02,280 but I move ownership, 181 00:07:02,280 --> 00:07:04,715 so that S2 now owns the text. 182 00:07:04,715 --> 00:07:07,041 S2 is hello and S1, 183 00:07:07,041 --> 00:07:09,630 I can't use it afterwards. 184 00:07:09,630 --> 00:07:11,550 If I tried to use S1, 185 00:07:11,550 --> 00:07:12,870 I'd get a compiler error, 186 00:07:12,870 --> 00:07:14,250 because I've donated, 187 00:07:14,250 --> 00:07:16,500 I've moved ownership to S2. 188 00:07:16,500 --> 00:07:18,510 S2 now owns the text. 189 00:07:18,510 --> 00:07:20,160 I can use S2 obviously, 190 00:07:20,160 --> 00:07:21,955 but I can't use S1. 191 00:07:21,955 --> 00:07:23,010 Let's see what would happen 192 00:07:23,010 --> 00:07:23,880 if I did try to, 193 00:07:23,880 --> 00:07:26,040 let's uncomment that line, 194 00:07:26,040 --> 00:07:28,263 and see what compiler error we would get. 195 00:07:31,860 --> 00:07:35,043 Okay, so I'm just gonna do a cargo check, 196 00:07:36,090 --> 00:07:38,460 just to check the syntax. 197 00:07:38,460 --> 00:07:41,370 This is a compile time enforced rule, 198 00:07:41,370 --> 00:07:42,813 enforced by the compiler. 199 00:07:43,650 --> 00:07:46,200 Right, I did say earlier 200 00:07:46,200 --> 00:07:47,220 that the error messages 201 00:07:47,220 --> 00:07:48,053 that you get in Rust 202 00:07:48,053 --> 00:07:51,420 are actually very helpful, quite verbose, 203 00:07:51,420 --> 00:07:53,640 but they tell you what led up to the error, 204 00:07:53,640 --> 00:07:55,950 and then what the error is. 205 00:07:55,950 --> 00:07:57,903 So, on line 14, 206 00:07:59,370 --> 00:08:01,413 I declared my string. 207 00:08:02,400 --> 00:08:03,723 S1 is a string. 208 00:08:05,010 --> 00:08:08,790 And so, S1 has type string, 209 00:08:08,790 --> 00:08:10,650 which does not implement the copy trait. 210 00:08:10,650 --> 00:08:12,780 It's very chatty, isn't it? 211 00:08:12,780 --> 00:08:16,830 So therefore, a move occurred here. 212 00:08:16,830 --> 00:08:18,120 Okay, so basically, 213 00:08:18,120 --> 00:08:20,490 S2 ownership is now moved into S2. 214 00:08:20,490 --> 00:08:22,407 So S2 basically owns the text, 215 00:08:22,407 --> 00:08:25,350 and S1 doesn't. 216 00:08:25,350 --> 00:08:26,280 So basically, 217 00:08:26,280 --> 00:08:27,750 without getting too much into 218 00:08:27,750 --> 00:08:29,130 the actual technicalities 219 00:08:29,130 --> 00:08:30,390 of the error message here, 220 00:08:30,390 --> 00:08:31,770 it basically means you can't use 221 00:08:31,770 --> 00:08:33,660 S1 afterwards, 222 00:08:33,660 --> 00:08:35,340 because its value has been lost, 223 00:08:35,340 --> 00:08:36,963 moved into S2. 224 00:08:37,950 --> 00:08:39,563 So you can't use a variable 225 00:08:39,563 --> 00:08:41,910 after it's been moved away. 226 00:08:41,910 --> 00:08:43,470 The reason why Rust does this, 227 00:08:43,470 --> 00:08:46,787 is to simplify when it knows clearly, 228 00:08:46,787 --> 00:08:50,070 when to deallocate the text for the string. 229 00:08:50,070 --> 00:08:51,519 Rather than having string one 230 00:08:51,519 --> 00:08:53,940 and string two both kind of point 231 00:08:53,940 --> 00:08:54,990 into the same buffer. 232 00:08:54,990 --> 00:08:57,390 You only have one active owner 233 00:08:57,390 --> 00:08:59,370 of memory at a time. 234 00:08:59,370 --> 00:09:00,480 So therefore, 235 00:09:00,480 --> 00:09:03,200 when S2 is deallocated, 236 00:09:03,200 --> 00:09:05,769 its distractor, its drop function 237 00:09:05,769 --> 00:09:07,650 will deallocate the text. 238 00:09:07,650 --> 00:09:09,660 Effectively, when you move ownership 239 00:09:09,660 --> 00:09:11,130 away from S1, 240 00:09:11,130 --> 00:09:12,030 it's as if that variable 241 00:09:12,030 --> 00:09:14,010 had never existed, okay? 242 00:09:14,010 --> 00:09:15,540 It's gone now. 243 00:09:15,540 --> 00:09:18,630 S2 is now the owner and is therefore 244 00:09:18,630 --> 00:09:20,469 responsible for deallocating the text 245 00:09:20,469 --> 00:09:22,964 when S2 goes outta scope. 246 00:09:22,964 --> 00:09:25,040 Right, so if I run the application now, 247 00:09:25,040 --> 00:09:26,490 it should work okay. 248 00:09:26,490 --> 00:09:28,920 I'm not trying to use S1 anymore, 249 00:09:28,920 --> 00:09:30,210 because I can't, 250 00:09:30,210 --> 00:09:31,890 because I've moved ownership. 251 00:09:31,890 --> 00:09:34,920 I can use S2 though, that should be fine. 252 00:09:34,920 --> 00:09:38,013 So let's do a cargo run just to confirm. 253 00:09:40,590 --> 00:09:43,813 So A and B, both printouts being 42, 254 00:09:45,533 --> 00:09:49,273 and S2, printout is being hello, 255 00:09:51,330 --> 00:09:53,793 and goodbye from this demo.