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