diff options
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/cx.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lints.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/pat.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 7 |
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; } |
