Skip to content

Commit

Permalink
Factor out some non_exhaustive-related checks
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Dec 4, 2019
1 parent 922310d commit b26aa0b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
26 changes: 18 additions & 8 deletions src/librustc_mir/hair/pattern/_match.rs
Expand Up @@ -238,7 +238,7 @@ use super::{FieldPat, Pat, PatKind, PatRange};
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};
Expand Down Expand Up @@ -596,9 +596,21 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
}
}

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,
}
}
Expand Down Expand Up @@ -858,8 +870,7 @@ impl<'tcx> Constructor<'tcx> {
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()
Expand Down Expand Up @@ -1264,8 +1275,7 @@ fn all_constructors<'a, 'tcx>(
// ```
// 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
Expand Down Expand Up @@ -2307,7 +2317,7 @@ fn specialize_one_pattern<'p, 'tcx>(

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(|_| {
Expand Down
9 changes: 3 additions & 6 deletions src/librustc_mir/hair/pattern/check_match.rs
Expand Up @@ -173,7 +173,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
let mut def_span = None;
let mut missing_variants = vec![];
if inlined_arms.is_empty() {
let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
let scrutinee_is_visibly_uninhabited = if self.tcx.features().exhaustive_patterns {
self.tcx.is_ty_uninhabited_from(module, pat_ty)
} else {
match pat_ty.kind {
Expand All @@ -186,15 +186,12 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
def.variants.iter().map(|variant| variant.ident).collect();
}

let is_non_exhaustive_and_non_local =
def.is_variant_list_non_exhaustive() && !def.did.is_local();

!(is_non_exhaustive_and_non_local) && def.variants.is_empty()
def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(pat_ty)
}
_ => false,
}
};
if !scrutinee_is_uninhabited {
if !scrutinee_is_visibly_uninhabited {
// We know the type is inhabited, so this must be wrong
let mut err = create_e0004(
self.tcx.sess,
Expand Down

0 comments on commit b26aa0b

Please sign in to comment.