diff options
| author | bors <bors@rust-lang.org> | 2024-04-10 18:52:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-10 18:52:51 +0000 |
| commit | b3bd7058c139e71bae0862ef8f8ac936208873e9 (patch) | |
| tree | b74588beab0654ccb6c6c343427929f434bf681f | |
| parent | c2239bca5b89a8d3573cc0fc0f2fa65c50edb79c (diff) | |
| parent | f4caa832dad4482ec1fa85bdbc3156c83cc948de (diff) | |
| download | rust-b3bd7058c139e71bae0862ef8f8ac936208873e9.tar.gz rust-b3bd7058c139e71bae0862ef8f8ac936208873e9.zip | |
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.
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/region.rs | 13 | ||||
| -rw-r--r-- | tests/ui/borrowck/let_underscore_temporary.rs | 30 | ||||
| -rw-r--r-- | tests/ui/borrowck/let_underscore_temporary.stderr | 158 | ||||
| -rw-r--r-- | tests/ui/lifetimes/temporary-lifetime-extension.rs | 33 |
4 files changed, 119 insertions, 115 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 3bdb9a214ec..397893491a3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -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 diff --git a/tests/ui/borrowck/let_underscore_temporary.rs b/tests/ui/borrowck/let_underscore_temporary.rs index 0a24df08925..d1bdabd4eca 100644 --- a/tests/ui/borrowck/let_underscore_temporary.rs +++ b/tests/ui/borrowck/let_underscore_temporary.rs @@ -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 } { _ => {} }; diff --git a/tests/ui/borrowck/let_underscore_temporary.stderr b/tests/ui/borrowck/let_underscore_temporary.stderr index 6bccf329181..90b3462ebf8 100644 --- a/tests/ui/borrowck/let_underscore_temporary.stderr +++ b/tests/ui/borrowck/let_underscore_temporary.stderr @@ -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 - | -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 +error[E0597]: `a` does not live long enough + --> $DIR/let_underscore_temporary.rs:26:9 | - = 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 - | -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 +error[E0597]: `a` does not live long enough + --> $DIR/let_underscore_temporary.rs:39:9 | - = 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 - | -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 +error[E0597]: `a` does not live long enough + --> $DIR/let_underscore_temporary.rs:71:9 | - = 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 - | -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 +error[E0597]: `a` does not live long enough + --> $DIR/let_underscore_temporary.rs:92:9 | - = 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`. diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs new file mode 100644 index 00000000000..1ecef2f3d04 --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -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:?}"); +} |
