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