]> git.lizzy.rs Git - rust.git/blob - src/doc/nomicon/dropck.md
Change error message in rustbook
[rust.git] / src / doc / nomicon / dropck.md
1 % Drop Check
2
3 We have seen how lifetimes provide us some fairly simple rules for ensuring
4 that we never read dangling references. However up to this point we have only ever
5 interacted with the *outlives* relationship in an inclusive manner. That is,
6 when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
7 `'b`. At first glance, this seems to be a meaningless distinction. Nothing ever
8 gets dropped at the same time as another, right? This is why we used the
9 following desugarring of `let` statements:
10
11 ```rust,ignore
12 let x;
13 let y;
14 ```
15
16 ```rust,ignore
17 {
18     let x;
19     {
20         let y;
21     }
22 }
23 ```
24
25 Each creates its own scope, clearly establishing that one drops before the
26 other. However, what if we do the following?
27
28 ```rust,ignore
29 let (x, y) = (vec![], vec![]);
30 ```
31
32 Does either value strictly outlive the other? The answer is in fact *no*,
33 neither value strictly outlives the other. Of course, one of x or y will be
34 dropped before the other, but the actual order is not specified. Tuples aren't
35 special in this regard; composite structures just don't guarantee their
36 destruction order as of Rust 1.0.
37
38 We *could* specify this for the fields of built-in composites like tuples and
39 structs. However, what about something like Vec? Vec has to manually drop its
40 elements via pure-library code. In general, anything that implements Drop has
41 a chance to fiddle with its innards during its final death knell. Therefore
42 the compiler can't sufficiently reason about the actual destruction order
43 of the contents of any type that implements Drop.
44
45 So why do we care? We care because if the type system isn't careful, it could
46 accidentally make dangling pointers. Consider the following simple program:
47
48 ```rust
49 struct Inspector<'a>(&'a u8);
50
51 fn main() {
52     let (inspector, days);
53     days = Box::new(1);
54     inspector = Inspector(&days);
55 }
56 ```
57
58 This program is totally sound and compiles today. The fact that `days` does
59 not *strictly* outlive `inspector` doesn't matter. As long as the `inspector`
60 is alive, so is days.
61
62 However if we add a destructor, the program will no longer compile!
63
64 ```rust,ignore
65 struct Inspector<'a>(&'a u8);
66
67 impl<'a> Drop for Inspector<'a> {
68     fn drop(&mut self) {
69         println!("I was only {} days from retirement!", self.0);
70     }
71 }
72
73 fn main() {
74     let (inspector, days);
75     days = Box::new(1);
76     inspector = Inspector(&days);
77     // Let's say `days` happens to get dropped first.
78     // Then when Inspector is dropped, it will try to read free'd memory!
79 }
80 ```
81
82 ```text
83 <anon>:12:28: 12:32 error: `days` does not live long enough
84 <anon>:12     inspector = Inspector(&days);
85                                      ^~~~
86 <anon>:9:11: 15:2 note: reference must be valid for the block at 9:10...
87 <anon>:9 fn main() {
88 <anon>:10     let (inspector, days);
89 <anon>:11     days = Box::new(1);
90 <anon>:12     inspector = Inspector(&days);
91 <anon>:13     // Let's say `days` happens to get dropped first.
92 <anon>:14     // Then when Inspector is dropped, it will try to read free'd memory!
93           ...
94 <anon>:10:27: 15:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 10:26
95 <anon>:10     let (inspector, days);
96 <anon>:11     days = Box::new(1);
97 <anon>:12     inspector = Inspector(&days);
98 <anon>:13     // Let's say `days` happens to get dropped first.
99 <anon>:14     // Then when Inspector is dropped, it will try to read free'd memory!
100 <anon>:15 }
101 ```
102
103 Implementing Drop lets the Inspector execute some arbitrary code during its
104 death. This means it can potentially observe that types that are supposed to
105 live as long as it does actually were destroyed first.
106
107 Interestingly, only generic types need to worry about this. If they aren't
108 generic, then the only lifetimes they can harbor are `'static`, which will truly
109 live *forever*. This is why this problem is referred to as *sound generic drop*.
110 Sound generic drop is enforced by the *drop checker*. As of this writing, some
111 of the finer details of how the drop checker validates types is totally up in
112 the air. However The Big Rule is the subtlety that we have focused on this whole
113 section:
114
115 **For a generic type to soundly implement drop, its generics arguments must
116 strictly outlive it.**
117
118 Obeying this rule is (usually) necessary to satisfy the borrow
119 checker; obeying it is sufficient but not necessary to be
120 sound. That is, if your type obeys this rule then it's definitely
121 sound to drop.
122
123 The reason that it is not always necessary to satisfy the above rule
124 is that some Drop implementations will not access borrowed data even
125 though their type gives them the capability for such access.
126
127 For example, this variant of the above `Inspector` example will never
128 accessed borrowed data:
129
130 ```rust,ignore
131 struct Inspector<'a>(&'a u8, &'static str);
132
133 impl<'a> Drop for Inspector<'a> {
134     fn drop(&mut self) {
135         println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
136     }
137 }
138
139 fn main() {
140     let (inspector, days);
141     days = Box::new(1);
142     inspector = Inspector(&days, "gadget");
143     // Let's say `days` happens to get dropped first.
144     // Even when Inspector is dropped, its destructor will not access the
145     // borrowed `days`.
146 }
147 ```
148
149 Likewise, this variant will also never access borrowed data:
150
151 ```rust,ignore
152 use std::fmt;
153
154 struct Inspector<T: fmt::Display>(T, &'static str);
155
156 impl<T: fmt::Display> Drop for Inspector<T> {
157     fn drop(&mut self) {
158         println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
159     }
160 }
161
162 fn main() {
163     let (inspector, days): (Inspector<&u8>, Box<u8>);
164     days = Box::new(1);
165     inspector = Inspector(&days, "gadget");
166     // Let's say `days` happens to get dropped first.
167     // Even when Inspector is dropped, its destructor will not access the
168     // borrowed `days`.
169 }
170 ```
171
172 However, *both* of the above variants are rejected by the borrow
173 checker during the analysis of `fn main`, saying that `days` does not
174 live long enough.
175
176 The reason is that the borrow checking analysis of `main` does not
177 know about the internals of each Inspector's Drop implementation.  As
178 far as the borrow checker knows while it is analyzing `main`, the body
179 of an inspector's destructor might access that borrowed data.
180
181 Therefore, the drop checker forces all borrowed data in a value to
182 strictly outlive that value.
183
184 # An Escape Hatch
185
186 The precise rules that govern drop checking may be less restrictive in
187 the future.
188
189 The current analysis is deliberately conservative and trivial; it forces all
190 borrowed data in a value to outlive that value, which is certainly sound.
191
192 Future versions of the language may make the analysis more precise, to
193 reduce the number of cases where sound code is rejected as unsafe.
194 This would help address cases such as the two Inspectors above that
195 know not to inspect during destruction.
196
197 In the meantime, there is an unstable attribute that one can use to
198 assert (unsafely) that a generic type's destructor is *guaranteed* to
199 not access any expired data, even if its type gives it the capability
200 to do so.
201
202 That attribute is called `unsafe_destructor_blind_to_params`.
203 To deploy it on the Inspector example from above, we would write:
204
205 ```rust,ignore
206 struct Inspector<'a>(&'a u8, &'static str);
207
208 impl<'a> Drop for Inspector<'a> {
209     #[unsafe_destructor_blind_to_params]
210     fn drop(&mut self) {
211         println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
212     }
213 }
214 ```
215
216 This attribute has the word `unsafe` in it because the compiler is not
217 checking the implicit assertion that no potentially expired data
218 (e.g. `self.0` above) is accessed.
219
220 It is sometimes obvious that no such access can occur, like the case above.
221 However, when dealing with a generic type parameter, such access can
222 occur indirectly. Examples of such indirect access are:
223  * invoking a callback,
224  * via a trait method call.
225
226 (Future changes to the language, such as impl specialization, may add
227 other avenues for such indirect access.)
228
229 Here is an example of invoking a callback:
230
231 ```rust,ignore
232 struct Inspector<T>(T, &'static str, Box<for <'r> fn(&'r T) -> String>);
233
234 impl<T> Drop for Inspector<T> {
235     fn drop(&mut self) {
236         // The `self.2` call could access a borrow e.g. if `T` is `&'a _`.
237         println!("Inspector({}, {}) unwittingly inspects expired data.",
238                  (self.2)(&self.0), self.1);
239     }
240 }
241 ```
242
243 Here is an example of a trait method call:
244
245 ```rust,ignore
246 use std::fmt;
247
248 struct Inspector<T: fmt::Display>(T, &'static str);
249
250 impl<T: fmt::Display> Drop for Inspector<T> {
251     fn drop(&mut self) {
252         // There is a hidden call to `<T as Display>::fmt` below, which
253         // could access a borrow e.g. if `T` is `&'a _`
254         println!("Inspector({}, {}) unwittingly inspects expired data.",
255                  self.0, self.1);
256     }
257 }
258 ```
259
260 And of course, all of these accesses could be further hidden within
261 some other method invoked by the destructor, rather than being written
262 directly within it.
263
264 In all of the above cases where the `&'a u8` is accessed in the
265 destructor, adding the `#[unsafe_destructor_blind_to_params]`
266 attribute makes the type vulnerable to misuse that the borrower
267 checker will not catch, inviting havoc. It is better to avoid adding
268 the attribute.
269
270 # Is that all about drop checker?
271
272 It turns out that when writing unsafe code, we generally don't need to
273 worry at all about doing the right thing for the drop checker. However there
274 is one special case that you need to worry about, which we will look at in
275 the next section.
276