Skip to content

Commit 6bae9c3

Browse files
committed
Always use LUB for match arms
1 parent a19c16d commit 6bae9c3

File tree

7 files changed

+49
-23
lines changed

7 files changed

+49
-23
lines changed

compiler/rustc_hir_typeck/src/_match.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7575
};
7676
CoerceMany::with_coercion_sites(coerce_first, arms)
7777
};
78+
coercion.force_lub();
7879

7980
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
8081
let mut prior_arm = None;

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,7 @@ pub(crate) struct CoerceMany<'tcx, 'exprs, E: AsCoercionSite> {
13871387
final_ty: Option<Ty<'tcx>>,
13881388
expressions: Expressions<'tcx, 'exprs, E>,
13891389
pushed: usize,
1390+
force_lub: bool,
13901391
}
13911392

13921393
/// The type of a `CoerceMany` that is storing up the expressions into
@@ -1416,7 +1417,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
14161417
}
14171418

14181419
fn make(expected_ty: Ty<'tcx>, expressions: Expressions<'tcx, 'exprs, E>) -> Self {
1419-
CoerceMany { expected_ty, final_ty: None, expressions, pushed: 0 }
1420+
CoerceMany { expected_ty, final_ty: None, expressions, pushed: 0, force_lub: false }
1421+
}
1422+
1423+
pub(crate) fn force_lub(&mut self) {
1424+
// Don't accidentally let someone switch this after coercing things
1425+
assert_eq!(self.pushed, 0);
1426+
self.force_lub = true;
14201427
}
14211428

14221429
/// Returns the "expected type" with which this coercion was
@@ -1529,10 +1536,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15291536

15301537
// Handle the actual type unification etc.
15311538
let result = if let Some(expression) = expression {
1532-
if self.pushed == 0 {
1533-
// Special-case the first expression we are coercing.
1534-
// To be honest, I'm not entirely sure why we do this.
1535-
// We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
1539+
if !self.force_lub && self.pushed == 0 {
1540+
// For this *first* expression, we do *not* use LUB
1541+
// (which `try_find_coercion_lub` does).
15361542
fcx.coerce(
15371543
expression,
15381544
expression_ty,

tests/ui/coercion/coerce-loop-issue-122561.stderr

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,6 @@ LL | | }
9090
|
9191
= note: expected type `!`
9292
found unit type `()`
93-
= note: `for` loops evaluate to unit type `()`
94-
help: consider adding a diverging expression here
95-
|
96-
LL ~ }
97-
LL + /* `loop {}` or `panic!("...")` */
98-
|
9993

10094
error[E0308]: mismatched types
10195
--> $DIR/coerce-loop-issue-122561.rs:35:32

tests/ui/issues/issue-28839.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
//@ run-pass
1+
//@ check-fail
22

33
pub struct Foo;
44

5-
pub fn get_foo2<'a>(foo: &'a mut Option<&'a mut Foo>) -> &'a mut Foo {
5+
pub fn get_foo1<'a>(foo: &'a mut Option<&'a mut Foo>) -> &'a mut Foo {
66
match foo {
7-
// Ensure that this is not considered a move, but rather a reborrow.
87
&mut Some(ref mut x) => *x,
8+
//~^ ERROR cannot move out of
9+
&mut None => panic!(),
10+
}
11+
}
12+
13+
pub fn get_foo2<'a>(foo: &'a mut Option<&'a mut Foo>) -> &'a mut Foo {
14+
match foo {
915
&mut None => panic!(),
16+
&mut Some(ref mut x) => *x,
17+
//~^ ERROR cannot move out of
1018
}
1119
}
1220

tests/ui/issues/issue-28839.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0507]: cannot move out of `*x` which is behind a mutable reference
2+
--> $DIR/issue-28839.rs:7:33
3+
|
4+
LL | &mut Some(ref mut x) => *x,
5+
| ^^ move occurs because `*x` has type `&mut Foo`, which does not implement the `Copy` trait
6+
7+
error[E0507]: cannot move out of `*x` which is behind a mutable reference
8+
--> $DIR/issue-28839.rs:16:33
9+
|
10+
LL | &mut Some(ref mut x) => *x,
11+
| ^^ move occurs because `*x` has type `&mut Foo`, which does not implement the `Copy` trait
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0507`.

tests/ui/nll/issue-52213.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
22
match (&t,) {
3-
((u,),) => u,
43
//~^ ERROR lifetime may not live long enough
4+
((u,),) => u,
55
}
66
}
77

tests/ui/nll/issue-52213.stderr

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
error: lifetime may not live long enough
2-
--> $DIR/issue-52213.rs:3:20
2+
--> $DIR/issue-52213.rs:2:5
33
|
4-
LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
5-
| -- -- lifetime `'b` defined here
6-
| |
7-
| lifetime `'a` defined here
8-
LL | match (&t,) {
9-
LL | ((u,),) => u,
10-
| ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
4+
LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | / match (&t,) {
9+
LL | |
10+
LL | | ((u,),) => u,
11+
LL | | }
12+
| |_____^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
1113
|
1214
= help: consider adding the following bound: `'a: 'b`
1315

0 commit comments

Comments
 (0)