Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate temporary lifetime extension into if and match. #121346

Merged
merged 5 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,8 @@ fn resolve_local<'tcx>(
/// | [ ..., E&, ... ]
/// | ( ..., E&, ... )
/// | {...; E&}
/// | if _ { ...; E& } else { ...; E& }
/// | match _ { ..., _ => E&, ... }
/// | box E&
/// | E& as ...
/// | ( E& )
Expand Down Expand Up @@ -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
Expand Down
30 changes: 18 additions & 12 deletions tests/ui/borrowck/let_underscore_temporary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
};
}

Expand All @@ -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 {
Expand All @@ -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
};
}

Expand All @@ -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
} {
_ => {}
};
Expand All @@ -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
} {
_ => {}
};
Expand Down
158 changes: 55 additions & 103 deletions tests/ui/borrowck/let_underscore_temporary.stderr
Original file line number Diff line number Diff line change
@@ -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`.
33 changes: 33 additions & 0 deletions tests/ui/lifetimes/temporary-lifetime-extension.rs
Original file line number Diff line number Diff line change
@@ -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:?}");
}