Skip to content

Commit

Permalink
Auto merge of rust-lang#121346 - m-ou-se:temp-lifetime-if-else-match,…
Browse files Browse the repository at this point in the history
… 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](rust-lang/lang-team#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.
  • Loading branch information
bors committed Apr 10, 2024
2 parents c2239bc + f4caa83 commit b3bd705
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 115 deletions.
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:?}");
}

0 comments on commit b3bd705

Please sign in to comment.