]> git.lizzy.rs Git - rust.git/blob - src/librustc_error_codes/error_codes/E0716.md
Rollup merge of #62514 - stephaneyfx:box-ffi, r=nikomatsakis
[rust.git] / src / librustc_error_codes / error_codes / E0716.md
1 This error indicates that a temporary value is being dropped
2 while a borrow is still in active use.
3
4 Erroneous code example:
5
6 ```compile_fail,E0716
7 fn foo() -> i32 { 22 }
8 fn bar(x: &i32) -> &i32 { x }
9 let p = bar(&foo());
10          // ------ creates a temporary
11 let q = *p;
12 ```
13
14 Here, the expression `&foo()` is borrowing the expression
15 `foo()`. As `foo()` is a call to a function, and not the name of
16 a variable, this creates a **temporary** -- that temporary stores
17 the return value from `foo()` so that it can be borrowed.
18 You could imagine that `let p = bar(&foo());` is equivalent
19 to this:
20
21 ```compile_fail,E0597
22 # fn foo() -> i32 { 22 }
23 # fn bar(x: &i32) -> &i32 { x }
24 let p = {
25   let tmp = foo(); // the temporary
26   bar(&tmp)
27 }; // <-- tmp is freed as we exit this block
28 let q = p;
29 ```
30
31 Whenever a temporary is created, it is automatically dropped (freed)
32 according to fixed rules. Ordinarily, the temporary is dropped
33 at the end of the enclosing statement -- in this case, after the `let`.
34 This is illustrated in the example above by showing that `tmp` would
35 be freed as we exit the block.
36
37 To fix this problem, you need to create a local variable
38 to store the value in rather than relying on a temporary.
39 For example, you might change the original program to
40 the following:
41
42 ```
43 fn foo() -> i32 { 22 }
44 fn bar(x: &i32) -> &i32 { x }
45 let value = foo(); // dropped at the end of the enclosing block
46 let p = bar(&value);
47 let q = *p;
48 ```
49
50 By introducing the explicit `let value`, we allocate storage
51 that will last until the end of the enclosing block (when `value`
52 goes out of scope). When we borrow `&value`, we are borrowing a
53 local variable that already exists, and hence no temporary is created.
54
55 Temporaries are not always dropped at the end of the enclosing
56 statement. In simple cases where the `&` expression is immediately
57 stored into a variable, the compiler will automatically extend
58 the lifetime of the temporary until the end of the enclosing
59 block. Therefore, an alternative way to fix the original
60 program is to write `let tmp = &foo()` and not `let tmp = foo()`:
61
62 ```
63 fn foo() -> i32 { 22 }
64 fn bar(x: &i32) -> &i32 { x }
65 let value = &foo();
66 let p = bar(value);
67 let q = *p;
68 ```
69
70 Here, we are still borrowing `foo()`, but as the borrow is assigned
71 directly into a variable, the temporary will not be dropped until
72 the end of the enclosing block. Similar rules apply when temporaries
73 are stored into aggregate structures like a tuple or struct:
74
75 ```
76 // Here, two temporaries are created, but
77 // as they are stored directly into `value`,
78 // they are not dropped until the end of the
79 // enclosing block.
80 fn foo() -> i32 { 22 }
81 let value = (&foo(), &foo());
82 ```