Skip to content

Commit

Permalink
Fix inhabitedness of non-exhaustive variants.
Browse files Browse the repository at this point in the history
This commit ensures that non-exhaustive variants are considered
inhabited when used in extern crates.
  • Loading branch information
davidtwco committed May 10, 2019
1 parent 0db087e commit 0d034a2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
11 changes: 8 additions & 3 deletions src/librustc/ty/inhabitedness/mod.rs
Expand Up @@ -134,9 +134,14 @@ impl<'a, 'gcx, 'tcx> VariantDef {
AdtKind::Enum => true,
AdtKind::Struct => false,
};
DefIdForest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(tcx, substs, is_enum)
}))
// Non-exhaustive variants from other crates are always considered inhabited.
if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
DefIdForest::empty()
} else {
DefIdForest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(tcx, substs, is_enum)
}))
}
}
}

Expand Down
27 changes: 23 additions & 4 deletions src/librustc_mir/hair/pattern/_match.rs
Expand Up @@ -388,6 +388,18 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
}
}

fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pattern<'tcx>) -> bool
where 'a: 'p
{
match *pattern.kind {
PatternKind::Variant { adt_def, variant_index, .. } => {
let ref variant = adt_def.variants[variant_index];
variant.is_field_list_non_exhaustive()
}
_ => false,
}
}

fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
Expand Down Expand Up @@ -1097,10 +1109,17 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);

if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
debug!("is_useful - expanding constructors: {:#?}", constructors);
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty);
debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}",
constructors, is_declared_nonexhaustive);

if is_declared_nonexhaustive {
Useful
} else {
split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
}
} else {
debug!("is_useful - expanding wildcard");

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/pattern/const-pat-ice.stderr
@@ -1,4 +1,4 @@
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1071:5
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic
Expand Down

0 comments on commit 0d034a2

Please sign in to comment.