Skip to content

Commit b26aa0b

Browse files
committed
Factor out some non_exhaustive-related checks
1 parent 922310d commit b26aa0b

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ use super::{FieldPat, Pat, PatKind, PatRange};
238238
use rustc::hir::def_id::DefId;
239239
use rustc::hir::{HirId, RangeEnd};
240240
use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx};
241-
use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable};
241+
use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef};
242242

243243
use rustc::lint;
244244
use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
@@ -596,9 +596,21 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
596596
}
597597
}
598598

599-
fn is_local(&self, ty: Ty<'tcx>) -> bool {
599+
// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
600+
pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
600601
match ty.kind {
601-
ty::Adt(adt_def, ..) => adt_def.did.is_local(),
602+
ty::Adt(def, ..) => {
603+
def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
604+
}
605+
_ => false,
606+
}
607+
}
608+
609+
// Returns whether the given variant is from another crate and has its fields declared
610+
// `#[non_exhaustive]`.
611+
fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool {
612+
match ty.kind {
613+
ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(),
602614
_ => false,
603615
}
604616
}
@@ -858,8 +870,7 @@ impl<'tcx> Constructor<'tcx> {
858870
vec![Pat::wildcard_from_ty(substs.type_at(0))]
859871
} else {
860872
let variant = &adt.variants[self.variant_index_for_adt(cx, adt)];
861-
let is_non_exhaustive =
862-
variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
873+
let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant);
863874
variant
864875
.fields
865876
.iter()
@@ -1264,8 +1275,7 @@ fn all_constructors<'a, 'tcx>(
12641275
// ```
12651276
// we don't want to show every possible IO error, but instead have only `_` as the
12661277
// witness.
1267-
let is_declared_nonexhaustive =
1268-
def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty);
1278+
let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty);
12691279

12701280
// If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it
12711281
// as though it had an "unknown" constructor to avoid exposing its emptyness. Note that
@@ -2307,7 +2317,7 @@ fn specialize_one_pattern<'p, 'tcx>(
23072317

23082318
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
23092319
let ref variant = adt_def.variants[variant_index];
2310-
let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
2320+
let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant);
23112321
Some(Variant(variant.def_id))
23122322
.filter(|variant_constructor| variant_constructor == constructor)
23132323
.map(|_| {

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
173173
let mut def_span = None;
174174
let mut missing_variants = vec![];
175175
if inlined_arms.is_empty() {
176-
let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
176+
let scrutinee_is_visibly_uninhabited = if self.tcx.features().exhaustive_patterns {
177177
self.tcx.is_ty_uninhabited_from(module, pat_ty)
178178
} else {
179179
match pat_ty.kind {
@@ -186,15 +186,12 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
186186
def.variants.iter().map(|variant| variant.ident).collect();
187187
}
188188

189-
let is_non_exhaustive_and_non_local =
190-
def.is_variant_list_non_exhaustive() && !def.did.is_local();
191-
192-
!(is_non_exhaustive_and_non_local) && def.variants.is_empty()
189+
def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(pat_ty)
193190
}
194191
_ => false,
195192
}
196193
};
197-
if !scrutinee_is_uninhabited {
194+
if !scrutinee_is_visibly_uninhabited {
198195
// We know the type is inhabited, so this must be wrong
199196
let mut err = create_e0004(
200197
self.tcx.sess,

0 commit comments

Comments
 (0)