Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs')
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs53
1 files changed, 23 insertions, 30 deletions
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 0b24fe7227..c171dbc170 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -1,9 +1,9 @@
//! Interface with `rustc_pattern_analysis`.
use std::fmt;
-use tracing::debug;
use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
+use once_cell::unsync::Lazy;
use rustc_hash::FxHashMap;
use rustc_pattern_analysis::{
constructor::{Constructor, ConstructorSet, VariantVisibility},
@@ -91,20 +91,13 @@ impl<'p> MatchCheckCtx<'p> {
}
fn is_uninhabited(&self, ty: &Ty) -> bool {
- is_ty_uninhabited_from(ty, self.module, self.db)
+ is_ty_uninhabited_from(self.db, ty, self.module)
}
- /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
- fn is_foreign_non_exhaustive_enum(&self, ty: &Ty) -> bool {
- match ty.as_adt() {
- Some((adt @ hir_def::AdtId::EnumId(_), _)) => {
- let has_non_exhaustive_attr =
- self.db.attrs(adt.into()).by_key("non_exhaustive").exists();
- let is_local = adt.module(self.db.upcast()).krate() == self.module.krate();
- has_non_exhaustive_attr && !is_local
- }
- _ => false,
- }
+ /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
+ fn is_foreign_non_exhaustive(&self, adt: hir_def::AdtId) -> bool {
+ let is_local = adt.krate(self.db.upcast()) == self.module.krate();
+ !is_local && self.db.attrs(adt.into()).by_key("non_exhaustive").exists()
}
fn variant_id_for_adt(
@@ -376,24 +369,21 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
single(subst_ty)
} else {
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
- let (adt, _) = ty.as_adt().unwrap();
- let adt_is_local =
- variant.module(self.db.upcast()).krate() == self.module.krate();
// Whether we must not match the fields of this variant exhaustively.
- let is_non_exhaustive =
- self.db.attrs(variant.into()).by_key("non_exhaustive").exists()
- && !adt_is_local;
- let visibilities = self.db.field_visibilities(variant);
+ let is_non_exhaustive = Lazy::new(|| self.is_foreign_non_exhaustive(adt));
+ let visibilities = Lazy::new(|| self.db.field_visibilities(variant));
self.list_variant_fields(ty, variant)
.map(move |(fid, ty)| {
- let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
- || visibilities[fid]
- .is_visible_from(self.db.upcast(), self.module);
+ let is_visible = || {
+ matches!(adt, hir_def::AdtId::EnumId(..))
+ || visibilities[fid]
+ .is_visible_from(self.db.upcast(), self.module)
+ };
let is_uninhabited = self.is_uninhabited(&ty);
let private_uninhabited =
- is_uninhabited && (!is_visible || is_non_exhaustive);
+ is_uninhabited && (!is_visible() || *is_non_exhaustive);
(ty, PrivateUninhabitedField(private_uninhabited))
})
.collect()
@@ -445,17 +435,20 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
TyKind::Scalar(Scalar::Char) => unhandled(),
TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
TyKind::Array(..) | TyKind::Slice(..) => unhandled(),
- TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), subst) => {
- let enum_data = cx.db.enum_data(*enum_id);
- let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(ty);
+ &TyKind::Adt(AdtId(adt @ hir_def::AdtId::EnumId(enum_id)), ref subst) => {
+ let enum_data = cx.db.enum_data(enum_id);
+ let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive(adt);
if enum_data.variants.is_empty() && !is_declared_nonexhaustive {
ConstructorSet::NoConstructors
} else {
- let mut variants = FxHashMap::default();
+ let mut variants = FxHashMap::with_capacity_and_hasher(
+ enum_data.variants.len(),
+ Default::default(),
+ );
for (i, &(variant, _)) in enum_data.variants.iter().enumerate() {
let is_uninhabited =
- is_enum_variant_uninhabited_from(variant, subst, cx.module, cx.db);
+ is_enum_variant_uninhabited_from(cx.db, variant, subst, cx.module);
let visibility = if is_uninhabited {
VariantVisibility::Empty
} else {
@@ -506,7 +499,7 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
}
fn bug(&self, fmt: fmt::Arguments<'_>) {
- debug!("{}", fmt)
+ never!("{}", fmt)
}
fn complexity_exceeded(&self) -> Result<(), Self::Error> {