about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrew Cann <shum@canndrew.org>2016-11-09 17:55:57 +0800
committerAndrew Cann <shum@canndrew.org>2016-11-22 13:22:31 +0800
commitd756f61a5a7ab84d58fdaa9d53d84f6dad29f8db (patch)
treec56b85f11021792f673249fbb140944c7a3e316c
parenta6cc398207009884a2885855e79ba424c2f4c303 (diff)
downloadrust-d756f61a5a7ab84d58fdaa9d53d84f6dad29f8db.tar.gz
rust-d756f61a5a7ab84d58fdaa9d53d84f6dad29f8db.zip
Make is_uninhabited respect privacy
-rw-r--r--src/librustc/ty/mod.rs14
-rw-r--r--src/librustc/ty/sty.rs19
-rw-r--r--src/librustc_const_eval/check_match.rs2
3 files changed, 21 insertions, 14 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f4a90876418..88eb4ec1014 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1394,13 +1394,16 @@ impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
     #[inline]
     pub fn is_uninhabited_recurse(&'tcx self,
                                   visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
+                                  block: Option<NodeId>,
                                   cx: TyCtxt<'a, 'gcx, 'tcx>,
                                   substs: &'tcx Substs<'tcx>) -> bool {
         match visited.entry((self.did, substs)) {
             hash_map::Entry::Occupied(_) => return false,
             hash_map::Entry::Vacant(ve) => ve.insert(()),
         };
-        self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union()))
+        self.variants.iter().all(|v| {
+            v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union())
+        })
     }
 }
 
@@ -1809,13 +1812,14 @@ impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
     #[inline]
     pub fn is_uninhabited_recurse(&'tcx self,
                                   visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
+                                  block: Option<NodeId>,
                                   cx: TyCtxt<'a, 'gcx, 'tcx>,
                                   substs: &'tcx Substs<'tcx>,
                                   is_union: bool) -> bool {
         if is_union {
-            self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, cx, substs))
+            self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
         } else {
-            self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs))
+            self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
         }
     }
 }
@@ -1849,9 +1853,11 @@ impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
     #[inline]
     pub fn is_uninhabited_recurse(&'tcx self,
                                   visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
+                                  block: Option<NodeId>,
                                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                   substs: &'tcx Substs<'tcx>) -> bool {
-        self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx)
+        block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) &&
+        self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
     }
 }
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 39461dc4f74..4e54e3a3630 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -23,7 +23,7 @@ use std::fmt;
 use std::ops;
 use std::collections::HashMap;
 use syntax::abi;
-use syntax::ast::{self, Name};
+use syntax::ast::{self, Name, NodeId};
 use syntax::symbol::{keywords, InternedString};
 
 use serialize;
@@ -930,25 +930,26 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+    /// Checks whether a type is uninhabited.
+    /// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`.
+    pub fn is_uninhabited(&self, block: Option<NodeId>, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
         let mut visited = HashMap::new();
-        self.is_uninhabited_recurse(&mut visited, cx)
+        self.is_uninhabited_recurse(&mut visited, block, cx)
     }
 
     pub fn is_uninhabited_recurse(&self,
                                   visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>,
+                                  block: Option<NodeId>,
                                   cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
-        // FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
-        // more complete.
         match self.sty {
             TyAdt(def, substs) => {
-                def.is_uninhabited_recurse(visited, cx, substs)
+                def.is_uninhabited_recurse(visited, block, cx, substs)
             },
 
             TyNever => true,
-            TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, cx)),
-            TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, cx),
-            TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, cx),
+            TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, block, cx)),
+            TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, block, cx),
+            TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, block, cx),
 
             _ => false,
         }
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index f63a27e0d75..3c94d7d6fd5 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -204,7 +204,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
             // Check for empty enum, because is_useful only works on inhabited types.
             let pat_ty = self.tcx.tables().node_id_to_type(scrut.id);
             if inlined_arms.is_empty() {
-                if !pat_ty.is_uninhabited(self.tcx) {
+                if !pat_ty.is_uninhabited(Some(scrut.id), self.tcx) {
                     // We know the type is inhabited, so this must be wrong
                     let mut err = create_e0004(self.tcx.sess, span,
                                                format!("non-exhaustive patterns: type {} \