Box field detection; test #[non-exhaustive] attribute
This commit is contained in:
parent
f46a42f73a
commit
4cce7a6407
@ -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
|
||||
|
@ -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<T>.
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -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<PatternArena>,
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user