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
4 changed files with 119 additions and 115 deletions
|
@ -689,6 +689,8 @@ fn resolve_local<'tcx>(
|
||||||
/// | [ ..., E&, ... ]
|
/// | [ ..., E&, ... ]
|
||||||
/// | ( ..., E&, ... )
|
/// | ( ..., E&, ... )
|
||||||
/// | {...; E&}
|
/// | {...; E&}
|
||||||
|
/// | if _ { ...; E& } else { ...; E& }
|
||||||
|
/// | match _ { ..., _ => E&, ... }
|
||||||
/// | box E&
|
/// | box E&
|
||||||
/// | E& as ...
|
/// | E& as ...
|
||||||
/// | ( E& )
|
/// | ( E& )
|
||||||
|
@ -727,6 +729,17 @@ fn resolve_local<'tcx>(
|
||||||
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
|
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(..) => {
|
hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => {
|
||||||
// FIXME(@dingxiangfei2009): choose call arguments here
|
// FIXME(@dingxiangfei2009): choose call arguments here
|
||||||
// for candidacy for extended parameter rule application
|
// for candidacy for extended parameter rule application
|
||||||
|
|
|
@ -7,8 +7,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
};
|
};
|
||||||
let _ = if let Some(ref s) = num { s } else { &0 };
|
let _ = if let Some(ref s) = num { s } else { &0 };
|
||||||
let _ = if let Some(mut s) = num {
|
let _ = if let Some(mut s) = num {
|
||||||
|
@ -21,8 +22,9 @@ fn let_underscore(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +35,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
};
|
};
|
||||||
let _: _ = if let Some(ref s) = num { s } else { &0 };
|
let _: _ = if let Some(ref s) = num { s } else { &0 };
|
||||||
let _: _ = if let Some(mut s) = num {
|
let _: _ = if let Some(mut s) = num {
|
||||||
|
@ -47,8 +50,9 @@ fn let_ascribe(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +67,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
} {
|
} {
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -83,8 +88,9 @@ fn matched(string: &Option<&str>, mut num: Option<i32>) {
|
||||||
*s += 1;
|
*s += 1;
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
&mut 0
|
let a = 0;
|
||||||
//~^ ERROR temporary value dropped while borrowed
|
&a
|
||||||
|
//~^ ERROR does not live long enough
|
||||||
} {
|
} {
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,117 +1,69 @@
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:10:14
|
--> $DIR/let_underscore_temporary.rs:11:9
|
||||||
|
|
|
|
||||||
LL | let _ = if let Some(s) = &mut num {
|
LL | let a = 0;
|
||||||
| _____________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | };
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:24:14
|
--> $DIR/let_underscore_temporary.rs:26:9
|
||||||
|
|
|
|
||||||
LL | let _ = if let Some(ref mut s) = num {
|
LL | let a = 0;
|
||||||
| _____________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | };
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:36:14
|
--> $DIR/let_underscore_temporary.rs:39:9
|
||||||
|
|
|
|
||||||
LL | let _: _ = if let Some(s) = &mut num {
|
LL | let a = 0;
|
||||||
| ________________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | };
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:50:14
|
--> $DIR/let_underscore_temporary.rs:54:9
|
||||||
|
|
|
|
||||||
LL | let _: _ = if let Some(ref mut s) = num {
|
LL | let a = 0;
|
||||||
| ________________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | };
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:66:14
|
--> $DIR/let_underscore_temporary.rs:71:9
|
||||||
|
|
|
|
||||||
LL | match if let Some(s) = &mut num {
|
LL | let a = 0;
|
||||||
| ___________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | } {
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/let_underscore_temporary.rs:86:14
|
--> $DIR/let_underscore_temporary.rs:92:9
|
||||||
|
|
|
|
||||||
LL | match if let Some(ref mut s) = num {
|
LL | let a = 0;
|
||||||
| ___________-
|
| - binding `a` declared here
|
||||||
LL | | *s += 1;
|
LL | &a
|
||||||
LL | | s
|
| ^^ borrowed value does not live long enough
|
||||||
LL | | } else {
|
LL |
|
||||||
LL | | &mut 0
|
LL | } {
|
||||||
| | ^ creates a temporary value which is freed while still in use
|
| - `a` dropped here while still borrowed
|
||||||
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
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
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…
Add table
Add a link
Reference in a new issue