Skip to content

Commit 0b2eae7

Browse files
committed
Auto merge of #54164 - mikhail-m1:54131, r=pnkfelix
add "temporary value borrowed for too long" error Issue #54131 r? @nikomatsakis
2 parents 92aff72 + 2af199d commit 0b2eae7

File tree

60 files changed

+852
-192
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+852
-192
lines changed

src/librustc_mir/borrow_check/error_reporting.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -694,9 +694,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
694694

695695
let tcx = self.infcx.tcx;
696696
let mut err =
697-
tcx.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
698-
err.span_label(proper_span, "temporary value does not live long enough");
699-
err.span_label(drop_span, "temporary value only lives until here");
697+
tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir);
698+
err.span_label(proper_span, "creates a temporary which is freed while still in use");
699+
err.span_label(drop_span, "temporary value is freed at the end of this statement");
700700

701701
let explanation = self.explain_why_borrow_contains_point(context, borrow, None);
702702
match explanation {

src/librustc_mir/diagnostics.rs

+85
Original file line numberDiff line numberDiff line change
@@ -2261,7 +2261,92 @@ that after `demo` finishes excuting, something else (such as the
22612261
destructor!) could access `s.data` after the end of that shorter
22622262
lifetime, which would again violate the `&mut`-borrow's exclusive
22632263
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:
22642308
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+
```
22652350
"##,
22662351

22672352
}

src/librustc_mir/util/borrowck_errors.rs

+16
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,22 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
730730

731731
self.cancel_if_wrong_origin(err, o)
732732
}
733+
734+
fn temporary_value_borrowed_for_too_long(
735+
self,
736+
span: Span,
737+
o: Origin,
738+
) -> DiagnosticBuilder<'cx> {
739+
let err = struct_span_err!(
740+
self,
741+
span,
742+
E0716,
743+
"temporary value dropped while borrowed{OGN}",
744+
OGN = o
745+
);
746+
747+
self.cancel_if_wrong_origin(err, o)
748+
}
733749
}
734750

735751
impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/borrowck-borrow-from-temporary.rs:19:24
3+
|
4+
LL | let &Foo(ref x) = &id(Foo(3)); //~ ERROR borrowed value does not live long enough
5+
| ^^^^^^^^^^ creates a temporary which is freed while still in use
6+
LL | x
7+
LL | }
8+
| - temporary value is freed at the end of this statement
9+
|
10+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 18:8...
11+
--> $DIR/borrowck-borrow-from-temporary.rs:18:8
12+
|
13+
LL | fn foo<'a>() -> &'a isize {
14+
| ^^
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0597]: borrowed value does not live long enough
1+
error[E0716]: temporary value dropped while borrowed
22
--> $DIR/borrowck-borrowed-uniq-rvalue-2.rs:32:20
33
|
44
LL | let x = defer(&vec!["Goodbye", "world!"]);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value only lives until here
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
66
| |
7-
| temporary value does not live long enough
7+
| creates a temporary which is freed while still in use
88
LL | x.x[0];
99
| ------ borrow later used here
1010
|
@@ -13,4 +13,4 @@ LL | x.x[0];
1313

1414
error: aborting due to previous error
1515

16-
For more information about this error, try `rustc --explain E0597`.
16+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0597]: borrowed value does not live long enough
1+
error[E0716]: temporary value dropped while borrowed
22
--> $DIR/borrowck-borrowed-uniq-rvalue.rs:20:28
33
|
44
LL | buggy_map.insert(42, &*Box::new(1)); //~ ERROR borrowed value does not live long enough
5-
| ^^^^^^^^^^^ - temporary value only lives until here
5+
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
66
| |
7-
| temporary value does not live long enough
7+
| creates a temporary which is freed while still in use
88
...
99
LL | buggy_map.insert(43, &*tmp);
1010
| --------- borrow later used here
@@ -13,4 +13,4 @@ LL | buggy_map.insert(43, &*tmp);
1313

1414
error: aborting due to previous error
1515

16-
For more information about this error, try `rustc --explain E0597`.
16+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,57 @@
1-
error[E0597]: borrowed value does not live long enough
1+
error[E0716]: temporary value dropped while borrowed
22
--> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:21
33
|
44
LL | let ref mut x = 1234543; //~ ERROR
5-
| ^^^^^^^ temporary value does not live long enough
5+
| ^^^^^^^ creates a temporary which is freed while still in use
66
LL | x
77
LL | }
8-
| - temporary value only lives until here
8+
| - temporary value is freed at the end of this statement
99
|
1010
= note: borrowed value must be valid for the static lifetime...
1111

12-
error[E0597]: borrowed value does not live long enough
12+
error[E0716]: temporary value dropped while borrowed
1313
--> $DIR/promote-ref-mut-in-let-issue-46557.rs:20:25
1414
|
1515
LL | let (ref mut x, ) = (1234543, ); //~ ERROR
16-
| ^^^^^^^^^^^ temporary value does not live long enough
16+
| ^^^^^^^^^^^ creates a temporary which is freed while still in use
1717
LL | x
1818
LL | }
19-
| - temporary value only lives until here
19+
| - temporary value is freed at the end of this statement
2020
|
2121
= note: borrowed value must be valid for the static lifetime...
2222

23-
error[E0597]: borrowed value does not live long enough
23+
error[E0716]: temporary value dropped while borrowed
2424
--> $DIR/promote-ref-mut-in-let-issue-46557.rs:25:11
2525
|
2626
LL | match 1234543 {
27-
| ^^^^^^^ temporary value does not live long enough
27+
| ^^^^^^^ creates a temporary which is freed while still in use
2828
...
2929
LL | }
30-
| - temporary value only lives until here
30+
| - temporary value is freed at the end of this statement
3131
|
3232
= note: borrowed value must be valid for the static lifetime...
3333

34-
error[E0597]: borrowed value does not live long enough
34+
error[E0716]: temporary value dropped while borrowed
3535
--> $DIR/promote-ref-mut-in-let-issue-46557.rs:31:11
3636
|
3737
LL | match (123443,) {
38-
| ^^^^^^^^^ temporary value does not live long enough
38+
| ^^^^^^^^^ creates a temporary which is freed while still in use
3939
...
4040
LL | }
41-
| - temporary value only lives until here
41+
| - temporary value is freed at the end of this statement
4242
|
4343
= note: borrowed value must be valid for the static lifetime...
4444

45-
error[E0597]: borrowed value does not live long enough
45+
error[E0716]: temporary value dropped while borrowed
4646
--> $DIR/promote-ref-mut-in-let-issue-46557.rs:37:10
4747
|
4848
LL | &mut 1234543 //~ ERROR
49-
| ^^^^^^^ temporary value does not live long enough
49+
| ^^^^^^^ creates a temporary which is freed while still in use
5050
LL | }
51-
| - temporary value only lives until here
51+
| - temporary value is freed at the end of this statement
5252
|
5353
= note: borrowed value must be valid for the static lifetime...
5454

5555
error: aborting due to 5 previous errors
5656

57-
For more information about this error, try `rustc --explain E0597`.
57+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: `foo` is not yet stable as a const fn
2+
--> $DIR/dont_promote_unstable_const_fn.rs:25:25
3+
|
4+
LL | const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
5+
| ^^^^^
6+
|
7+
= help: in Nightly builds, add `#![feature(foo)]` to the crate attributes to enable
8+
9+
error[E0716]: temporary value dropped while borrowed
10+
--> $DIR/dont_promote_unstable_const_fn.rs:28:28
11+
|
12+
LL | let _: &'static u32 = &foo(); //~ ERROR does not live long enough
13+
| ^^^^^ creates a temporary which is freed while still in use
14+
LL | }
15+
| - temporary value is freed at the end of this statement
16+
|
17+
= note: borrowed value must be valid for the static lifetime...
18+
19+
error[E0716]: temporary value dropped while borrowed
20+
--> $DIR/dont_promote_unstable_const_fn.rs:32:28
21+
|
22+
LL | let _: &'static u32 = &meh(); //~ ERROR does not live long enough
23+
| ^^^^^ creates a temporary which is freed while still in use
24+
...
25+
LL | }
26+
| - temporary value is freed at the end of this statement
27+
|
28+
= note: borrowed value must be valid for the static lifetime...
29+
30+
error[E0716]: temporary value dropped while borrowed
31+
--> $DIR/dont_promote_unstable_const_fn.rs:33:26
32+
|
33+
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
34+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
35+
LL | //~^ does not live long enough
36+
LL | }
37+
| - temporary value is freed at the end of this statement
38+
|
39+
= note: borrowed value must be valid for the static lifetime...
40+
41+
error: aborting due to 4 previous errors
42+
43+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:18:28
3+
|
4+
LL | let _: &'static u32 = &foo(); //~ ERROR does not live long enough
5+
| ^^^^^ creates a temporary which is freed while still in use
6+
LL | let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
7+
LL | }
8+
| - temporary value is freed at the end of this statement
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0716]: temporary value dropped while borrowed
13+
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:19:29
14+
|
15+
LL | let _x: &'static u32 = &foo(); //~ ERROR does not live long enough
16+
| ^^^^^ creates a temporary which is freed while still in use
17+
LL | }
18+
| - temporary value is freed at the end of this statement
19+
|
20+
= note: borrowed value must be valid for the static lifetime...
21+
22+
error: aborting due to 2 previous errors
23+
24+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/promoted_raw_ptr_ops.rs:14:29
3+
|
4+
LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
6+
...
7+
LL | }
8+
| - temporary value is freed at the end of this statement
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error[E0716]: temporary value dropped while borrowed
13+
--> $DIR/promoted_raw_ptr_ops.rs:16:30
14+
|
15+
LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
17+
LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
18+
LL | }
19+
| - temporary value is freed at the end of this statement
20+
|
21+
= note: borrowed value must be valid for the static lifetime...
22+
23+
error[E0716]: temporary value dropped while borrowed
24+
--> $DIR/promoted_raw_ptr_ops.rs:17:28
25+
|
26+
LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
28+
LL | }
29+
| - temporary value is freed at the end of this statement
30+
|
31+
= note: borrowed value must be valid for the static lifetime...
32+
33+
error: aborting due to 3 previous errors
34+
35+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/transmute-const-promotion.rs:16:37
3+
|
4+
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
6+
LL | //~^ ERROR value does not live long enough
7+
LL | }
8+
| - temporary value is freed at the end of this statement
9+
|
10+
= note: borrowed value must be valid for the static lifetime...
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0716`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/union_promotion.rs:19:29
3+
|
4+
LL | let x: &'static bool = &unsafe { //~ borrowed value does not live long enough
5+
| _____________________________^
6+
LL | | Foo { a: &1 }.b == Foo { a: &2 }.b
7+
LL | | };
8+
| |_____^ creates a temporary which is freed while still in use
9+
LL | }
10+
| - temporary value is freed at the end of this statement
11+
|
12+
= note: borrowed value must be valid for the static lifetime...
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0716`.

0 commit comments

Comments
 (0)