Open
Description
I tried this code:
struct C;
fn inout<'cfg>(c_out: &'cfg mut C) -> &'cfg C {
loop {
*c_out = C;
let r = &*c_out;
if true {
break r;
}
}
}
fn main() {
let mut c = C;
inout(&mut c);
}
I expected to see this happen: it compiles and runs
Instead, this happened: it fails to compile with the error:
error[E0506]: cannot assign to `*c_out` because it is borrowed
--> src/main.rs:5:9
|
3 | fn inout<'cfg>(c_out: &'cfg mut C) -> &'cfg C {
| ---- lifetime `'cfg` defined here
4 | loop {
5 | *c_out = C;
| ^^^^^^^^^^ assignment to borrowed `*c_out` occurs here
6 | let r = &*c_out;
| ------- borrow of `*c_out` occurs here
7 | if true {
8 | break r;
| - returning this value requires that `*c_out` is borrowed for `'cfg`
It's worth noting that the code builds fine if the break
is unconditional.
Even though the reproduction is somewhat different, this feels related to #92984
Meta
Happens on 1.61.0 stable, beta, and nightly.
Nightly Rust version from playground:
1.63.0-nightly
2022-06-07 5435ed6916a59e8d5acb
Hard mode
If you're looking for test cases, may also be worth including this one, which "launders" the lifetime through a for<'a>
:
struct C;
fn inout<'cfg, F>(c_out: &'cfg mut C, f: F) -> &'cfg C
where
for<'c> F: Fn(&'c C) -> &'c C,
{
loop {
*c_out = C;
let c = &*c_out;
let r = f(c);
if true {
break r;
}
}
}
fn main() {
let mut c = C;
inout(&mut c, |c| c);
}