1 00:00:00,000 --> 00:00:08,533 [No Audio] 2 00:00:08,534 --> 00:00:10,966 Lifetimes are one of the most important yet 3 00:00:10,967 --> 00:00:13,133 probably one of the least understood topics 4 00:00:13,134 --> 00:00:15,300 in the Rust programming language. The 5 00:00:15,301 --> 00:00:17,400 Lifetimes explains the scope for which 6 00:00:17,433 --> 00:00:19,933 reference is being valid. Rust claims to be 7 00:00:19,934 --> 00:00:22,100 memory safe, and we have talked about that to 8 00:00:22,101 --> 00:00:24,700 some extent under the topic of ownership in Rust. 9 00:00:24,833 --> 00:00:26,900 The concept of Lifetimes in Rust is 10 00:00:26,901 --> 00:00:29,600 also part of memory safety feature. This will 11 00:00:29,601 --> 00:00:31,700 become more clear to us in this tutorial 12 00:00:31,701 --> 00:00:34,633 after covering what Lifetimes are, why do 13 00:00:34,634 --> 00:00:36,933 they exist, and when do we need them? 14 00:00:36,934 --> 00:00:40,200 So let's start learning about Lifetimes. Before 15 00:00:40,201 --> 00:00:42,233 starting, we will address the question 16 00:00:42,234 --> 00:00:43,833 of why we need Lifetimes. 17 00:00:44,600 --> 00:00:47,733 In fact, it will be better to highlight at this point that, 18 00:00:47,734 --> 00:00:49,833 in this particular tutorial we will be first 19 00:00:49,834 --> 00:00:52,300 explaining some of the problems that sets the 20 00:00:52,301 --> 00:00:54,833 motivation for the use of Lifetime specifier. 21 00:00:55,100 --> 00:00:56,700 And then in the next tutorial, we will be 22 00:00:56,701 --> 00:00:58,500 looking at the possible solution. 23 00:00:59,400 --> 00:01:01,833 Okay, let us come back to the basic question of 24 00:01:01,834 --> 00:01:05,099 why we need Lifetimes? To better answer this 25 00:01:05,100 --> 00:01:07,100 question, we will need to understand what are 26 00:01:07,101 --> 00:01:08,833 dangling references. 27 00:01:10,000 --> 00:01:11,200 When the references are 28 00:01:11,201 --> 00:01:13,400 being used to point to some variable or 29 00:01:13,401 --> 00:01:15,766 resource in memory, so there is always an 30 00:01:15,800 --> 00:01:18,133 owner of that resource or variable. 31 00:01:18,266 --> 00:01:20,200 The dangling reference is a reference which 32 00:01:20,201 --> 00:01:22,266 points to a resource, whose owner does not 33 00:01:22,267 --> 00:01:24,633 exist. In other words, when a program tries 34 00:01:24,634 --> 00:01:27,200 to access an invalid reference, it is known 35 00:01:27,201 --> 00:01:30,066 as a dangling reference. By invalid, we mean 36 00:01:30,067 --> 00:01:32,200 that the resource has been deallocated. 37 00:01:32,700 --> 00:01:35,933 Dangling reference is also sometimes called 38 00:01:35,934 --> 00:01:38,866 as a dangling pointer. Let us illustrate this 39 00:01:38,867 --> 00:01:41,200 with the help of an example. I will declare a 40 00:01:41,201 --> 00:01:43,633 variable which will hold a reference to an integer. 41 00:01:43,634 --> 00:01:50,100 [No Audio] 42 00:01:50,101 --> 00:01:52,166 Next, I will include a code segment. 43 00:01:53,400 --> 00:01:56,000 Inside the code segment I will declare a variable j, 44 00:01:56,001 --> 00:01:57,600 and we'll set its value. 45 00:01:57,601 --> 00:01:59,933 [No Audio] 46 00:01:59,934 --> 00:02:01,366 I will next set the 47 00:02:01,367 --> 00:02:03,633 variable i as a reference to the variable j. 48 00:02:04,433 --> 00:02:06,300 Outside the code segment, I will access the 49 00:02:06,301 --> 00:02:08,600 value of the variable i by printing its value. 50 00:02:08,601 --> 00:02:11,233 [No Audio] 51 00:02:11,234 --> 00:02:12,666 You may note that the compiler is 52 00:02:12,667 --> 00:02:15,600 complaining, it says j does not live long enough. 53 00:02:16,133 --> 00:02:17,933 Some of you might have already 54 00:02:17,934 --> 00:02:20,700 guessed what the problem is, but let us explain this. 55 00:02:22,033 --> 00:02:23,166 When we were explaining the 56 00:02:23,167 --> 00:02:25,400 ownership rules, we explained the concept of scope. 57 00:02:25,900 --> 00:02:28,800 The scope of a variable is the code 58 00:02:28,801 --> 00:02:30,933 segment in which it is defined. In 59 00:02:30,934 --> 00:02:33,233 this program, the scope of the variable i 60 00:02:33,234 --> 00:02:35,700 start from the first line of the program, and 61 00:02:35,701 --> 00:02:38,600 ends at the last statement of the program at 62 00:02:38,601 --> 00:02:40,400 this particular closing curly brackets. 63 00:02:41,000 --> 00:02:43,166 The variable j comes into scope inside the code 64 00:02:43,167 --> 00:02:45,300 segment at this line in which it is defined. 65 00:02:46,033 --> 00:02:48,133 The variable j goes out of scope when the 66 00:02:48,134 --> 00:02:50,066 ending curly brackets are encountered for the 67 00:02:50,067 --> 00:02:53,000 code segment. Outside the code segment, since 68 00:02:53,001 --> 00:02:55,733 the variable i is pointing or or referencing to 69 00:02:55,734 --> 00:02:58,100 a resource which does not exist, therefore 70 00:02:58,101 --> 00:03:01,100 the compiler is complaining. The variable i, 71 00:03:01,101 --> 00:03:02,900 in this case, is said to be a dangling 72 00:03:02,901 --> 00:03:04,966 reference, or a reference which is pointing to 73 00:03:04,967 --> 00:03:07,733 an invalid resource. The definition of 74 00:03:07,734 --> 00:03:10,233 Lifetime is now very easy to understand and 75 00:03:10,234 --> 00:03:14,100 comprehend. The Lifetime explains the scope 76 00:03:14,101 --> 00:03:17,100 for which a reference is valid. For instance, 77 00:03:17,101 --> 00:03:18,833 the Lifetime of the variable j in the 78 00:03:18,834 --> 00:03:21,066 above example starts from the line in which 79 00:03:21,067 --> 00:03:23,333 we initialize it, which is this particular 80 00:03:23,334 --> 00:03:26,333 line of code, and ends at ending curly 81 00:03:26,334 --> 00:03:28,933 brackets when the code segment ends. 82 00:03:29,800 --> 00:03:32,366 The Lifetime of all the variables end at the 83 00:03:32,367 --> 00:03:34,266 ending curly brackets where the main function 84 00:03:34,267 --> 00:03:37,000 ends. In summary, some variables may have 85 00:03:37,001 --> 00:03:39,166 longer Lifetimes and other may have shorter 86 00:03:39,167 --> 00:03:42,333 Lifetimes. A reference variable must live 87 00:03:42,334 --> 00:03:44,900 long enough and should have a longer lifetime 88 00:03:44,901 --> 00:03:47,533 enough for the duration in which it is being referenced. 89 00:03:48,833 --> 00:03:50,400 Dangling references are typically 90 00:03:50,401 --> 00:03:51,900 encountered, when we are dealing with 91 00:03:51,901 --> 00:03:55,600 functions. Let us see this using some suitable examples. 92 00:03:57,233 --> 00:03:59,466 I would start by declaring a variable. 93 00:03:59,467 --> 00:04:01,500 [No Audio] 94 00:04:01,501 --> 00:04:04,400 I will define a function called some_fn. 95 00:04:06,366 --> 00:04:08,700 This function will accept an integer input 96 00:04:08,701 --> 00:04:10,933 and will return a reference to an integer. 97 00:04:10,934 --> 00:04:15,100 [No Audio] 98 00:04:15,101 --> 00:04:16,933 Inside the body of the function, I will 99 00:04:16,934 --> 00:04:19,366 return a reference to the input variable i. 100 00:04:20,100 --> 00:04:21,700 I will use the same function in the main 101 00:04:21,701 --> 00:04:24,200 program and will assign it to a variable. 102 00:04:24,201 --> 00:04:28,266 [No Audio] 103 00:04:28,267 --> 00:04:30,900 Finally, I will, I will use a print statement 104 00:04:30,901 --> 00:04:34,066 for printing the value of additional_int variable. 105 00:04:34,067 --> 00:04:39,766 [No Audio] 106 00:04:39,767 --> 00:04:41,833 You may note that the compiler has already some 107 00:04:41,834 --> 00:04:44,700 useful information for us, it says missing 108 00:04:44,733 --> 00:04:47,966 lifetime specifier. We will explain the 109 00:04:47,967 --> 00:04:50,300 lifetime specifiers later on, but for now let 110 00:04:50,301 --> 00:04:53,600 us see what has gone wrong in this case. In 111 00:04:53,601 --> 00:04:55,466 the main program we have defined a variable 112 00:04:55,467 --> 00:04:58,500 of some_int, which is the owner of the value. 113 00:04:58,700 --> 00:05:00,100 In the second line of the code, we 114 00:05:00,101 --> 00:05:01,966 are calling the function with a variable of 115 00:05:01,967 --> 00:05:05,000 some_int. Since we are using the 116 00:05:05,001 --> 00:05:07,033 value and not the reference, so when the 117 00:05:07,034 --> 00:05:09,266 function is called and executed, it will take 118 00:05:09,267 --> 00:05:11,700 the ownership of the value. And now the owner 119 00:05:11,701 --> 00:05:14,800 is the variable i and not the variable of some_int. 120 00:05:15,533 --> 00:05:16,666 Inside the function, we 121 00:05:16,667 --> 00:05:18,600 are returning a reference to the variable i. 122 00:05:19,966 --> 00:05:22,200 Now have when the function ends, the variable 123 00:05:22,201 --> 00:05:24,833 i will be no more in scope, and in other 124 00:05:24,834 --> 00:05:27,866 words, its lifetime will end. So when we 125 00:05:27,867 --> 00:05:30,966 return back to the main function, that is 126 00:05:31,200 --> 00:05:33,366 that is to the second line of the code in 127 00:05:33,367 --> 00:05:35,333 the main function, the variable i will no 128 00:05:35,334 --> 00:05:37,933 more exist, because it was defined inside the 129 00:05:37,934 --> 00:05:39,900 function and its scope was limited to the 130 00:05:39,901 --> 00:05:42,833 body of the function, and is no more in scope. 131 00:05:43,033 --> 00:05:45,333 Therefore the variable of additional_int 132 00:05:45,334 --> 00:05:46,900 will be pointing to or 133 00:05:46,901 --> 00:05:49,600 referring to a resource which is invalid and 134 00:05:49,601 --> 00:05:52,400 does not exist. For this reason, it is known 135 00:05:52,401 --> 00:05:53,900 as a dangling reference. 136 00:05:54,000 --> 00:05:56,700 In this case, the variable i does not live long 137 00:05:56,701 --> 00:06:00,000 enough and its lifetime was being limited to the function. 138 00:06:00,533 --> 00:06:02,866 The solution in this case would be to use a 139 00:06:02,867 --> 00:06:04,766 reference in the function instead of the 140 00:06:04,767 --> 00:06:07,200 actual value. So let me use a reference in 141 00:06:07,201 --> 00:06:10,066 the function call, and also in the function definition. 142 00:06:10,166 --> 00:06:11,466 And now you may note that, the 143 00:06:11,467 --> 00:06:13,100 compiler is no more complaining. 144 00:06:14,533 --> 00:06:17,066 Before moving further, it is important to highlight 145 00:06:17,067 --> 00:06:19,000 it the Rust has a special module called the 146 00:06:19,001 --> 00:06:21,800 Borrow checker, which checks for the lifetime 147 00:06:21,801 --> 00:06:25,766 related issues. It is tasked with enforcing a 148 00:06:25,767 --> 00:06:28,533 number of properties related to the ownership and lifetime. 149 00:06:29,400 --> 00:06:30,933 In addition to dangling pointers, 150 00:06:30,934 --> 00:06:32,433 there is another issue or problem 151 00:06:32,434 --> 00:06:34,033 in connection with the lifetime called 152 00:06:34,066 --> 00:06:37,666 undetermined lifetimes. Let us learn about that also. 153 00:06:39,066 --> 00:06:40,700 The Rust compiler checks for the 154 00:06:40,701 --> 00:06:43,900 lifetimes related issue as issues at compile time. 155 00:06:43,901 --> 00:06:46,500 Sometimes it may happen that at compile 156 00:06:46,501 --> 00:06:48,833 time, the Llifetime of a variable may not be known. 157 00:06:49,200 --> 00:06:51,133 Let us see how this can happen. 158 00:06:52,000 --> 00:06:53,700 I will define a couple of variables. 159 00:06:53,701 --> 00:06:59,800 [No Audio] 160 00:06:59,801 --> 00:07:02,033 Next I will write a function called greater, 161 00:07:02,066 --> 00:07:03,900 which is going to return a reference to the 162 00:07:03,901 --> 00:07:05,366 greater of the two values. 163 00:07:05,367 --> 00:07:15,900 [No Audio] 164 00:07:15,901 --> 00:07:17,566 Inside the body of the function, I will 165 00:07:17,567 --> 00:07:20,100 compare the two values and will return the 166 00:07:20,101 --> 00:07:21,733 greater, let me add the code. 167 00:07:21,734 --> 00:07:28,200 [No Audio] 168 00:07:28,201 --> 00:07:30,300 In this case now, a reference to a value which 169 00:07:30,301 --> 00:07:31,800 is greater will be returned from the 170 00:07:31,801 --> 00:07:33,900 function. Please note that in this case, we 171 00:07:33,901 --> 00:07:36,066 do not have a dangling pointer or reference, 172 00:07:36,067 --> 00:07:37,766 because we are passing the value to the 173 00:07:37,767 --> 00:07:39,966 function by references, which means that the 174 00:07:39,967 --> 00:07:42,066 ownership of the values does not change, and 175 00:07:42,067 --> 00:07:43,633 therefore the two variables in the main 176 00:07:43,634 --> 00:07:46,066 function are valid. However, the Rust 177 00:07:46,067 --> 00:07:48,866 compiler is still complaining, it says missing 178 00:07:48,867 --> 00:07:51,666 lifetime specifier. The reason for this is 179 00:07:51,667 --> 00:07:53,833 that the Rust is confused in this case, as to 180 00:07:53,834 --> 00:07:56,266 which Lifetime the returning reference may be 181 00:07:56,267 --> 00:07:58,933 corresponding to, the actual reference cannot 182 00:07:58,934 --> 00:08:01,500 be determined at compile time and can only be 183 00:08:01,501 --> 00:08:03,833 determined during the execution time, 184 00:08:03,834 --> 00:08:06,333 Because it depends on the if statement condition. 185 00:08:06,334 --> 00:08:09,066 This scenario is referred to as undetermined 186 00:08:09,067 --> 00:08:12,800 lifetime case. Let us look at another example 187 00:08:12,801 --> 00:08:15,333 of the same issue to better understand the concepts. 188 00:08:16,633 --> 00:08:18,233 I will use strings in this example 189 00:08:18,234 --> 00:08:20,633 now, I will declare a string variable with the 190 00:08:20,634 --> 00:08:21,900 value of Hello. 191 00:08:21,901 --> 00:08:25,066 [No Audio] 192 00:08:25,067 --> 00:08:26,400 Next inside the code segment, 193 00:08:26,401 --> 00:08:28,200 I will declare another string variable with 194 00:08:28,201 --> 00:08:29,366 the value of World. 195 00:08:29,367 --> 00:08:34,866 [No Audio] 196 00:08:34,867 --> 00:08:36,765 I will include a function now, which will take 197 00:08:36,766 --> 00:08:39,400 two string slices as an input, and will return 198 00:08:39,401 --> 00:08:41,066 the first slice as an output. 199 00:08:41,067 --> 00:08:48,966 [No Audio] 200 00:08:48,967 --> 00:08:53,233 Inside the body of the function, we will write first_str. 201 00:08:53,234 --> 00:08:57,933 [No Audio] 202 00:08:57,934 --> 00:09:00,300 In the code segment, I will call the function and we'll 203 00:09:00,301 --> 00:09:02,000 assign it to some variable. 204 00:09:02,001 --> 00:09:08,533 [No Audio] 205 00:09:08,566 --> 00:09:11,233 I will declare the same variable v before the 206 00:09:11,234 --> 00:09:14,633 start of the code segment. Outside the code 207 00:09:14,634 --> 00:09:17,200 segment, I will use the variable v in a print statement. 208 00:09:17,201 --> 00:09:23,433 [No Audio] 209 00:09:23,434 --> 00:09:26,333 You may note that the compiler has issues, again 210 00:09:26,334 --> 00:09:28,166 please note that we do not have dangling 211 00:09:28,167 --> 00:09:30,300 pointers in this case. The variable v is 212 00:09:30,301 --> 00:09:32,766 pointing to the variable s1, which has the 213 00:09:32,767 --> 00:09:36,966 scope of the entire main function. Let us inspect the error. 214 00:09:38,233 --> 00:09:41,300 It says expected named lifetime parameter. 215 00:09:41,301 --> 00:09:42,900 Moreover, it says that 216 00:09:42,901 --> 00:09:45,600 this function returns type, contains a 217 00:09:45,601 --> 00:09:48,066 borrowed value, but the signature does not 218 00:09:48,067 --> 00:09:50,900 say whether it is borrowed from first_str 219 00:09:50,901 --> 00:09:53,100 or second_str, 220 00:09:53,800 --> 00:09:56,600 this leads to the issue of undetermined lifetime. 221 00:09:57,500 --> 00:09:59,533 The compiler needs to explicitly 222 00:09:59,534 --> 00:10:01,466 know in this case to, which one of the two 223 00:10:01,467 --> 00:10:03,133 variables the returning variable should 224 00:10:03,134 --> 00:10:06,300 correspond to, as it is unable to reduce it 225 00:10:06,301 --> 00:10:08,233 at its own in this case. 226 00:10:09,166 --> 00:10:10,166 Okay, that brings us 227 00:10:10,167 --> 00:10:12,100 to the end of this tutorial, we have covered 228 00:10:12,101 --> 00:10:14,566 two important issues called a dangling 229 00:10:14,567 --> 00:10:17,000 pointers or references and undetermined 230 00:10:17,001 --> 00:10:19,133 lifetimes. In the next tutorial, we will be 231 00:10:19,134 --> 00:10:21,466 looking at the concept of Lifetime specifier, 232 00:10:21,700 --> 00:10:23,866 which will enable us to design solutions for 233 00:10:23,867 --> 00:10:26,066 these issues. Do come back to cover that and 234 00:10:26,067 --> 00:10:28,833 until next tutorial, happy Rust programming. 235 00:10:28,834 --> 00:10:35,000 [No Audio]