From 679b90c2954102099d4876d59e94219e544964ce Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 20 Feb 2024 14:41:55 +0100 Subject: [PATCH 1/5] Propagate temporary lifetime extension into if and match. --- compiler/rustc_hir_analysis/src/check/region.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 0f5fd7e99b776..e16d61bed2e9d 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 From 476faa219641878df1ed95db6ed138b49cf6f348 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 20 Feb 2024 14:58:17 +0100 Subject: [PATCH 2/5] Update test. --- tests/ui/borrowck/let_underscore_temporary.rs | 30 ++-- .../borrowck/let_underscore_temporary.stderr | 158 ++++++------------ 2 files changed, 73 insertions(+), 115 deletions(-) diff --git a/tests/ui/borrowck/let_underscore_temporary.rs b/tests/ui/borrowck/let_underscore_temporary.rs index 0a24df08925f8..d1bdabd4ecac4 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) { *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) { *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) { *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) { *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) { *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) { *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 6bccf329181f0..90b3462ebf8c3 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`. From bec765e5079c09fe9f32119d4f8b7a3ff818f4f2 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 20 Feb 2024 15:19:16 +0100 Subject: [PATCH 3/5] Add test. --- .../lifetimes/temporary-lifetime-extension.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/ui/lifetimes/temporary-lifetime-extension.rs diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs new file mode 100644 index 0000000000000..477801f327344 --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -0,0 +1,29 @@ +//@ 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() + } + }; + println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); +} From e6d3e0cf99dcde0dd660cea52998fa11c79f36d1 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 20 Feb 2024 16:22:04 +0100 Subject: [PATCH 4/5] Extend temporary lifetime extension test. Co-authored-by: Daniel Henry-Mantilla --- tests/ui/lifetimes/temporary-lifetime-extension.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs index 477801f327344..193ca0b4d0733 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -25,5 +25,8 @@ fn main() { &temp() } }; - println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); + let h = match temp() { + owned_non_temporary => &{ owned_non_temporary }, + }; + println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?} {h:?}"); } From f4caa832dad4482ec1fa85bdbc3156c83cc948de Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 20 Feb 2024 16:23:05 +0100 Subject: [PATCH 5/5] Add clarifying comment to test. --- tests/ui/lifetimes/temporary-lifetime-extension.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs index 193ca0b4d0733..1ecef2f3d04df 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -26,6 +26,7 @@ fn main() { } }; 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:?}");