Auto merge of #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](https://github.com/rust-lang/lang-team/issues/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.
This commit is contained in:
commit
b3bd7058c1
@ -689,6 +689,8 @@ fn resolve_local<'tcx>(
|
||||
/// | [ ..., E&, ... ]
|
||||
/// | ( ..., E&, ... )
|
||||
/// | {...; E&}
|
||||
/// | if _ { ...; E& } else { ...; E& }
|
||||
/// | match _ { ..., _ => E&, ... }
|
||||
/// | box E&
|
||||
/// | E& as ...
|
||||
/// | ( E& )
|
||||
@ -727,6 +729,17 @@ fn resolve_local<'tcx>(
|
||||
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
|
||||
}
|
||||
}
|
||||
hir::ExprKind::If(_, then_block, else_block) => {
|
||||
record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id);
|
||||
if let Some(else_block) = else_block {
|
||||
record_rvalue_scope_if_borrow_expr(visitor, else_block, blk_id);
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Match(_, arms, _) => {
|
||||
for arm in arms {
|
||||
record_rvalue_scope_if_borrow_expr(visitor, arm.body, blk_id);
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => {
|
||||
// FIXME(@dingxiangfei2009): choose call arguments here
|
||||
// for candidacy for extended parameter rule application
|
||||
|
@ -7,8 +7,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
};
|
||||
let _ = if let Some(ref s) = num { s } else { &0 };
|
||||
let _ = if let Some(mut s) = num {
|
||||
@ -21,8 +22,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
};
|
||||
}
|
||||
|
||||
@ -33,8 +35,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
};
|
||||
let _: _ = if let Some(ref s) = num { s } else { &0 };
|
||||
let _: _ = if let Some(mut s) = num {
|
||||
@ -47,8 +50,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
};
|
||||
}
|
||||
|
||||
@ -63,8 +67,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
} {
|
||||
_ => {}
|
||||
};
|
||||
@ -83,8 +88,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
|
||||
*s += 1;
|
||||
s
|
||||
} else {
|
||||
&mut 0
|
||||
//~^ ERROR temporary value dropped while borrowed
|
||||
let a = 0;
|
||||
&a
|
||||
//~^ ERROR does not live long enough
|
||||
} {
|
||||
_ => {}
|
||||
};
|
||||
|
@ -1,117 +1,69 @@
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:10:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:11:9
|
||||
|
|
||||
LL | let _ = if let Some(s) = &mut num {
|
||||
| _____________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | };
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | };
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:24:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:26:9
|
||||
|
|
||||
LL | let _ = if let Some(ref mut s) = num {
|
||||
| _____________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | };
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | };
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:36:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:39:9
|
||||
|
|
||||
LL | let _: _ = if let Some(s) = &mut num {
|
||||
| ________________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | };
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | };
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:50:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:54:9
|
||||
|
|
||||
LL | let _: _ = if let Some(ref mut s) = num {
|
||||
| ________________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | };
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | };
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:66:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:71:9
|
||||
|
|
||||
LL | match if let Some(s) = &mut num {
|
||||
| ___________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | } {
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | } {
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/let_underscore_temporary.rs:86:14
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/let_underscore_temporary.rs:92:9
|
||||
|
|
||||
LL | match if let Some(ref mut s) = num {
|
||||
| ___________-
|
||||
LL | | *s += 1;
|
||||
LL | | s
|
||||
LL | | } else {
|
||||
LL | | &mut 0
|
||||
| | ^ creates a temporary value which is freed while still in use
|
||||
LL | |
|
||||
LL | | } {
|
||||
| | -
|
||||
| | |
|
||||
| |_____temporary value is freed at the end of this statement
|
||||
| borrow later used here
|
||||
|
|
||||
= note: consider using a `let` binding to create a longer lived value
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | &a
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL |
|
||||
LL | } {
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
33
tests/ui/lifetimes/temporary-lifetime-extension.rs
Normal file
33
tests/ui/lifetimes/temporary-lifetime-extension.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//@ check-pass
|
||||
|
||||
fn temp() -> (String, i32) {
|
||||
(String::from("Hello"), 1)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &temp();
|
||||
let b = [(&temp(),)];
|
||||
let c = &temp().0;
|
||||
let d = &temp().0[..];
|
||||
let e = {
|
||||
let _ = 123;
|
||||
&(*temp().0)[..]
|
||||
};
|
||||
let f = if true {
|
||||
&temp()
|
||||
} else {
|
||||
&temp()
|
||||
};
|
||||
let g = match true {
|
||||
true => &temp(),
|
||||
false => {
|
||||
let _ = 123;
|
||||
&temp()
|
||||
}
|
||||
};
|
||||
let h = match temp() {
|
||||
// The {} moves the value, making a new temporary.
|
||||
owned_non_temporary => &{ owned_non_temporary },
|
||||
};
|
||||
println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?} {h:?}");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user