]> git.lizzy.rs Git - rust.git/commitdiff
always record reference to binding in match if guards
authorSNCPlay42 <SNCPlay42@gmail.com>
Mon, 26 Oct 2020 09:28:09 +0000 (09:28 +0000)
committerSNCPlay42 <SNCPlay42@gmail.com>
Mon, 26 Oct 2020 09:29:50 +0000 (09:29 +0000)
compiler/rustc_typeck/src/check/generator_interior.rs
src/test/ui/generator/yielding-in-match-guards.rs

index 4473aa2081f23192c1d0944950229e8bafef8f01..f1828ddf3eb9497a92d14b740d176ec1873ce023 100644 (file)
@@ -344,6 +344,18 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'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");
index d8aa354b1c604bb382622b1b8e09e9d423dd0937..c76726414df8abb27752ac058572bd0655cb0fee 100644 (file)
@@ -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);
 }