Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/diagnostics/match_check/usefulness.rs')
-rw-r--r--crates/hir-ty/src/diagnostics/match_check/usefulness.rs41
1 files changed, 33 insertions, 8 deletions
diff --git a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs b/crates/hir-ty/src/diagnostics/match_check/usefulness.rs
index 1221327b95..4bb4ff8f10 100644
--- a/crates/hir-ty/src/diagnostics/match_check/usefulness.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/usefulness.rs
@@ -274,10 +274,11 @@
use std::iter::once;
use hir_def::{AdtId, DefWithBodyId, HasModule, ModuleId};
+use once_cell::unsync::OnceCell;
use smallvec::{smallvec, SmallVec};
use typed_arena::Arena;
-use crate::{db::HirDatabase, Ty, TyExt};
+use crate::{db::HirDatabase, inhabitedness::is_ty_uninhabited_from, Ty, TyExt};
use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard};
@@ -289,13 +290,25 @@ pub(crate) struct MatchCheckCtx<'a, 'p> {
pub(crate) db: &'a dyn HirDatabase,
/// Lowered patterns from arms plus generated by the check.
pub(crate) pattern_arena: &'p Arena<DeconstructedPat<'p>>,
+ feature_exhaustive_patterns: OnceCell<bool>,
}
impl<'a, 'p> MatchCheckCtx<'a, 'p> {
- pub(super) fn is_uninhabited(&self, _ty: &Ty) -> bool {
- // FIXME(iDawer) implement exhaustive_patterns feature. More info in:
- // Tracking issue for RFC 1872: exhaustive_patterns feature https://github.com/rust-lang/rust/issues/51085
- false
+ pub(crate) fn new(
+ module: ModuleId,
+ body: DefWithBodyId,
+ db: &'a dyn HirDatabase,
+ pattern_arena: &'p Arena<DeconstructedPat<'p>>,
+ ) -> Self {
+ Self { module, body, db, pattern_arena, feature_exhaustive_patterns: Default::default() }
+ }
+
+ pub(super) fn is_uninhabited(&self, ty: &Ty) -> bool {
+ if self.feature_exhaustive_patterns() {
+ is_ty_uninhabited_from(ty, self.module, self.db)
+ } else {
+ false
+ }
}
/// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
@@ -311,10 +324,22 @@ impl<'a, 'p> MatchCheckCtx<'a, 'p> {
}
}
- // Rust feature described as "Allows exhaustive pattern matching on types that contain uninhabited types."
+ // Rust's unstable feature described as "Allows exhaustive pattern matching on types that contain uninhabited types."
pub(super) fn feature_exhaustive_patterns(&self) -> bool {
- // FIXME see MatchCheckCtx::is_uninhabited
- false
+ *self.feature_exhaustive_patterns.get_or_init(|| {
+ let def_map = self.db.crate_def_map(self.module.krate());
+ let root_mod = def_map.module_id(def_map.root());
+ let rood_attrs = self.db.attrs(root_mod.into());
+ let mut nightly_features = rood_attrs
+ .by_key("feature")
+ .attrs()
+ .map(|attr| attr.parse_path_comma_token_tree())
+ .flatten()
+ .flatten();
+ nightly_features.any(
+ |feat| matches!(feat.segments(), [name] if name.to_smol_str() == "exhaustive_patterns"),
+ )
+ })
}
}