Skip to content

Commit 4cce7a6

Browse files
committed
Box field detection; test #[non-exhaustive] attribute
1 parent f46a42f commit 4cce7a6

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

crates/hir_ty/src/diagnostics/match_check.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,42 @@ fn main() {
10901090
);
10911091
}
10921092

1093+
#[test]
1094+
fn enum_non_exhaustive() {
1095+
check_diagnostics(
1096+
r#"
1097+
//- /lib.rs crate:lib
1098+
#[non_exhaustive]
1099+
pub enum E { A, B }
1100+
fn _local() {
1101+
match E::A { _ => {} }
1102+
match E::A {
1103+
E::A => {}
1104+
E::B => {}
1105+
}
1106+
match E::A {
1107+
E::A | E::B => {}
1108+
}
1109+
}
1110+
1111+
//- /main.rs crate:main deps:lib
1112+
use lib::E;
1113+
fn main() {
1114+
match E::A { _ => {} }
1115+
match E::A {
1116+
//^^^^ Missing match arm
1117+
E::A => {}
1118+
E::B => {}
1119+
}
1120+
match E::A {
1121+
//^^^^ Missing match arm
1122+
E::A | E::B => {}
1123+
}
1124+
}
1125+
"#,
1126+
);
1127+
}
1128+
10931129
mod false_negatives {
10941130
//! The implementation of match checking here is a work in progress. As we roll this out, we
10951131
//! prefer false negatives to false positives (ideally there would be no false positives). This

crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -513,9 +513,7 @@ impl SplitWildcard {
513513
if is_secretly_empty || is_declared_nonexhaustive {
514514
smallvec![NonExhaustive]
515515
} else if cx.feature_exhaustive_patterns() {
516-
// If `exhaustive_patterns` is enabled, we exclude variants known to be
517-
// uninhabited.
518-
unhandled()
516+
unimplemented!() // see MatchCheckCtx.feature_exhaustive_patterns()
519517
} else {
520518
enum_data
521519
.variants
@@ -643,6 +641,7 @@ impl Fields {
643641
Fields::Vec(pats)
644642
}
645643

644+
/// Creates a new list of wildcard fields for a given constructor.
646645
pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self {
647646
let ty = pcx.ty;
648647
let cx = pcx.cx;
@@ -655,14 +654,13 @@ impl Fields {
655654
Fields::wildcards_from_tys(cx, tys)
656655
}
657656
TyKind::Ref(.., rty) => Fields::from_single_pattern(wildcard_from_ty(rty)),
658-
TyKind::Adt(AdtId(adt), substs) => {
659-
let adt_is_box = false; // TODO(iDawer): implement this
660-
if adt_is_box {
657+
&TyKind::Adt(AdtId(adt), ref substs) => {
658+
if adt_is_box(adt, cx) {
661659
// Use T as the sub pattern type of Box<T>.
662660
let subst_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner);
663661
Fields::from_single_pattern(wildcard_from_ty(subst_ty))
664662
} else {
665-
let variant_id = constructor.variant_id_for_adt(*adt);
663+
let variant_id = constructor.variant_id_for_adt(adt);
666664
let adt_is_local =
667665
variant_id.module(cx.db.upcast()).krate() == cx.module.krate();
668666
// Whether we must not match the fields of this variant exhaustively.
@@ -680,7 +678,7 @@ impl Fields {
680678
if has_no_hidden_fields {
681679
Fields::wildcards_from_tys(cx, field_tys())
682680
} else {
683-
//FIXME(iDawer): see MatchCheckCtx::is_uninhabited
681+
//FIXME(iDawer): see MatchCheckCtx::is_uninhabited, has_no_hidden_fields is always true
684682
unimplemented!("exhaustive_patterns feature")
685683
}
686684
}
@@ -892,3 +890,11 @@ fn is_field_list_non_exhaustive(variant_id: VariantId, cx: &MatchCheckCtx<'_>) -
892890
};
893891
cx.db.attrs(attr_def_id).by_key("non_exhaustive").exists()
894892
}
893+
894+
fn adt_is_box(adt: hir_def::AdtId, cx: &MatchCheckCtx<'_>) -> bool {
895+
use hir_def::lang_item::LangItemTarget;
896+
match cx.db.lang_item(cx.module.krate(), "owned_box".into()) {
897+
Some(LangItemTarget::StructId(box_id)) => adt == box_id.into(),
898+
_ => false,
899+
}
900+
}

crates/hir_ty/src/diagnostics/match_check/usefulness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ pub(crate) struct MatchCheckCtx<'a> {
293293
pub(crate) match_expr: ExprId,
294294
pub(crate) infer: &'a InferenceResult,
295295
pub(crate) db: &'a dyn HirDatabase,
296-
/// Lowered patterns from self.body.pats plus generated by the check.
296+
/// Lowered patterns from arms plus generated by the check.
297297
pub(crate) pattern_arena: &'a RefCell<PatternArena>,
298298
}
299299

@@ -315,7 +315,7 @@ impl<'a> MatchCheckCtx<'a> {
315315

316316
// Rust feature described as "Allows exhaustive pattern matching on types that contain uninhabited types."
317317
pub(super) fn feature_exhaustive_patterns(&self) -> bool {
318-
// TODO
318+
// FIXME see MatchCheckCtx::is_uninhabited
319319
false
320320
}
321321

0 commit comments

Comments
 (0)