@@ -2241,7 +2241,92 @@ that after `demo` finishes excuting, something else (such as the
2241
2241
destructor!) could access `s.data` after the end of that shorter
2242
2242
lifetime, which would again violate the `&mut`-borrow's exclusive
2243
2243
access.
2244
+ "## ,
2245
+
2246
+ E0714 : r##"
2247
+ This error indicates that a temporary value is being dropped
2248
+ while a borrow is still in active use.
2249
+
2250
+ Erroneous code example:
2251
+
2252
+ ```compile_fail,E0714
2253
+ # #![feature(nll)]
2254
+ fn foo() -> i32 { 22 }
2255
+ fn bar(x: &i32) -> &i32 { x }
2256
+ let p = bar(&foo());
2257
+ // ------ creates a temporary
2258
+ let q = *p;
2259
+ ```
2260
+
2261
+ Here, the expression `&foo()` is borrowing the expression
2262
+ `foo()`. As `foo()` is call to a function, and not the name of
2263
+ a variable, this creates a **temporary** -- that temporary stores
2264
+ the return value from `foo()` so that it can be borrowed.
2265
+ So you might imagine that `let p = bar(&foo())` is equivalent
2266
+ to this:
2267
+
2268
+ ```compile_fail,E0597
2269
+ # fn foo() -> i32 { 22 }
2270
+ # fn bar(x: &i32) -> &i32 { x }
2271
+ let p = {
2272
+ let tmp = foo(); // the temporary
2273
+ bar(&tmp)
2274
+ }; // <-- tmp is freed as we exit this block
2275
+ let q = p;
2276
+ ```
2277
+
2278
+ Whenever a temporary is created, it is automatically dropped (freed)
2279
+ according to fixed rules. Ordinarily, the temporary is dropped
2280
+ at the end of the enclosing statement -- in this case, after the `let`.
2281
+ This is illustrated in the example above by showing that `tmp` would
2282
+ be freed as we exit the block.
2283
+
2284
+ To fix this problem, you need to create a local variable
2285
+ to store the value in rather than relying on a temporary.
2286
+ For example, you might change the original program to
2287
+ the following:
2244
2288
2289
+ ```
2290
+ fn foo() -> i32 { 22 }
2291
+ fn bar(x: &i32) -> &i32 { x }
2292
+ let value = foo(); // dropped at the end of the enclosing block
2293
+ let p = bar(&value);
2294
+ let q = *p;
2295
+ ```
2296
+
2297
+ By introducing the explicit `let value`, we allocate storage
2298
+ that will last until the end of the enclosing block (when `value`
2299
+ goes out of scope). When we borrow `&value`, we are borrowing a
2300
+ local variable that already exists, and hence no temporary is created.
2301
+
2302
+ Temporaries are not always dropped at the end of the enclosing
2303
+ statement. In simple cases where the `&` expression is immediately
2304
+ stored into a variable, the compiler will automatically extend
2305
+ the lifetime of the temporary until the end of the enclosinb
2306
+ block. Therefore, an alternative way to fix the original
2307
+ program is to write `let tmp = &foo()` and not `let tmp = foo()`:
2308
+
2309
+ ```
2310
+ fn foo() -> i32 { 22 }
2311
+ fn bar(x: &i32) -> &i32 { x }
2312
+ let value = &foo();
2313
+ let p = bar(value);
2314
+ let q = *p;
2315
+ ```
2316
+
2317
+ Here, we are still borrowing `foo()`, but as the borrow is assigned
2318
+ directly into a variable, the temporary will not be dropped until
2319
+ the end of the enclosing block. Similar rules apply when temporaries
2320
+ are stored into aggregate structures like a tuple or struct:
2321
+
2322
+ ```
2323
+ // Here, two temporaries are created, but
2324
+ // as they are stored directly into `value`,
2325
+ // they are not dropped until the end of the
2326
+ // enclosing block.
2327
+ fn foo() -> i32 { 22 }
2328
+ let value = (&foo(), &foo());
2329
+ ```
2245
2330
"## ,
2246
2331
2247
2332
}
0 commit comments