1 00:00:00,000 --> 00:00:07,900 [No Audio] 2 00:00:07,933 --> 00:00:10,433 In the previous tutorial, we looked in details 3 00:00:10,434 --> 00:00:12,566 at two specific problems that are dangling 4 00:00:12,600 --> 00:00:15,300 references and the undetermined lifetimes. 5 00:00:15,900 --> 00:00:18,100 In this tutorial, we will be looking at the 6 00:00:18,101 --> 00:00:20,366 concept of lifetime specifiers, which will 7 00:00:20,367 --> 00:00:22,666 enable us to overcome these issues, pretty 8 00:00:22,667 --> 00:00:25,333 much exciting material to cover. So let's get started. 9 00:00:26,000 --> 00:00:27,800 I'm starting with the code that we 10 00:00:27,801 --> 00:00:30,300 have seen in the last tutorial, this program 11 00:00:30,301 --> 00:00:32,966 was having an issue, that was missing lifetime 12 00:00:32,967 --> 00:00:36,466 specifier. Okay, to deal with this problem, 13 00:00:36,467 --> 00:00:38,666 the Rust allows us to specify explicitly 14 00:00:38,667 --> 00:00:41,300 lifetimes which are known as generic lifetime 15 00:00:41,301 --> 00:00:44,166 parameters. A generic lifetime parameter 16 00:00:44,167 --> 00:00:46,466 imposes a lifetime constraint on the 17 00:00:46,500 --> 00:00:49,733 references and the return values of a function. 18 00:00:49,766 --> 00:00:52,066 Let us modify the existing examples 19 00:00:52,067 --> 00:00:54,400 with the help of some generic lifetime parameters. 20 00:00:55,233 --> 00:00:56,933 The generic lifetime parameters 21 00:00:56,934 --> 00:00:58,600 will be specified after the name of the 22 00:00:58,601 --> 00:01:01,200 function, inside less than and greater than symbols. 23 00:01:02,233 --> 00:01:04,433 Typically, small case letters along 24 00:01:04,434 --> 00:01:06,500 with a single quotes are used for this purpose. 25 00:01:06,900 --> 00:01:08,400 Let me add generic lifetime 26 00:01:08,401 --> 00:01:10,166 parameters for the two variables. 27 00:01:10,200 --> 00:01:16,466 [No Audio] 28 00:01:16,467 --> 00:01:20,200 The 'a and 'b are the generic lifetime specifiers, 29 00:01:20,201 --> 00:01:22,800 which will be used by the inputs and outputs of this 30 00:01:22,801 --> 00:01:25,133 function. Next, I would specify to the 31 00:01:25,134 --> 00:01:27,600 compiler that the variable first_str 32 00:01:27,633 --> 00:01:29,666 has a lifetime which is specified by the 33 00:01:29,700 --> 00:01:32,500 'a in the variable second_str 34 00:01:32,501 --> 00:01:34,500 will have a lifetime specifier 35 00:01:34,533 --> 00:01:36,566 which will be specified using the generic 36 00:01:36,567 --> 00:01:38,600 lifetime parameters 'b. 37 00:01:39,500 --> 00:01:43,000 This will have a syntax of &,and after that without any 38 00:01:43,001 --> 00:01:45,466 spaces 'a, and for the second 39 00:01:45,467 --> 00:01:47,666 variable, I will do the same by mentioning 40 00:01:47,700 --> 00:01:50,433 & and immediately followed by 'b. 41 00:01:50,800 --> 00:01:53,233 For the output I will need to mention 42 00:01:53,266 --> 00:01:55,900 which of the two variable's 43 00:01:55,901 --> 00:01:59,066 lifetime the output will be assuming. So I 44 00:01:59,067 --> 00:02:02,100 will mention, let's say 'a, which 45 00:02:02,101 --> 00:02:03,966 tells the compiler that the lifetime of the 46 00:02:03,967 --> 00:02:06,366 returning variable is at least equal to that 47 00:02:06,367 --> 00:02:09,600 of variable first_str. This 48 00:02:09,601 --> 00:02:11,666 program will now compile without any error, 49 00:02:11,700 --> 00:02:13,200 let us execute. 50 00:02:13,201 --> 00:02:19,133 [No Audio] 51 00:02:19,134 --> 00:02:21,100 What will happen if I change the returning 52 00:02:21,101 --> 00:02:25,133 value from a first_str to that of second_str? 53 00:02:26,000 --> 00:02:28,000 In this case, the compiler will complain again. 54 00:02:28,600 --> 00:02:32,200 The error in this case is that of lifetime mismatch. This 55 00:02:32,201 --> 00:02:34,100 is because the returning reference in this 56 00:02:34,101 --> 00:02:36,400 case does not match the returning lifetime, 57 00:02:36,666 --> 00:02:39,500 which is specified as date of 'a. 58 00:02:40,633 --> 00:02:43,333 Now let us look at some important points 59 00:02:43,334 --> 00:02:46,133 with regards to the generic lifetime parameters. 60 00:02:47,833 --> 00:02:49,366 The very first point to note is 61 00:02:49,367 --> 00:02:51,600 that the generic lifetime parameters are only 62 00:02:51,601 --> 00:02:54,333 needed when we use references as outputs from 63 00:02:54,366 --> 00:02:56,900 a function. Let us see this in some detail. 64 00:02:58,133 --> 00:03:00,000 I will write the program that is similar to 65 00:03:00,001 --> 00:03:02,166 program considered in the previous tutorial, 66 00:03:02,366 --> 00:03:04,233 I will declare a couple of variables. 67 00:03:04,234 --> 00:03:09,300 [No Audio] 68 00:03:09,301 --> 00:03:11,500 Next, I will pass these two values by 69 00:03:11,501 --> 00:03:13,533 reference to a function as inputs 70 00:03:13,566 --> 00:03:15,600 [No Audio] 71 00:03:15,633 --> 00:03:18,300 The output will be a simple i32 type integer. 72 00:03:18,301 --> 00:03:21,866 [No Audio] 73 00:03:21,867 --> 00:03:23,633 Inside the function, I will compare the two 74 00:03:23,634 --> 00:03:25,700 numbers, and we'll return the actual value of 75 00:03:25,701 --> 00:03:27,533 the variable which is greater in value. 76 00:03:27,534 --> 00:03:36,300 [No Audio] 77 00:03:36,301 --> 00:03:38,833 In this case, the return is a variable and 78 00:03:38,834 --> 00:03:40,900 not a reference. So therefore, I have added 79 00:03:40,901 --> 00:03:44,133 stars to the values of the variables, because 80 00:03:44,134 --> 00:03:46,566 they are references and we need stars to get 81 00:03:46,567 --> 00:03:48,733 the values from a variable which is a reference. 82 00:03:49,100 --> 00:03:50,800 So in summary, this is the same 83 00:03:50,801 --> 00:03:53,000 program but the return type in this case is 84 00:03:53,001 --> 00:03:54,800 not a reference but rather a value. 85 00:03:55,300 --> 00:03:56,933 Let us call this function from the main. 86 00:03:56,966 --> 00:04:01,433 [No Audio] 87 00:04:01,466 --> 00:04:03,500 You may note that, the compiler is not complaining. 88 00:04:03,933 --> 00:04:05,966 This is because, the issue of lifetime and 89 00:04:05,967 --> 00:04:08,766 undetermined lifetimes is when we use a 90 00:04:08,767 --> 00:04:11,700 reference as a returning value. So the first 91 00:04:11,701 --> 00:04:13,900 point that we should note is that, typically 92 00:04:13,901 --> 00:04:15,900 the generic lifetime parameters are needed 93 00:04:15,901 --> 00:04:18,533 when we use references as function outputs. 94 00:04:20,033 --> 00:04:22,300 The second important point to 95 00:04:22,301 --> 00:04:24,300 note is that, the lifetime parameters are only 96 00:04:24,301 --> 00:04:27,033 specified with references. Let us look into 97 00:04:27,034 --> 00:04:28,700 it with the help of some examples. 98 00:04:29,200 --> 00:04:31,833 I will modify the same program, I will add a 99 00:04:31,834 --> 00:04:33,466 generic to this program. 100 00:04:33,467 --> 00:04:37,633 [No Audio] 101 00:04:37,634 --> 00:04:39,033 Inside a function, I will use 102 00:04:39,034 --> 00:04:41,733 a reference for the variable i and a value 103 00:04:41,734 --> 00:04:42,833 for the variable j. 104 00:04:42,866 --> 00:04:49,266 [No Audio] 105 00:04:49,267 --> 00:04:52,033 For the output, I will add so mentioned the reference. 106 00:04:52,034 --> 00:04:57,400 [No Audio] 107 00:04:57,433 --> 00:04:59,400 I will simplify the body of the program by 108 00:04:59,401 --> 00:05:01,200 just returning the variable i. 109 00:05:02,200 --> 00:05:04,533 In the function call, I will also update the first 110 00:05:04,534 --> 00:05:06,233 parameter to that of reference. 111 00:05:06,266 --> 00:05:10,433 [No Audio] 112 00:05:10,466 --> 00:05:13,166 Now in the Function Parameter List, I will add a generic 113 00:05:13,167 --> 00:05:16,133 lifetime of 'a to that of the variable i, 114 00:05:17,400 --> 00:05:19,300 and also to the output value. 115 00:05:19,301 --> 00:05:22,333 [No Audio] 116 00:05:22,366 --> 00:05:24,633 If I try to add a generic lifetime to that of the 117 00:05:24,634 --> 00:05:26,600 variable j, the compiler will complain. 118 00:05:27,033 --> 00:05:29,400 The point which we wanted to emphasize is that, 119 00:05:29,401 --> 00:05:31,333 the generic lifetime parameters are only 120 00:05:31,334 --> 00:05:33,900 mentioned with the references. If we remove 121 00:05:33,901 --> 00:05:36,000 the lifetime parameters from the variable j 122 00:05:36,001 --> 00:05:38,400 and execute, the program will execute successfully. 123 00:05:38,401 --> 00:05:44,000 [No Audio] 124 00:05:44,033 --> 00:05:46,766 The next point we want to focus is on the 125 00:05:46,767 --> 00:05:50,200 issue with multiple lifetimes. Let us look 126 00:05:50,201 --> 00:05:52,000 again at the program containing the greater 127 00:05:52,001 --> 00:05:54,000 than function. Let us take rid of the 128 00:05:54,001 --> 00:05:55,800 previous code and write fresh. 129 00:05:55,801 --> 00:05:59,000 [No Audio] 130 00:05:59,033 --> 00:06:00,866 I will define a couple of variables. 131 00:06:00,867 --> 00:06:05,466 [No Audio] 132 00:06:05,467 --> 00:06:06,300 Next, I will call the 133 00:06:06,301 --> 00:06:08,133 function greater with two references to the 134 00:06:08,134 --> 00:06:11,166 variable of int1 and int2, and will store 135 00:06:11,167 --> 00:06:12,600 the result in a variable. 136 00:06:12,601 --> 00:06:17,433 [No Audio] 137 00:06:17,434 --> 00:06:19,633 Next, I will define the greater than function 138 00:06:19,634 --> 00:06:22,000 with two references as inputs, and for the 139 00:06:22,001 --> 00:06:24,000 output, I will also mention a reference. 140 00:06:24,001 --> 00:06:30,033 [No Audio] 141 00:06:30,034 --> 00:06:33,333 In the body, I will return the greater of the two values. 142 00:06:33,334 --> 00:06:39,400 [No Audio] 143 00:06:39,401 --> 00:06:42,300 I will now add a couple of generic lifetime parameters. 144 00:06:42,301 --> 00:06:45,200 [No Audio] 145 00:06:45,201 --> 00:06:47,000 I will attach the generic 'a 146 00:06:47,033 --> 00:06:49,000 to the variable i, and in the same way 147 00:06:49,001 --> 00:06:51,366 I will add a generic lifetime parameter b. 148 00:06:51,367 --> 00:06:53,533 [No Audio] 149 00:06:53,534 --> 00:06:56,266 For the output, I will mention lifetime parameter a. 150 00:06:57,700 --> 00:06:58,866 In this case now, there are 151 00:06:58,867 --> 00:07:00,466 different lifetimes for the returning 152 00:07:00,467 --> 00:07:03,866 variable, which can be either i or j. Since 153 00:07:03,867 --> 00:07:06,000 the compiler anticipates that there may be 154 00:07:06,001 --> 00:07:08,266 situation and possibility for the variable j 155 00:07:08,267 --> 00:07:10,766 to be the returning reference, so 156 00:07:10,767 --> 00:07:12,733 therefore, it sees in advance that the 157 00:07:12,734 --> 00:07:15,200 variable j does not match the lifetime of the 158 00:07:15,201 --> 00:07:17,833 returning variable. This means we need to 159 00:07:17,834 --> 00:07:20,133 keep a close eye on the returning values from 160 00:07:20,134 --> 00:07:22,566 a function, which are the places to take care 161 00:07:22,567 --> 00:07:24,433 of with regards to the lifetime. 162 00:07:25,333 --> 00:07:27,233 Let us now look at another important point, 163 00:07:27,800 --> 00:07:30,900 we will modify the same program to illustrate a key 164 00:07:30,901 --> 00:07:33,100 point, that is the lifetime will correspond to 165 00:07:33,101 --> 00:07:35,533 the minimum lifetime in case of association 166 00:07:35,534 --> 00:07:38,700 with multiple variables. I will change the 167 00:07:38,701 --> 00:07:42,500 lifetime parameter for the variable j to that of 'a. 168 00:07:43,800 --> 00:07:45,033 Next in the main function, 169 00:07:45,034 --> 00:07:46,933 I will introduce a code segment, and we'll 170 00:07:46,934 --> 00:07:50,066 introduce the statement of let int2 = 10, 171 00:07:50,600 --> 00:07:52,700 and we'll make a call to the function in 172 00:07:52,701 --> 00:07:55,900 the code segment. I will also add a print 173 00:07:55,901 --> 00:07:57,300 statement to the code segment. 174 00:07:57,301 --> 00:08:00,500 [No Audio] 175 00:08:00,501 --> 00:08:02,900 Now, let us explain this program a bit. The two 176 00:08:02,901 --> 00:08:05,466 references pass to the greater than function 177 00:08:05,500 --> 00:08:07,500 have different lifetimes. 178 00:08:08,300 --> 00:08:11,900 That is, the variable int1 has a different lifetime 179 00:08:11,901 --> 00:08:14,800 than the variable int2, since int2 has a smaller 180 00:08:14,801 --> 00:08:17,466 lifetime, it becomes the concrete lifetime. 181 00:08:17,700 --> 00:08:20,266 This means that all the parameters that have 182 00:08:20,267 --> 00:08:22,500 'a written next to them should 183 00:08:22,501 --> 00:08:25,466 have a lifetime at least as long as int2. 184 00:08:25,467 --> 00:08:28,266 This also means that the variable result which 185 00:08:28,267 --> 00:08:31,500 stores the returned reference should be valid 186 00:08:31,501 --> 00:08:34,866 as long as int2 is valid. Therefore, if we 187 00:08:34,867 --> 00:08:37,299 use the variable result out of the scope of 188 00:08:37,300 --> 00:08:39,765 int2, we get a compilation error. For 189 00:08:39,766 --> 00:08:42,133 instance, if I move the same print statement 190 00:08:42,134 --> 00:08:44,166 to outside the code segment, I will get an error. 191 00:08:44,167 --> 00:08:47,600 [No Audio] 192 00:08:47,633 --> 00:08:49,566 You may note that, it is giving an error 193 00:08:49,567 --> 00:08:52,300 saying that, cannot find result in this scope 194 00:08:52,301 --> 00:08:53,766 Let me redo this. 195 00:08:53,767 --> 00:08:57,100 [No Audio] 196 00:08:57,133 --> 00:08:58,300 The point to note from this 197 00:08:58,301 --> 00:08:59,966 is that, when a lifetime is used in 198 00:08:59,967 --> 00:09:02,266 connection with multiple variables, so we 199 00:09:02,267 --> 00:09:04,333 need to pay special attention to the one that 200 00:09:04,334 --> 00:09:06,466 has the minimum lifetime, as it will become 201 00:09:06,467 --> 00:09:08,966 the concrete lifetime. Now let's look at 202 00:09:08,967 --> 00:09:11,400 another important point, that is 203 00:09:11,401 --> 00:09:13,033 in connection with structures. 204 00:09:14,300 --> 00:09:16,600 Consider the scenario where we have a structure 205 00:09:16,601 --> 00:09:18,633 that has a field which is a reference, 206 00:09:18,700 --> 00:09:20,100 let me define a struct. 207 00:09:20,133 --> 00:09:25,900 [No Audio] 208 00:09:25,901 --> 00:09:27,800 The name field, in this case, is a reference to 209 00:09:27,801 --> 00:09:30,000 a string slice. You may note that, the Rust 210 00:09:30,001 --> 00:09:32,100 compiler is already complaining about the 211 00:09:32,101 --> 00:09:35,733 missing lifetime specifier. The Rust basically 212 00:09:35,734 --> 00:09:38,100 wants that the reference to the field should 213 00:09:38,101 --> 00:09:41,433 live as long enough as the structure itself. Of 214 00:09:41,434 --> 00:09:43,100 course, we do not want to have a structure 215 00:09:43,101 --> 00:09:45,166 with reference field which is pointing to an 216 00:09:45,167 --> 00:09:48,133 invalid resource. To ensure this, we will need 217 00:09:48,134 --> 00:09:51,133 to specify the Rust the lifetime specifier, 218 00:09:51,134 --> 00:09:52,600 so let us add the lifetime 219 00:09:54,600 --> 00:09:57,833 Let us now use the structure. I will first define a variable 220 00:09:57,866 --> 00:10:00,700 called first_name initialized from my name. 221 00:10:00,701 --> 00:10:03,500 [No Audio] 222 00:10:03,501 --> 00:10:05,066 Next I will define an instance of the 223 00:10:05,067 --> 00:10:07,766 structure Person and we'll set its fields. 224 00:10:07,767 --> 00:10:13,500 [No Audio] 225 00:10:13,501 --> 00:10:15,300 I will next include a code segment and 226 00:10:15,301 --> 00:10:17,266 will declare a string variable inside it. 227 00:10:17,267 --> 00:10:23,100 [No Audio] 228 00:10:23,101 --> 00:10:25,133 Finally, I will update the name field to the 229 00:10:25,134 --> 00:10:27,300 reference of the last_name. 230 00:10:27,301 --> 00:10:31,033 [No Audio] 231 00:10:31,034 --> 00:10:32,900 Outside the code segment, I will access the 232 00:10:32,901 --> 00:10:34,933 fields of the structure in a print statement. 233 00:10:34,934 --> 00:10:39,000 [No Audio] 234 00:10:39,001 --> 00:10:41,266 The compiler is giving us an error message, 235 00:10:41,267 --> 00:10:43,300 saying that the variable last_name 236 00:10:43,301 --> 00:10:45,900 did not live long enough. This is because the 237 00:10:45,901 --> 00:10:48,300 requirement due to the lifetime specifier was 238 00:10:48,301 --> 00:10:50,333 that the field should live at least as long 239 00:10:50,334 --> 00:10:53,033 as the structure itself, but it did not live 240 00:10:53,034 --> 00:10:56,033 long enough and it becomes invalid at the end 241 00:10:56,034 --> 00:10:58,966 of the code segment. Please note that, if we 242 00:10:58,967 --> 00:11:02,200 remove the print statement the code will have no issues. 243 00:11:02,201 --> 00:11:06,000 [No Audio] 244 00:11:06,001 --> 00:11:07,500 This is because the structure is 245 00:11:07,501 --> 00:11:09,733 last modified in the same code block in which 246 00:11:09,734 --> 00:11:11,966 the variable last_name is defined. 247 00:11:12,766 --> 00:11:14,433 In other words, both the field and the 248 00:11:14,434 --> 00:11:18,000 structure has the same lifetime. Now, we will 249 00:11:18,001 --> 00:11:20,066 explain a last point which is related to the 250 00:11:20,067 --> 00:11:23,666 issue of using of references to the same variable. 251 00:11:24,700 --> 00:11:26,400 Let us write a simple program to 252 00:11:26,401 --> 00:11:28,266 illustrate this issue. I will declare a 253 00:11:28,267 --> 00:11:31,066 vector, and we'll initialize it from some values. 254 00:11:31,067 --> 00:11:37,200 [No Audio] 255 00:11:37,201 --> 00:11:39,533 I will next create a function which will use 256 00:11:39,534 --> 00:11:41,633 the vector by reference, there will be two 257 00:11:41,634 --> 00:11:43,433 vector references as inputs. 258 00:11:43,434 --> 00:11:48,800 [No Audio] 259 00:11:48,833 --> 00:11:50,766 The output will be a vector reference 260 00:11:50,767 --> 00:11:52,900 [No Audio] 261 00:11:52,933 --> 00:11:55,466 inside the body of the function, I will have a 262 00:11:55,467 --> 00:11:58,200 simple logic for determining the returning value. 263 00:11:58,201 --> 00:12:05,133 [No Audio] 264 00:12:05,134 --> 00:12:07,533 Let us now call this function, I will call it 265 00:12:07,534 --> 00:12:09,700 with the same some_vec as input, 266 00:12:09,701 --> 00:12:12,066 so I will write it twice as inputs. 267 00:12:12,067 --> 00:12:17,266 [No Audio] 268 00:12:17,267 --> 00:12:19,000 This means that, I am passing the same 269 00:12:19,001 --> 00:12:21,666 reference to the function but two types. 270 00:12:22,300 --> 00:12:25,200 As expected without the lifetime parameter, the 271 00:12:25,201 --> 00:12:27,100 Rust will complaint. You may note that, 272 00:12:27,101 --> 00:12:29,366 although we are passing the same vec, Rust 273 00:12:29,367 --> 00:12:31,900 will still complain as it is unable to know 274 00:12:32,100 --> 00:12:34,266 to which variable the output reference may 275 00:12:34,267 --> 00:12:36,700 corresponds to. Although we know that they 276 00:12:36,733 --> 00:12:39,433 are the same, but Rust is unable to detect it, 277 00:12:39,434 --> 00:12:41,966 and therefore it needs explicit information 278 00:12:41,967 --> 00:12:44,433 about lifetimes to avoid possible confusion. 279 00:12:45,266 --> 00:12:47,333 So let us add the lifetime parameters to the 280 00:12:47,334 --> 00:12:49,400 inputs and also with the output. 281 00:12:49,401 --> 00:12:53,133 [No Audio] 282 00:12:53,166 --> 00:12:55,766 Now the program will compile without an issue, let us 283 00:12:55,767 --> 00:12:57,233 cargo run to confirm. 284 00:12:57,234 --> 00:13:00,233 [No Audio] 285 00:13:00,234 --> 00:13:01,266 Okay, that brings us to 286 00:13:01,267 --> 00:13:03,033 the end of this tutorial. We have learned 287 00:13:03,066 --> 00:13:05,366 about the lifetimes and some issues 288 00:13:05,367 --> 00:13:08,066 while using the lifetimes. The special point 289 00:13:08,067 --> 00:13:09,900 to note is that, the lifetime will come into 290 00:13:09,901 --> 00:13:12,133 play, when we have functions that returns 291 00:13:12,134 --> 00:13:14,300 references, or when we have structures with a 292 00:13:14,301 --> 00:13:16,466 reference field. See you again and until next 293 00:13:16,467 --> 00:13:18,533 tutorial happy Rust programming. 294 00:13:18,534 --> 00:13:23,900 [No Audio]