From 759bb5622fcd9dcab269cd574655bd49dad08f78 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 27 Oct 2023 05:10:58 +0200 Subject: [PATCH] Handle `ty::Opaque` correctly --- .../src/thir/pattern/usefulness.rs | 17 +++++++++++- .../issue-96572-unconstrained.rs | 27 ++++++++++++------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index bac995f7c36f6..25e0f3ceaa473 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -883,7 +883,22 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> { self.patterns.is_empty() } fn head_ty(&self) -> Option> { - self.patterns.get(0).map(|p| p.ty()) + if self.patterns.len() == 0 { + return None; + } + // If the type is opaque and it is revealed anywhere in the column, we take the revealed + // version. Otherwise we could encounter constructors for the revealed type and crash. + let is_opaque = |ty: Ty<'tcx>| matches!(ty.kind(), ty::Alias(ty::Opaque, ..)); + let first_ty = self.patterns[0].ty(); + if is_opaque(first_ty) { + for pat in &self.patterns { + let ty = pat.ty(); + if !is_opaque(ty) { + return Some(ty); + } + } + } + Some(first_ty) } fn analyze_ctors(&self, pcx: &PatCtxt<'_, 'p, 'tcx>) -> SplitConstructorSet<'tcx> { diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index fdd8fa65bd05f..5bd854be8c6ab 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -26,11 +26,9 @@ fn upvar() { fn enum_upvar() { type T = impl Copy; let foo: T = Some((1u32, 2u32)); - let x = move || { - match foo { - None => (), - Some((a, b)) => (), - } + let x = move || match foo { + None => (), + Some((a, b)) => (), }; } @@ -63,6 +61,19 @@ mod only_pattern { None => {} } } + + type V = impl Copy; + + fn baz(baz: Option) { + match baz { + _ => {} + Some((mut x, mut y)) => { + x = 42; + y = "foo"; + } + None => {} + } + } } mod only_pattern_rpit { @@ -71,11 +82,7 @@ mod only_pattern_rpit { let (mut x, mut y) = foo(false); x = 42; y = "foo"; - if b { - panic!() - } else { - foo(true) - } + if b { panic!() } else { foo(true) } } fn bar(b: bool) -> Option {