about summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
-rw-r--r--compiler/rustc_pattern_analysis/src/cx.rs6
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs5
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs49
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs7
4 files changed, 31 insertions, 36 deletions
diff --git a/compiler/rustc_pattern_analysis/src/cx.rs b/compiler/rustc_pattern_analysis/src/cx.rs
index 81c836b878e..e4acf317a0d 100644
--- a/compiler/rustc_pattern_analysis/src/cx.rs
+++ b/compiler/rustc_pattern_analysis/src/cx.rs
@@ -49,10 +49,14 @@ pub struct MatchCheckCtxt<'p, 'tcx> {
 }
 
 impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
-    pub(super) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
+    pub(crate) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         !ty.is_inhabited_from(self.tcx, self.module, self.param_env)
     }
 
+    pub(crate) fn is_opaque(ty: Ty<'tcx>) -> bool {
+        matches!(ty.kind(), ty::Alias(ty::Opaque, ..))
+    }
+
     /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
     pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind() {
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 8ab559c9e7a..aaa859f33fa 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -53,12 +53,11 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
         }
         // 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) {
+        if MatchCheckCtxt::is_opaque(first_ty) {
             for pat in &self.patterns {
                 let ty = pat.ty();
-                if !is_opaque(ty) {
+                if !MatchCheckCtxt::is_opaque(ty) {
                     return Some(ty);
                 }
             }
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index 404651124ad..7f33a1ab40c 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -6,13 +6,12 @@ use std::fmt;
 use smallvec::{smallvec, SmallVec};
 
 use rustc_data_structures::captures::Captures;
-use rustc_middle::ty::{self, Ty};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_middle::ty::Ty;
+use rustc_span::Span;
 
 use self::Constructor::*;
-use self::SliceKind::*;
 
-use crate::constructor::{Constructor, SliceKind};
+use crate::constructor::{Constructor, Slice, SliceKind};
 use crate::cx::MatchCheckCtxt;
 use crate::usefulness::PatCtxt;
 
@@ -90,31 +89,25 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                 // We return a wildcard for each field of `other_ctor`.
                 pcx.cx.ctor_wildcard_fields(other_ctor, pcx.ty).iter().collect()
             }
-            (Slice(self_slice), Slice(other_slice))
-                if self_slice.arity() != other_slice.arity() =>
-            {
-                // The only tricky case: two slices of different arity. Since `self_slice` covers
-                // `other_slice`, `self_slice` must be `VarLen`, i.e. of the form
-                // `[prefix, .., suffix]`. Moreover `other_slice` is guaranteed to have a larger
-                // arity. So we fill the middle part with enough wildcards to reach the length of
-                // the new, larger slice.
-                match self_slice.kind {
-                    FixedLen(_) => bug!("{:?} doesn't cover {:?}", self_slice, other_slice),
-                    VarLen(prefix, suffix) => {
-                        let (ty::Slice(inner_ty) | ty::Array(inner_ty, _)) = *self.ty.kind() else {
-                            bug!("bad slice pattern {:?} {:?}", self.ctor, self.ty);
-                        };
-                        let prefix = &self.fields[..prefix];
-                        let suffix = &self.fields[self_slice.arity() - suffix..];
-                        let wildcard: &_ = pcx
-                            .cx
-                            .pattern_arena
-                            .alloc(DeconstructedPat::wildcard(inner_ty, DUMMY_SP));
-                        let extra_wildcards = other_slice.arity() - self_slice.arity();
-                        let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
-                        prefix.iter().chain(extra_wildcards).chain(suffix).collect()
-                    }
+            (
+                &Slice(self_slice @ Slice { kind: SliceKind::VarLen(prefix, suffix), .. }),
+                &Slice(other_slice),
+            ) if self_slice.arity() != other_slice.arity() => {
+                // The only non-trivial case: two slices of different arity. `other_slice` is
+                // guaranteed to have a larger arity, so we fill the middle part with enough
+                // wildcards to reach the length of the new, larger slice.
+                // Start with a slice of wildcards of the appropriate length.
+                let mut fields: SmallVec<[_; 2]> =
+                    pcx.cx.ctor_wildcard_fields(other_ctor, pcx.ty).iter().collect();
+                // Fill in the fields from both ends.
+                let new_arity = fields.len();
+                for i in 0..prefix {
+                    fields[i] = &self.fields[i];
                 }
+                for i in 0..suffix {
+                    fields[new_arity - 1 - i] = &self.fields[self.fields.len() - 1 - i];
+                }
+                fields
             }
             _ => self.fields.iter().collect(),
         }
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index a2467ae6a39..d007e382000 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -556,7 +556,7 @@ use smallvec::{smallvec, SmallVec};
 use std::fmt;
 
 use rustc_data_structures::{captures::Captures, stack::ensure_sufficient_stack};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::Ty;
 use rustc_span::{Span, DUMMY_SP};
 
 use crate::constructor::{Constructor, ConstructorSet};
@@ -856,11 +856,10 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
         let mut ty = self.wildcard_row.head().ty();
         // 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, ..));
-        if is_opaque(ty) {
+        if MatchCheckCtxt::is_opaque(ty) {
             for pat in self.heads() {
                 let pat_ty = pat.ty();
-                if !is_opaque(pat_ty) {
+                if !MatchCheckCtxt::is_opaque(pat_ty) {
                     ty = pat_ty;
                     break;
                 }