1
00:00:00,040 --> 00:00:00,859
Welcome to module
2
00:00:00,860 --> 00:00:03,630
7, Lifetime parameters are descriptive,
3
00:00:03,640 --> 00:00:04,740
not prescriptive.
4
00:00:06,340 --> 00:00:13,150
In this module, we'll clear up some common misconceptions about lifetime parameters by explaining what the title of this module means.
5
00:00:13,640 --> 00:00:20,050
We'll talk about what lifetime parameters do in terms of describing and what they don't do in terms of prescribing.
6
00:00:21,140 --> 00:00:25,150
We'll discuss the special 'static lifetime and what it does and doesn't do.
7
00:00:26,240 --> 00:00:31,150
And we'll wrap up with some questions to consider when you're getting compiler errors related to lifetimes.
8
00:00:32,740 --> 00:00:36,340
Let's start with what we mean by lifetime parameters being descriptive.
9
00:00:37,940 --> 00:00:46,450
Lifetime parameters are descriptive in the sense that we programmers use them to describe to the compiler how the lifetimes of references are related.
10
00:00:47,970 --> 00:00:49,539
The generic lifetime parameters
11
00:00:49,540 --> 00:00:50,470
we specify
12
00:00:50,480 --> 00:00:52,469
get filled in with concrete lifetimes
13
00:00:52,470 --> 00:00:53,750
when our code is used.
14
00:00:54,340 --> 00:00:59,650
The lifetime parameters don't have any control over or knowledge of what those concrete lifetimes will be.
15
00:01:00,240 --> 00:01:03,339
We're only able to say when there are concrete lifetimes,
16
00:01:03,340 --> 00:01:04,850
they will have this relationship.
17
00:01:06,440 --> 00:01:11,040
So, now, let's talk about what we mean by lifetime parameters not being prescriptive.
18
00:01:12,640 --> 00:01:18,050
Lifetime parameters don't prescribe, by which we mean they don't order code to behave a certain way.
19
00:01:18,600 --> 00:01:23,400
They don't specify how long a concrete lifetime of a value or a reference must be.
20
00:01:24,440 --> 00:01:28,450
They don't change the concrete lifetimes of values or references.
21
00:01:29,490 --> 00:01:31,640
Lifetime parameters aren't setting lifetimes,
22
00:01:31,650 --> 00:01:35,050
assigning lifetimes, or forcing lifetimes to be a certain length.
23
00:01:36,110 --> 00:01:41,390
And adding lifetime parameters won't make a reference live long enough to be valid for that code.
24
00:01:42,940 --> 00:01:44,040
Let's take another look
25
00:01:44,050 --> 00:01:44,789
at an example
26
00:01:44,790 --> 00:01:50,179
from the module on visualizing lifetimes to understand borrow checker errors, where we tried to return,
27
00:01:50,180 --> 00:01:52,550
a reference from the return_first_two function.
28
00:01:53,540 --> 00:02:00,159
The reference being returned points to the list vector created within the function. When we looked at the lifetimes
29
00:02:00,160 --> 00:02:00,870
previously,
30
00:02:01,090 --> 00:02:04,879
we saw list goes out of scope and gets cleaned up at the end of the
31
00:02:04,880 --> 00:02:05,930
return_first_two function.
32
00:02:07,020 --> 00:02:11,430
The return reference is invalid because it outlives the value it's pointing to.
33
00:02:13,020 --> 00:02:14,220
When we compiled this code,
34
00:02:14,230 --> 00:02:15,610
we get an error that says,
35
00:02:15,620 --> 00:02:24,630
missinglifetime specifier. Now that we've covered what lifetime specifiers are, let's try adding a lifetime specifier to see what happens.
36
00:02:26,180 --> 00:02:31,930
The error message we get with Rust 1.24.1 says that the borrowed value does not live long enough.
37
00:02:32,520 --> 00:02:40,030
Adding the lifetime specifier has not changed the list value's lifetime to make it live long enough for us to return a reference to it out of the function.
38
00:02:41,020 --> 00:02:54,030
This error message has been improved in newer versions of Rust. With Rust 1.35, the compiler says that we cannot return a value referencing local variable list in the return value reference's data owned by the current function.
39
00:02:54,620 --> 00:02:58,330
This error message is more specific about the root cause of the problem.
40
00:02:59,920 --> 00:03:00,530
Next,
41
00:03:00,740 --> 00:03:04,730
let's go back to the error message we got when we didn't have any lifetime parameters.
42
00:03:05,720 --> 00:03:06,929
The error message had some help
43
00:03:06,930 --> 00:03:07,770
text that said
44
00:03:07,950 --> 00:03:10,230
consider giving it a 'static lifetime.
45
00:03:11,820 --> 00:03:12,850
Before we try that,
46
00:03:12,860 --> 00:03:15,130
let's talk about what the 'static lifetime even is.
47
00:03:16,720 --> 00:03:18,760
The 'static lifetime is a concrete lifetime -
48
00:03:18,830 --> 00:03:26,830
the only concrete lifetime you can specify in code. The 'static lifetime is for references that are valid the entire time your program is running.
49
00:03:27,820 --> 00:03:30,960
It's named static because it's similar to static variables,
50
00:03:30,970 --> 00:03:33,130
which are also valid for the entire program.
51
00:03:34,120 --> 00:03:38,820
You can get a reference with the 'static lifetime by taking a reference to static variables,
52
00:03:39,110 --> 00:03:40,830
constants, or literals.
53
00:03:42,370 --> 00:03:46,530
Let's return to our code and try adding the 'static lifetime to the return reference.
54
00:03:47,120 --> 00:03:50,630
We don't need to declare it because 'static is built into Rust.
55
00:03:51,660 --> 00:03:53,689
This gives us the same borrowed value
56
00:03:53,690 --> 00:03:58,520
does not live long enough error we got when we used 'a. Again,
57
00:03:58,570 --> 00:04:02,340
because lifetimes don't force values or references to live longer,
58
00:04:02,349 --> 00:04:06,799
adding 'static doesn't make list live for the entire runtime of the program.
59
00:04:08,289 --> 00:04:11,708
Using the 'static lifetime would work if the value we reference is,
60
00:04:11,709 --> 00:04:12,569
for example,
61
00:04:12,579 --> 00:04:14,699
a static array instead of a vector.
62
00:04:16,189 --> 00:04:21,269
This code compiles and runs successfully because the static variable is valid anywhere in the program,
63
00:04:21,489 --> 00:04:25,199
so a reference to the static variable is also valid anywhere in the program.
64
00:04:26,749 --> 00:04:36,999
Rust suggests that we use the 'static lifetime in the return_first_two function because it's actually the only lifetime that could work for a function returning a reference that has no references in its parameters.
65
00:04:38,089 --> 00:04:40,859
There's nothing for the return reference to be related to,
66
00:04:40,869 --> 00:04:44,659
so it must be referencing a value that exists at any time in the program.
67
00:04:46,189 --> 00:04:46,829
Finally,
68
00:04:46,969 --> 00:04:55,329
let's talk about some questions that will hopefully help you fix errors having to do with lifetime parameters.
69
00:04:55,339 --> 00:04:57,319
When you see the error message, "Borrowed value does not live long enough,"
70
00:04:57,519 --> 00:04:58,188
it's natural to
71
00:04:58,189 --> 00:05:05,489
ask, "How can I make this borrow live long enough?" and try to use lifetime parameters to do that. As we've discussed,
72
00:05:05,499 --> 00:05:07,419
that's not what lifetime parameters do.
73
00:05:07,429 --> 00:05:12,959
No amount of adding or rearranging lifetime parameters will extend any concrete lifetimes of values.
74
00:05:13,989 --> 00:05:17,599
Here are some more useful questions to ask yourself in this situation.
75
00:05:18,689 --> 00:05:21,599
Look at the definition containing lifetime parameters.
76
00:05:22,189 --> 00:05:25,588
What are the actual reference relationships in the implementation
77
00:05:25,589 --> 00:05:26,319
you're writing?
78
00:05:26,499 --> 00:05:30,899
And do the generic parameters accurately communicate that relationship to the compiler?
79
00:05:31,989 --> 00:05:32,639
Next,
80
00:05:32,789 --> 00:05:34,899
look at where you use that definition.
81
00:05:35,389 --> 00:05:39,438
What are the concrete lifetimes? Where might there be an invalid
82
00:05:39,439 --> 00:05:41,799
reference because of a value getting cleaned up?
83
00:05:42,329 --> 00:05:43,299
In other words,
84
00:05:43,309 --> 00:05:46,499
where is the use-after-free problem the compiler is preventing?
85
00:05:47,589 --> 00:05:50,459
Then, think about how to rearrange the definition,
86
00:05:50,469 --> 00:05:54,199
the lifetime parameters, or the usage, so that they're all consistent with each other.
87
00:05:55,249 --> 00:05:56,369
And if you're still stuck,
88
00:05:56,379 --> 00:05:58,699
consider if references are right for your case.
89
00:05:59,259 --> 00:06:02,559
Some lifetime problems happen because there's data without an owner,
90
00:06:02,798 --> 00:06:04,818
so using references will never work.
91
00:06:05,388 --> 00:06:06,268
Other times,
92
00:06:06,298 --> 00:06:08,248
cloning data can get the code working,
93
00:06:08,428 --> 00:06:16,358
and then you can profile to see if there are performance problems that justify figuring out how to use references.
94
00:06:16,368 --> 00:06:20,318
In this module, we discussed that lifetime parameters describe relationships between references.
95
00:06:21,408 --> 00:06:25,608
Lifetime parameters don't prescribe how long values or references live.
96
00:06:26,708 --> 00:06:30,958
The 'static lifetime is for references that will be valid at any point in the program.
97
00:06:30,968 --> 00:06:38,768
But specifying 'static won't make a value live that long if it doesn't already.
98
00:06:38,778 --> 00:06:43,218
Given these properties of lifetime parameters, we talked about questions that will hopefully help next time you're getting errors about lifetimes.
99
00:06:44,808 --> 00:06:45,458
Next,
100
00:06:45,488 --> 00:06:47,118
we'll cover lifetime elision.