Skip to content

Commit b3bd705

Browse files
committed
Auto merge of rust-lang#121346 - m-ou-se:temp-lifetime-if-else-match, r=compiler-errors
Propagate temporary lifetime extension into if and match. This PR makes this work: ```rust let a = if true { ..; &temp() // used to error, but now gets lifetime extended } else { ..; &temp() // used to error, but now gets lifetime extended }; ``` and ```rust let a = match () { _ => { ..; &temp() // used to error, but now gets lifetime extended } }; ``` to make it consistent with: ```rust let a = { ..; &temp() // lifetime is extended }; ``` This is one small part of [the temporary lifetimes work](rust-lang/lang-team#253). This part is backwards compatible (so doesn't need be edition-gated), because all code affected by this change previously resulted in a hard error.
2 parents c2239bc + f4caa83 commit b3bd705

File tree

4 files changed

+119
-115
lines changed

4 files changed

+119
-115
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

+13
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,8 @@ fn resolve_local<'tcx>(
689689
/// | [ ..., E&, ... ]
690690
/// | ( ..., E&, ... )
691691
/// | {...; E&}
692+
/// | if _ { ...; E& } else { ...; E& }
693+
/// | match _ { ..., _ => E&, ... }
692694
/// | box E&
693695
/// | E& as ...
694696
/// | ( E& )
@@ -727,6 +729,17 @@ fn resolve_local<'tcx>(
727729
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
728730
}
729731
}
732+
hir::ExprKind::If(_, then_block, else_block) => {
733+
record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id);
734+
if let Some(else_block) = else_block {
735+
record_rvalue_scope_if_borrow_expr(visitor, else_block, blk_id);
736+
}
737+
}
738+
hir::ExprKind::Match(_, arms, _) => {
739+
for arm in arms {
740+
record_rvalue_scope_if_borrow_expr(visitor, arm.body, blk_id);
741+
}
742+
}
730743
hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => {
731744
// FIXME(@dingxiangfei2009): choose call arguments here
732745
// for candidacy for extended parameter rule application

tests/ui/borrowck/let_underscore_temporary.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
77
*s += 1;
88
s
99
} else {
10-
&mut 0
11-
//~^ ERROR temporary value dropped while borrowed
10+
let a = 0;
11+
&a
12+
//~^ ERROR does not live long enough
1213
};
1314
let _ = if let Some(ref s) = num { s } else { &0 };
1415
let _ = if let Some(mut s) = num {
@@ -21,8 +22,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
2122
*s += 1;
2223
s
2324
} else {
24-
&mut 0
25-
//~^ ERROR temporary value dropped while borrowed
25+
let a = 0;
26+
&a
27+
//~^ ERROR does not live long enough
2628
};
2729
}
2830

@@ -33,8 +35,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
3335
*s += 1;
3436
s
3537
} else {
36-
&mut 0
37-
//~^ ERROR temporary value dropped while borrowed
38+
let a = 0;
39+
&a
40+
//~^ ERROR does not live long enough
3841
};
3942
let _: _ = if let Some(ref s) = num { s } else { &0 };
4043
let _: _ = if let Some(mut s) = num {
@@ -47,8 +50,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
4750
*s += 1;
4851
s
4952
} else {
50-
&mut 0
51-
//~^ ERROR temporary value dropped while borrowed
53+
let a = 0;
54+
&a
55+
//~^ ERROR does not live long enough
5256
};
5357
}
5458

@@ -63,8 +67,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
6367
*s += 1;
6468
s
6569
} else {
66-
&mut 0
67-
//~^ ERROR temporary value dropped while borrowed
70+
let a = 0;
71+
&a
72+
//~^ ERROR does not live long enough
6873
} {
6974
_ => {}
7075
};
@@ -83,8 +88,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
8388
*s += 1;
8489
s
8590
} else {
86-
&mut 0
87-
//~^ ERROR temporary value dropped while borrowed
91+
let a = 0;
92+
&a
93+
//~^ ERROR does not live long enough
8894
} {
8995
_ => {}
9096
};
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,69 @@
1-
error[E0716]: temporary value dropped while borrowed
2-
--> $DIR/let_underscore_temporary.rs:10:14
1+
error[E0597]: `a` does not live long enough
2+
--> $DIR/let_underscore_temporary.rs:11:9
33
|
4-
LL | let _ = if let Some(s) = &mut num {
5-
| _____________-
6-
LL | | *s += 1;
7-
LL | | s
8-
LL | | } else {
9-
LL | | &mut 0
10-
| | ^ creates a temporary value which is freed while still in use
11-
LL | |
12-
LL | | };
13-
| | -
14-
| | |
15-
| |_____temporary value is freed at the end of this statement
16-
| borrow later used here
17-
|
18-
= note: consider using a `let` binding to create a longer lived value
4+
LL | let a = 0;
5+
| - binding `a` declared here
6+
LL | &a
7+
| ^^ borrowed value does not live long enough
8+
LL |
9+
LL | };
10+
| - `a` dropped here while still borrowed
1911

20-
error[E0716]: temporary value dropped while borrowed
21-
--> $DIR/let_underscore_temporary.rs:24:14
22-
|
23-
LL | let _ = if let Some(ref mut s) = num {
24-
| _____________-
25-
LL | | *s += 1;
26-
LL | | s
27-
LL | | } else {
28-
LL | | &mut 0
29-
| | ^ creates a temporary value which is freed while still in use
30-
LL | |
31-
LL | | };
32-
| | -
33-
| | |
34-
| |_____temporary value is freed at the end of this statement
35-
| borrow later used here
12+
error[E0597]: `a` does not live long enough
13+
--> $DIR/let_underscore_temporary.rs:26:9
3614
|
37-
= note: consider using a `let` binding to create a longer lived value
15+
LL | let a = 0;
16+
| - binding `a` declared here
17+
LL | &a
18+
| ^^ borrowed value does not live long enough
19+
LL |
20+
LL | };
21+
| - `a` dropped here while still borrowed
3822

39-
error[E0716]: temporary value dropped while borrowed
40-
--> $DIR/let_underscore_temporary.rs:36:14
41-
|
42-
LL | let _: _ = if let Some(s) = &mut num {
43-
| ________________-
44-
LL | | *s += 1;
45-
LL | | s
46-
LL | | } else {
47-
LL | | &mut 0
48-
| | ^ creates a temporary value which is freed while still in use
49-
LL | |
50-
LL | | };
51-
| | -
52-
| | |
53-
| |_____temporary value is freed at the end of this statement
54-
| borrow later used here
23+
error[E0597]: `a` does not live long enough
24+
--> $DIR/let_underscore_temporary.rs:39:9
5525
|
56-
= note: consider using a `let` binding to create a longer lived value
26+
LL | let a = 0;
27+
| - binding `a` declared here
28+
LL | &a
29+
| ^^ borrowed value does not live long enough
30+
LL |
31+
LL | };
32+
| - `a` dropped here while still borrowed
5733

58-
error[E0716]: temporary value dropped while borrowed
59-
--> $DIR/let_underscore_temporary.rs:50:14
34+
error[E0597]: `a` does not live long enough
35+
--> $DIR/let_underscore_temporary.rs:54:9
6036
|
61-
LL | let _: _ = if let Some(ref mut s) = num {
62-
| ________________-
63-
LL | | *s += 1;
64-
LL | | s
65-
LL | | } else {
66-
LL | | &mut 0
67-
| | ^ creates a temporary value which is freed while still in use
68-
LL | |
69-
LL | | };
70-
| | -
71-
| | |
72-
| |_____temporary value is freed at the end of this statement
73-
| borrow later used here
74-
|
75-
= note: consider using a `let` binding to create a longer lived value
37+
LL | let a = 0;
38+
| - binding `a` declared here
39+
LL | &a
40+
| ^^ borrowed value does not live long enough
41+
LL |
42+
LL | };
43+
| - `a` dropped here while still borrowed
7644

77-
error[E0716]: temporary value dropped while borrowed
78-
--> $DIR/let_underscore_temporary.rs:66:14
79-
|
80-
LL | match if let Some(s) = &mut num {
81-
| ___________-
82-
LL | | *s += 1;
83-
LL | | s
84-
LL | | } else {
85-
LL | | &mut 0
86-
| | ^ creates a temporary value which is freed while still in use
87-
LL | |
88-
LL | | } {
89-
| | -
90-
| | |
91-
| |_____temporary value is freed at the end of this statement
92-
| borrow later used here
45+
error[E0597]: `a` does not live long enough
46+
--> $DIR/let_underscore_temporary.rs:71:9
9347
|
94-
= note: consider using a `let` binding to create a longer lived value
48+
LL | let a = 0;
49+
| - binding `a` declared here
50+
LL | &a
51+
| ^^ borrowed value does not live long enough
52+
LL |
53+
LL | } {
54+
| - `a` dropped here while still borrowed
9555

96-
error[E0716]: temporary value dropped while borrowed
97-
--> $DIR/let_underscore_temporary.rs:86:14
98-
|
99-
LL | match if let Some(ref mut s) = num {
100-
| ___________-
101-
LL | | *s += 1;
102-
LL | | s
103-
LL | | } else {
104-
LL | | &mut 0
105-
| | ^ creates a temporary value which is freed while still in use
106-
LL | |
107-
LL | | } {
108-
| | -
109-
| | |
110-
| |_____temporary value is freed at the end of this statement
111-
| borrow later used here
56+
error[E0597]: `a` does not live long enough
57+
--> $DIR/let_underscore_temporary.rs:92:9
11258
|
113-
= note: consider using a `let` binding to create a longer lived value
59+
LL | let a = 0;
60+
| - binding `a` declared here
61+
LL | &a
62+
| ^^ borrowed value does not live long enough
63+
LL |
64+
LL | } {
65+
| - `a` dropped here while still borrowed
11466

11567
error: aborting due to 6 previous errors
11668

117-
For more information about this error, try `rustc --explain E0716`.
69+
For more information about this error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ check-pass
2+
3+
fn temp() -> (String, i32) {
4+
(String::from("Hello"), 1)
5+
}
6+
7+
fn main() {
8+
let a = &temp();
9+
let b = [(&temp(),)];
10+
let c = &temp().0;
11+
let d = &temp().0[..];
12+
let e = {
13+
let _ = 123;
14+
&(*temp().0)[..]
15+
};
16+
let f = if true {
17+
&temp()
18+
} else {
19+
&temp()
20+
};
21+
let g = match true {
22+
true => &temp(),
23+
false => {
24+
let _ = 123;
25+
&temp()
26+
}
27+
};
28+
let h = match temp() {
29+
// The {} moves the value, making a new temporary.
30+
owned_non_temporary => &{ owned_non_temporary },
31+
};
32+
println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?} {h:?}");
33+
}

0 commit comments

Comments
 (0)