From 4cce7a6407821f456741a8d512ae31da3128c84f Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Wed, 12 May 2021 11:04:56 +0500 Subject: Box field detection; test #[non-exhaustive] attribute --- crates/hir_ty/src/diagnostics/match_check.rs | 36 ++++++++++++++++++++++ .../src/diagnostics/match_check/deconstruct_pat.rs | 22 ++++++++----- .../src/diagnostics/match_check/usefulness.rs | 4 +-- 3 files changed, 52 insertions(+), 10 deletions(-) (limited to 'crates/hir_ty') diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 5f0cc4145..061ef754d 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -1090,6 +1090,42 @@ fn main() { ); } + #[test] + fn enum_non_exhaustive() { + check_diagnostics( + r#" +//- /lib.rs crate:lib +#[non_exhaustive] +pub enum E { A, B } +fn _local() { + match E::A { _ => {} } + match E::A { + E::A => {} + E::B => {} + } + match E::A { + E::A | E::B => {} + } +} + +//- /main.rs crate:main deps:lib +use lib::E; +fn main() { + match E::A { _ => {} } + match E::A { + //^^^^ Missing match arm + E::A => {} + E::B => {} + } + match E::A { + //^^^^ Missing match arm + E::A | E::B => {} + } +} +"#, + ); + } + mod false_negatives { //! The implementation of match checking here is a work in progress. As we roll this out, we //! prefer false negatives to false positives (ideally there would be no false positives). This diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs index 9fa82a952..6711fbb4a 100644 --- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs @@ -513,9 +513,7 @@ impl SplitWildcard { if is_secretly_empty || is_declared_nonexhaustive { smallvec![NonExhaustive] } else if cx.feature_exhaustive_patterns() { - // If `exhaustive_patterns` is enabled, we exclude variants known to be - // uninhabited. - unhandled() + unimplemented!() // see MatchCheckCtx.feature_exhaustive_patterns() } else { enum_data .variants @@ -643,6 +641,7 @@ impl Fields { Fields::Vec(pats) } + /// Creates a new list of wildcard fields for a given constructor. pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self { let ty = pcx.ty; let cx = pcx.cx; @@ -655,14 +654,13 @@ impl Fields { Fields::wildcards_from_tys(cx, tys) } TyKind::Ref(.., rty) => Fields::from_single_pattern(wildcard_from_ty(rty)), - TyKind::Adt(AdtId(adt), substs) => { - let adt_is_box = false; // TODO(iDawer): implement this - if adt_is_box { + &TyKind::Adt(AdtId(adt), ref substs) => { + if adt_is_box(adt, cx) { // Use T as the sub pattern type of Box. let subst_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner); Fields::from_single_pattern(wildcard_from_ty(subst_ty)) } else { - let variant_id = constructor.variant_id_for_adt(*adt); + let variant_id = constructor.variant_id_for_adt(adt); let adt_is_local = variant_id.module(cx.db.upcast()).krate() == cx.module.krate(); // Whether we must not match the fields of this variant exhaustively. @@ -680,7 +678,7 @@ impl Fields { if has_no_hidden_fields { Fields::wildcards_from_tys(cx, field_tys()) } else { - //FIXME(iDawer): see MatchCheckCtx::is_uninhabited + //FIXME(iDawer): see MatchCheckCtx::is_uninhabited, has_no_hidden_fields is always true unimplemented!("exhaustive_patterns feature") } } @@ -892,3 +890,11 @@ fn is_field_list_non_exhaustive(variant_id: VariantId, cx: &MatchCheckCtx<'_>) - }; cx.db.attrs(attr_def_id).by_key("non_exhaustive").exists() } + +fn adt_is_box(adt: hir_def::AdtId, cx: &MatchCheckCtx<'_>) -> bool { + use hir_def::lang_item::LangItemTarget; + match cx.db.lang_item(cx.module.krate(), "owned_box".into()) { + Some(LangItemTarget::StructId(box_id)) => adt == box_id.into(), + _ => false, + } +} diff --git a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs index b01e3557c..44e08b6e9 100644 --- a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs +++ b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs @@ -293,7 +293,7 @@ pub(crate) struct MatchCheckCtx<'a> { pub(crate) match_expr: ExprId, pub(crate) infer: &'a InferenceResult, pub(crate) db: &'a dyn HirDatabase, - /// Lowered patterns from self.body.pats plus generated by the check. + /// Lowered patterns from arms plus generated by the check. pub(crate) pattern_arena: &'a RefCell, } @@ -315,7 +315,7 @@ impl<'a> MatchCheckCtx<'a> { // Rust feature described as "Allows exhaustive pattern matching on types that contain uninhabited types." pub(super) fn feature_exhaustive_patterns(&self) -> bool { - // TODO + // FIXME see MatchCheckCtx::is_uninhabited false } -- cgit v1.2.3