@@ -121,17 +121,19 @@ every expression, block, and pattern (patterns are considered to
121
121
"execute" by testing the value they are applied to and creating any
122
122
relevant bindings). So, for example:
123
123
124
- fn foo(x: isize, y: isize) { // -+
125
- // +------------+ // |
126
- // | +-----+ // |
127
- // | +-+ +-+ +-+ // |
128
- // | | | | | | | // |
129
- // v v v v v v v // |
130
- let z = x + y; // |
131
- ... // |
132
- } // -+
133
-
134
- fn bar() { ... }
124
+ ``` rust
125
+ fn foo (x : isize , y : isize ) { // -+
126
+ // +------------+ // |
127
+ // | +-----+ // |
128
+ // | +-+ +-+ +-+ // |
129
+ // | | | | | | | // |
130
+ // v v v v v v v // |
131
+ let z = x + y ; // |
132
+ ... // |
133
+ } // -+
134
+
135
+ fn bar () { ... }
136
+ ```
135
137
136
138
In this example, there is a region for the fn body block as a whole,
137
139
and then a subregion for the declaration of the local variable.
@@ -160,28 +162,32 @@ this, we get a lot of spurious errors around nested calls, in
160
162
particular when combined with ` &mut ` functions. For example, a call
161
163
like this one
162
164
163
- self.foo(self.bar())
165
+ ``` rust
166
+ self . foo (self . bar ())
167
+ ```
164
168
165
169
where both ` foo ` and ` bar ` are ` &mut self ` functions will always yield
166
170
an error.
167
171
168
172
Here is a more involved example (which is safe) so we can see what's
169
173
going on:
170
174
171
- struct Foo { f: usize, g: usize }
172
- ...
173
- fn add(p: &mut usize, v: usize) {
174
- *p += v;
175
- }
176
- ...
177
- fn inc(p: &mut usize) -> usize {
178
- *p += 1; *p
179
- }
180
- fn weird() {
181
- let mut x: Box<Foo> = box Foo { ... };
182
- 'a: add(&mut (*x).f,
183
- 'b: inc(&mut (*x).f)) // (..)
184
- }
175
+ ``` rust
176
+ struct Foo { f : usize , g : usize }
177
+ // ...
178
+ fn add (p : & mut usize , v : usize ) {
179
+ * p += v ;
180
+ }
181
+ // ...
182
+ fn inc (p : & mut usize ) -> usize {
183
+ * p += 1 ; * p
184
+ }
185
+ fn weird () {
186
+ let mut x : Box <Foo > = box Foo { /* ... */ };
187
+ 'a : add (& mut (* x ). f,
188
+ 'b : inc (& mut (* x ). f)) // (..)
189
+ }
190
+ ```
185
191
186
192
The important part is the line marked ` (..) ` which contains a call to
187
193
` add() ` . The first argument is a mutable borrow of the field ` f ` . The
@@ -197,16 +203,18 @@ can see that this error is unnecessary. Let's examine the lifetimes
197
203
involved with ` 'a ` in detail. We'll break apart all the steps involved
198
204
in a call expression:
199
205
200
- 'a: {
201
- 'a_arg1: let a_temp1: ... = add;
202
- 'a_arg2: let a_temp2: &'a mut usize = &'a mut (*x).f;
203
- 'a_arg3: let a_temp3: usize = {
204
- let b_temp1: ... = inc;
205
- let b_temp2: &'b = &'b mut (*x).f;
206
- 'b_call: b_temp1(b_temp2)
207
- };
208
- 'a_call: a_temp1(a_temp2, a_temp3) // (**)
209
- }
206
+ ``` rust
207
+ 'a : {
208
+ 'a_arg1 : let a_temp1 : ... = add ;
209
+ 'a_arg2 : let a_temp2 : & 'a mut usize = & 'a mut (* x ). f;
210
+ 'a_arg3 : let a_temp3 : usize = {
211
+ let b_temp1 : ... = inc ;
212
+ let b_temp2 : & 'b = & 'b mut (* x ). f;
213
+ 'b_call : b_temp1 (b_temp2 )
214
+ };
215
+ 'a_call : a_temp1 (a_temp2 , a_temp3 ) // (**)
216
+ }
217
+ ```
210
218
211
219
Here we see that the lifetime ` 'a ` includes a number of substatements.
212
220
In particular, there is this lifetime I've called ` 'a_call ` that
@@ -225,19 +233,21 @@ it will not be *dereferenced* during the evaluation of the second
225
233
argument, it can still be * invalidated* by that evaluation. Consider
226
234
this similar but unsound example:
227
235
228
- struct Foo { f: usize, g: usize }
229
- ...
230
- fn add(p: &mut usize, v: usize) {
231
- *p += v;
232
- }
233
- ...
234
- fn consume(x: Box<Foo>) -> usize {
235
- x.f + x.g
236
- }
237
- fn weird() {
238
- let mut x: Box<Foo> = box Foo { ... };
239
- 'a: add(&mut (*x).f, consume(x)) // (..)
240
- }
236
+ ``` rust
237
+ struct Foo { f : usize , g : usize }
238
+ // ...
239
+ fn add (p : & mut usize , v : usize ) {
240
+ * p += v ;
241
+ }
242
+ // ...
243
+ fn consume (x : Box <Foo >) -> usize {
244
+ x . f + x . g
245
+ }
246
+ fn weird () {
247
+ let mut x : Box <Foo > = box Foo { ... };
248
+ 'a : add (& mut (* x ). f, consume (x )) // (..)
249
+ }
250
+ ```
241
251
242
252
In this case, the second argument to ` add ` actually consumes ` x ` , thus
243
253
invalidating the first argument.
0 commit comments