diff options
| author | bors <bors@rust-lang.org> | 2020-10-30 07:05:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-10-30 07:05:57 +0000 |
| commit | 8df58ae03a8fda8ed126c02fbc16b530d18344df (patch) | |
| tree | c0c78ef0211c49ea75eb27eccdd9441a017d81d9 | |
| parent | 0d33ab7af4aebe786410b4c10367eb6ddf13af0b (diff) | |
| parent | 8bf9abbb7b7321ed4014b7f0d9978e425c966c95 (diff) | |
| download | rust-8df58ae03a8fda8ed126c02fbc16b530d18344df.tar.gz rust-8df58ae03a8fda8ed126c02fbc16b530d18344df.zip | |
Auto merge of #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 #75213 because the binding in that test case was autorefed and we recorded that adjusted type anyway. Fixes #78366
| -rw-r--r-- | compiler/rustc_typeck/src/check/generator_interior.rs | 12 | ||||
| -rw-r--r-- | src/test/ui/generator/yielding-in-match-guards.rs | 21 |
2 files changed, 32 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 4473aa2081f..f1828ddf3eb 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 d8aa354b1c6..c76726414df 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); } |
