diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 4473aa2081f23..f1828ddf3eb94 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -344,6 +344,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // The type table might not have information for this expression // if it is in a malformed scope. (#66387) if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) { + if guard_borrowing_from_pattern { + // Match guards create references to all the bindings in the pattern that are used + // in the guard, e.g. `y if is_even(y) => ...` becomes `is_even(*r_y)` where `r_y` + // is a reference to `y`, so we must record a reference to the type of the binding. + let tcx = self.fcx.tcx; + let ref_ty = tcx.mk_ref( + // Use `ReErased` as `resolve_interior` is going to replace all the regions anyway. + tcx.mk_region(ty::RegionKind::ReErased), + ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }, + ); + self.record(ref_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); + } self.record(ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern); } else { self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); diff --git a/src/test/ui/generator/yielding-in-match-guards.rs b/src/test/ui/generator/yielding-in-match-guards.rs index d8aa354b1c604..c76726414df8a 100644 --- a/src/test/ui/generator/yielding-in-match-guards.rs +++ b/src/test/ui/generator/yielding-in-match-guards.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass // edition:2018 // This test is derived from @@ -11,6 +11,7 @@ // of the underlying generator. async fn f() -> u8 { 1 } +async fn foo() -> [bool; 10] { [false; 10] } pub async fn g(x: u8) { match x { @@ -19,6 +20,24 @@ pub async fn g(x: u8) { } } +// #78366: check the reference to the binding is recorded even if the binding is not autorefed + +async fn h(x: usize) { + match x { + y if foo().await[y] => (), + _ => (), + } +} + +async fn i(x: u8) { + match x { + y if f().await == y + 1 => (), + _ => (), + } +} + fn main() { let _ = g(10); + let _ = h(9); + let _ = i(8); }