1 00:00:00,040 --> 00:00:00,920 Welcome to module 2 00:00:00,930 --> 00:00:01,330 8 on 3 00:00:01,460 --> 00:00:05,310 lifetime elision. In this module, 4 00:00:05,320 --> 00:00:07,710 we'll define what lifetime elision means. 5 00:00:08,740 --> 00:00:13,750 We'll go through the three rules the compiler uses to figure out what any alighted lifetimes are. 6 00:00:14,840 --> 00:00:19,190 And we'll review some examples from previous modules that involve lifetime elision, 7 00:00:19,250 --> 00:00:20,850 which we glossed over at the time. 8 00:00:22,340 --> 00:00:25,650 Let's get started by talking about what lifetime elision is. 9 00:00:27,240 --> 00:00:31,750 Elision is a relatively uncommon English word that means omitting or leaving out. 10 00:00:32,340 --> 00:00:35,200 Lifetime elision is a concept unique to Rust. 11 00:00:35,740 --> 00:00:42,800 It's a set of rules programmed into the compiler that were added so that you don't have to add generic lifetime parameters on every reference. 12 00:00:43,840 --> 00:00:48,250 The people who worked on Rust noticed that there were many common patterns for using lifetimes. 13 00:00:48,770 --> 00:00:53,419 They coded rules into the compiler to apply default generic lifetime parameters to use 14 00:00:53,420 --> 00:00:54,450 in these cases. 15 00:00:55,540 --> 00:00:59,500 These rules only take into account the signatures of functions and methods. 16 00:01:00,110 --> 00:01:03,050 The bodies don't have any influence over lifetime elision. 17 00:01:04,640 --> 00:01:05,100 If, 18 00:01:05,150 --> 00:01:06,480 after applying the rules, 19 00:01:06,490 --> 00:01:10,550 Rust still can't figure out the lifetime parameters for all of the references in the signature, 20 00:01:10,780 --> 00:01:17,470 you'll get a compiler error that says you need to add lifetime parameters. 21 00:01:17,510 --> 00:01:20,850 If you want to do something other than the defaults, you can add lifetime parameters to specify a different relationship. 22 00:01:21,940 --> 00:01:23,820 If you want to annotate lifetimes, 23 00:01:23,830 --> 00:01:26,680 even in cases where lifetime elision would let you leave them out, 24 00:01:26,800 --> 00:01:29,950 feel free, even though this isn't idiomatic Rust. 25 00:01:31,540 --> 00:01:32,190 Next, 26 00:01:32,240 --> 00:01:34,850 let's look at what the three lifetime elision rules are. 27 00:01:36,440 --> 00:01:41,550 The first rule says that each parameter that's a reference is considered to have its own lifetime parameter. 28 00:01:42,640 --> 00:01:43,380 For example, 29 00:01:43,390 --> 00:01:45,720 if we enter this function that has three parameters, 30 00:01:45,730 --> 00:01:57,920 the compiler interprets the first two parameters that are references as having their own lifetime annotations, shown here as 'a and 'b. The second rule says that if there's only one lifetime in the parameters, 31 00:01:57,990 --> 00:02:00,050 a return reference gets that lifetime. 32 00:02:01,140 --> 00:02:01,950 For example, 33 00:02:01,960 --> 00:02:04,820 if we enter this function that has one reference parameter, 34 00:02:05,030 --> 00:02:08,050 the first rule says that the reference gets its own lifetime, 35 00:02:08,330 --> 00:02:11,450 and the second rule says the return reference gets that lifetime as well. 36 00:02:13,040 --> 00:02:18,580 This is because any other association would be invalid unless the return type's lifetime is 'static, 37 00:02:18,660 --> 00:02:20,530 as we discussed in the previous module, 38 00:02:20,760 --> 00:02:22,350 which we would need to add manually. 39 00:02:23,440 --> 00:02:29,640 The third rule only applies to methods. It gives return types the same lifetime as the self parameter, 40 00:02:29,880 --> 00:02:32,550 even if there are other parameters with different lifetimes. 41 00:02:33,580 --> 00:02:34,480 For example, 42 00:02:34,550 --> 00:02:37,650 in this get_value method implemented on a Config struct, 43 00:02:38,040 --> 00:02:43,150 the compiler would use the first rule to assign different lifetimes to the self and key parameters. 44 00:02:44,140 --> 00:02:49,330 Then, the third rule tells the compiler to assume the return string slice has the same lifetime itself, 45 00:02:49,340 --> 00:02:51,050 which would be 'a here. 46 00:02:52,070 --> 00:02:54,569 This is because it's very common for methods to return 47 00:02:54,570 --> 00:02:56,150 a reference to a part of self. 48 00:02:57,680 --> 00:02:59,610 Now that we've covered all three rules, 49 00:02:59,700 --> 00:03:04,450 let's re-examine the three examples that demonstrated the rules to see if those examples would compile. 50 00:03:06,040 --> 00:03:07,660 In the first example we looked at, 51 00:03:07,670 --> 00:03:10,310 neither the second nor the third rules apply. 52 00:03:10,890 --> 00:03:13,360 The return reference still doesn't have a lifetime, 53 00:03:13,380 --> 00:03:16,750 so we'd get a compiler error saying we need to add lifetime parameters. 54 00:03:17,840 --> 00:03:19,060 In the second example, 55 00:03:19,150 --> 00:03:20,820 after applying the second rule, 56 00:03:20,960 --> 00:03:23,290 all references in the signature have a lifetime. 57 00:03:23,570 --> 00:03:28,050 So, this example would compile successfully as long as the body aligns with the assumed relationship. 58 00:03:29,140 --> 00:03:29,980 Similarly, 59 00:03:30,110 --> 00:03:34,950 the third example also has lifetimes for all the references and compilation can continue. 60 00:03:36,540 --> 00:03:37,100 Finally, 61 00:03:37,110 --> 00:03:45,340 let's look at some examples from previous modules to see how lifetime elision affects them. 62 00:03:45,350 --> 00:03:54,440 Way back in the module on concrete lifetimes, we introduced this example with the return_first_two function that has a reference as a parameter and returns a reference. In the module introducing generic lifetimes, 63 00:03:54,450 --> 00:03:57,190 we said that the return_first_two has a generic lifetime, 64 00:03:57,200 --> 00:03:59,650 which we represented with an orange dotted line. 65 00:04:00,640 --> 00:04:09,800 We didn't look at this example in the module where we learned the syntax for adding generic lifetime parameters because it doesn't need any. Because of the second lifetime elision rule, 66 00:04:09,820 --> 00:04:12,850 the return reference gets the same lifetime as the one parameter and this code compiles. 67 00:04:12,880 --> 00:04:18,240 In the module on generic lifetime parameters, 68 00:04:18,350 --> 00:04:19,959 we looked at an example with the Stemmer 69 00:04:19,960 --> 00:04:22,050 struct that has this stem method. 70 00:04:23,040 --> 00:04:25,380 When we compiled this without any lifetimes, 71 00:04:25,390 --> 00:04:26,259 we got an error 72 00:04:26,260 --> 00:04:26,920 that said, 73 00:04:27,230 --> 00:04:30,450 this parameter and the return type are declared with different lifetimes.... 74 00:04:31,480 --> 00:04:33,790 You may have been wondering why the compiler said that, 75 00:04:33,870 --> 00:04:37,550 seeing as how the method doesn't appear to contain any declared lifetimes. 76 00:04:38,080 --> 00:04:41,550 Lifetime elision is why the compiler thinks that there are lifetimes here. 77 00:04:42,640 --> 00:04:46,140 The first rule gives self and word separate lifetimes. 78 00:04:46,310 --> 00:04:52,150 And the third rule assumes that the lifetime of the return type was the same as the lifetime of self - 'a here. 79 00:04:52,840 --> 00:04:58,450 When the compiler proceeded to verifying that the references were valid according to the specified lifetime relationships, 80 00:04:58,760 --> 00:05:02,660 it sees that the implementation doesn't align with the lifetimes it assumes from elision 81 00:05:02,730 --> 00:05:03,720 and we get an error. 82 00:05:04,740 --> 00:05:11,930 We fixed this error by associating the return reference's lifetime with the word parameter instead. And, again, because of lifetime elision, 83 00:05:11,940 --> 00:05:14,850 we didn't need to add a lifetime for the self parameter. 84 00:05:15,440 --> 00:05:18,750 The first elision rule will assume it's a different lifetime than word. 85 00:05:19,340 --> 00:05:21,160 So, when we fixed this example earlier, 86 00:05:21,170 --> 00:05:26,150 we only specified one lifetime parameter. In this module, 87 00:05:26,160 --> 00:05:30,439 we discussed how lifetime elision is a feature that lets us leave out generic lifetime parameters 88 00:05:30,440 --> 00:05:31,650 in common cases. 89 00:05:32,640 --> 00:05:37,150 We covered the three rules the compiler uses to figure out lifetimes when they're omitted. 90 00:05:37,740 --> 00:05:40,120 Each reference parameter gets its own lifetime. 91 00:05:40,370 --> 00:05:42,060 If there's one parameter lifetime, 92 00:05:42,070 --> 00:05:45,240 a return reference gets that lifetime, and with methods, 93 00:05:45,250 --> 00:05:48,150 a return reference gets the lifetime of the self parameter. 94 00:05:49,390 --> 00:05:56,950 And we looked at some cases where lifetime elision lets us leave some generic lifetime parameters out, in the return_first_two function and the stem method. 95 00:05:57,980 --> 00:05:59,020 Congratulations! 96 00:05:59,030 --> 00:06:01,149 You've made it to the end of the Rust in Motion video 97 00:06:01,150 --> 00:06:01,800 course. 98 00:06:03,340 --> 00:06:08,079 Now would be a great time to write some Rust code by doing some programming practice problems like rustlings 99 00:06:08,080 --> 00:06:12,699 or exercism, or working on a project like writing a command-line utility. Happy 100 00:06:12,700 --> 00:06:13,260 Rusting!