about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2019-05-04 01:17:26 +0100
committerDavid Wood <david@davidtw.co>2019-05-10 17:52:12 +0100
commit0d034a2e4dd9418fa41aba4ebdd1ebc31a08c9e9 (patch)
tree2b8181dccce6f74086ff1f74385d4a383930648d /src
parent0db087e6840cc865bcf8be09ff940f2ac13341ac (diff)
downloadrust-0d034a2e4dd9418fa41aba4ebdd1ebc31a08c9e9.tar.gz
rust-0d034a2e4dd9418fa41aba4ebdd1ebc31a08c9e9.zip
Fix inhabitedness of non-exhaustive variants.
This commit ensures that non-exhaustive variants are considered
inhabited when used in extern crates.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs11
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs27
-rw-r--r--src/test/ui/pattern/const-pat-ice.stderr2
3 files changed, 32 insertions, 8 deletions
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 197d3325f51..2fc07fb20bf 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -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)
+            }))
+        }
     }
 }
 
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index edd36abc0b8..fd4416fc2b7 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -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(),
@@ -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");
 
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 261e95229a7..260c2e04d74 100644
--- a/src/test/ui/pattern/const-pat-ice.stderr
+++ b/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