Skip to content

Commit 8df58ae

Browse files
committed
Auto merge of rust-lang#78393 - SNCPlay42:match-if-guard, r=tmandry
Always record reference to binding in match if guards When encountering a binding from a `match` pattern in its `if` guard when computing a generator's interior types, we must always record the type of a reference to the binding because of how `if` guards are lowered to MIR. This was missed in rust-lang#75213 because the binding in that test case was autorefed and we recorded that adjusted type anyway. Fixes rust-lang#78366
2 parents 0d33ab7 + 8bf9abb commit 8df58ae

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

compiler/rustc_typeck/src/check/generator_interior.rs

+12
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
344344
// The type table might not have information for this expression
345345
// if it is in a malformed scope. (#66387)
346346
if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) {
347+
if guard_borrowing_from_pattern {
348+
// Match guards create references to all the bindings in the pattern that are used
349+
// in the guard, e.g. `y if is_even(y) => ...` becomes `is_even(*r_y)` where `r_y`
350+
// is a reference to `y`, so we must record a reference to the type of the binding.
351+
let tcx = self.fcx.tcx;
352+
let ref_ty = tcx.mk_ref(
353+
// Use `ReErased` as `resolve_interior` is going to replace all the regions anyway.
354+
tcx.mk_region(ty::RegionKind::ReErased),
355+
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
356+
);
357+
self.record(ref_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern);
358+
}
347359
self.record(ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern);
348360
} else {
349361
self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");

src/test/ui/generator/yielding-in-match-guards.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// check-pass
1+
// build-pass
22
// edition:2018
33

44
// This test is derived from
@@ -11,6 +11,7 @@
1111
// of the underlying generator.
1212

1313
async fn f() -> u8 { 1 }
14+
async fn foo() -> [bool; 10] { [false; 10] }
1415

1516
pub async fn g(x: u8) {
1617
match x {
@@ -19,6 +20,24 @@ pub async fn g(x: u8) {
1920
}
2021
}
2122

23+
// #78366: check the reference to the binding is recorded even if the binding is not autorefed
24+
25+
async fn h(x: usize) {
26+
match x {
27+
y if foo().await[y] => (),
28+
_ => (),
29+
}
30+
}
31+
32+
async fn i(x: u8) {
33+
match x {
34+
y if f().await == y + 1 => (),
35+
_ => (),
36+
}
37+
}
38+
2239
fn main() {
2340
let _ = g(10);
41+
let _ = h(9);
42+
let _ = i(8);
2443
}

0 commit comments

Comments
 (0)