use rustc::hir::def_id::DefId;
use rustc::hir::{HirId, RangeEnd};
use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
-use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
use rustc::lint;
use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
}
}
- fn is_local(&self, ty: Ty<'tcx>) -> bool {
+ // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
+ pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.kind {
- ty::Adt(adt_def, ..) => adt_def.did.is_local(),
+ ty::Adt(def, ..) => {
+ def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
+ }
+ _ => false,
+ }
+ }
+
+ // Returns whether the given variant is from another crate and has its fields declared
+ // `#[non_exhaustive]`.
+ fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool {
+ match ty.kind {
+ ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(),
_ => false,
}
}
vec![Pat::wildcard_from_ty(substs.type_at(0))]
} else {
let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
- let is_non_exhaustive =
- variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
+ let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant);
variant
.fields
.iter()
// ```
// we don't want to show every possible IO error, but instead have only `_` as the
// witness.
- let is_declared_nonexhaustive =
- def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
+ let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
// as though it had an "unknown" constructor to avoid exposing its emptyness. Note that
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
let ref variant = adt_def.variants[variant_index];
- let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
+ let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
Some(Variant(variant.def_id))
.filter(|variant_constructor| variant_constructor == constructor)
.map(|_| {