Skip to content

Commit f947890

Browse files
committed
Change file structure, add comments for inhabitedness.rs
1 parent e9ffc40 commit f947890

File tree

3 files changed

+222
-123
lines changed

3 files changed

+222
-123
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::mem;
12+
use rustc_data_structures::small_vec::SmallVec;
13+
use syntax::ast::CRATE_NODE_ID;
14+
use ty::context::TyCtxt;
15+
use ty::{DefId, DefIdTree};
16+
17+
/// Represents a forest of DefIds closed under the ancestor relation. That is,
18+
/// if a DefId representing a module is contained in the forest then all
19+
/// DefIds defined in that module or submodules are also implicitly contained
20+
/// in the forest.
21+
///
22+
/// This is used to represent a set of modules in which a type is visibly
23+
/// uninhabited.
24+
#[derive(Clone)]
25+
pub struct DefIdForest {
26+
/// The minimal set of DefIds required to represent the whole set.
27+
/// If A and B are DefIds in the DefIdForest, and A is a desecendant
28+
/// of B, then only B will be in root_ids.
29+
/// We use a SmallVec here because (for its use for cacheing inhabitedness)
30+
/// its rare that this will contain even two ids.
31+
root_ids: SmallVec<[DefId; 1]>,
32+
}
33+
34+
impl<'a, 'gcx, 'tcx> DefIdForest {
35+
/// Create an empty forest.
36+
pub fn empty() -> DefIdForest {
37+
DefIdForest {
38+
root_ids: SmallVec::new(),
39+
}
40+
}
41+
42+
/// Create a forest consisting of a single tree representing the entire
43+
/// crate.
44+
#[inline]
45+
pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
46+
let crate_id = tcx.map.local_def_id(CRATE_NODE_ID);
47+
DefIdForest::from_id(crate_id)
48+
}
49+
50+
/// Create a forest containing a DefId and all its descendants.
51+
pub fn from_id(id: DefId) -> DefIdForest {
52+
let mut root_ids = SmallVec::new();
53+
root_ids.push(id);
54+
DefIdForest {
55+
root_ids: root_ids,
56+
}
57+
}
58+
59+
/// Test whether the forest is empty.
60+
pub fn is_empty(&self) -> bool {
61+
self.root_ids.is_empty()
62+
}
63+
64+
/// Test whether the forest conains a given DefId.
65+
pub fn contains(&self,
66+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
67+
id: DefId) -> bool
68+
{
69+
for root_id in self.root_ids.iter() {
70+
if tcx.is_descendant_of(id, *root_id) {
71+
return true;
72+
}
73+
}
74+
false
75+
}
76+
77+
/// Calculate the intersection of a collection of forests.
78+
pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
79+
iter: I) -> DefIdForest
80+
where I: IntoIterator<Item=DefIdForest>
81+
{
82+
let mut ret = DefIdForest::full(tcx);
83+
let mut next_ret = SmallVec::new();
84+
let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
85+
for next_forest in iter {
86+
for id in ret.root_ids.drain(..) {
87+
if next_forest.contains(tcx, id) {
88+
next_ret.push(id);
89+
} else {
90+
old_ret.push(id);
91+
}
92+
}
93+
ret.root_ids.extend(old_ret.drain(..));
94+
95+
for id in next_forest.root_ids {
96+
if ret.contains(tcx, id) {
97+
next_ret.push(id);
98+
}
99+
}
100+
101+
mem::swap(&mut next_ret, &mut ret.root_ids);
102+
next_ret.drain(..);
103+
}
104+
ret
105+
}
106+
107+
/// Calculate the union of a collection of forests.
108+
pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
109+
iter: I) -> DefIdForest
110+
where I: IntoIterator<Item=DefIdForest>
111+
{
112+
let mut ret = DefIdForest::empty();
113+
let mut next_ret = SmallVec::new();
114+
for next_forest in iter {
115+
for id in ret.root_ids.drain(..) {
116+
if !next_forest.contains(tcx, id) {
117+
next_ret.push(id);
118+
}
119+
}
120+
121+
for id in next_forest.root_ids {
122+
if !next_ret.contains(&id) {
123+
next_ret.push(id);
124+
}
125+
}
126+
127+
mem::swap(&mut next_ret, &mut ret.root_ids);
128+
next_ret.drain(..);
129+
}
130+
ret
131+
}
132+
}
133+

src/librustc/ty/inhabitedness.rs renamed to src/librustc/ty/inhabitedness/mod.rs

Lines changed: 48 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -8,127 +8,59 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::mem;
12-
use rustc_data_structures::small_vec::SmallVec;
13-
use syntax::ast::CRATE_NODE_ID;
1411
use util::nodemap::FxHashSet;
1512
use ty::context::TyCtxt;
1613
use ty::{AdtDef, VariantDef, FieldDef, TyS};
1714
use ty::{DefId, Substs};
18-
use ty::{AdtKind, Visibility, DefIdTree};
15+
use ty::{AdtKind, Visibility};
1916
use ty::TypeVariants::*;
2017

21-
/// Represents a set of DefIds closed under the ancestor relation. That is, if
22-
/// a DefId is in this set then so are all its descendants.
23-
#[derive(Clone)]
24-
pub struct DefIdForest {
25-
/// The minimal set of DefIds required to represent the whole set.
26-
/// If A and B are DefIds in the DefIdForest, and A is a desecendant
27-
/// of B, then only B will be in root_ids.
28-
/// We use a SmallVec here because (for its use in this module) its rare
29-
/// that this will contain even two ids.
30-
root_ids: SmallVec<[DefId; 1]>,
31-
}
32-
33-
impl<'a, 'gcx, 'tcx> DefIdForest {
34-
/// Create an empty forest.
35-
pub fn empty() -> DefIdForest {
36-
DefIdForest {
37-
root_ids: SmallVec::new(),
38-
}
39-
}
40-
41-
/// Create a forest consisting of a single tree representing the entire
42-
/// crate.
43-
#[inline]
44-
pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
45-
let crate_id = tcx.map.local_def_id(CRATE_NODE_ID);
46-
DefIdForest::from_id(crate_id)
47-
}
48-
49-
/// Create a forest containing a DefId and all its descendants.
50-
pub fn from_id(id: DefId) -> DefIdForest {
51-
let mut root_ids = SmallVec::new();
52-
root_ids.push(id);
53-
DefIdForest {
54-
root_ids: root_ids,
55-
}
56-
}
57-
58-
/// Test whether the forest is empty.
59-
pub fn is_empty(&self) -> bool {
60-
self.root_ids.is_empty()
61-
}
62-
63-
/// Test whether the forest conains a given DefId.
64-
pub fn contains(&self,
65-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
66-
id: DefId) -> bool
67-
{
68-
for root_id in self.root_ids.iter() {
69-
if tcx.is_descendant_of(id, *root_id) {
70-
return true;
71-
}
72-
}
73-
false
74-
}
75-
76-
/// Calculate the intersection of a collection of forests.
77-
pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
78-
iter: I) -> DefIdForest
79-
where I: IntoIterator<Item=DefIdForest>
80-
{
81-
let mut ret = DefIdForest::full(tcx);
82-
let mut next_ret = SmallVec::new();
83-
let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
84-
for next_forest in iter {
85-
for id in ret.root_ids.drain(..) {
86-
if next_forest.contains(tcx, id) {
87-
next_ret.push(id);
88-
} else {
89-
old_ret.push(id);
90-
}
91-
}
92-
ret.root_ids.extend(old_ret.drain(..));
18+
pub use self::def_id_forest::DefIdForest;
9319

94-
for id in next_forest.root_ids {
95-
if ret.contains(tcx, id) {
96-
next_ret.push(id);
97-
}
98-
}
99-
100-
mem::swap(&mut next_ret, &mut ret.root_ids);
101-
next_ret.drain(..);
102-
}
103-
ret
104-
}
20+
mod def_id_forest;
10521

106-
/// Calculate the union of a collection of forests.
107-
pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
108-
iter: I) -> DefIdForest
109-
where I: IntoIterator<Item=DefIdForest>
110-
{
111-
let mut ret = DefIdForest::empty();
112-
let mut next_ret = SmallVec::new();
113-
for next_forest in iter {
114-
for id in ret.root_ids.drain(..) {
115-
if !next_forest.contains(tcx, id) {
116-
next_ret.push(id);
117-
}
118-
}
119-
120-
for id in next_forest.root_ids {
121-
if !next_ret.contains(&id) {
122-
next_ret.push(id);
123-
}
124-
}
125-
126-
mem::swap(&mut next_ret, &mut ret.root_ids);
127-
next_ret.drain(..);
128-
}
129-
ret
130-
}
131-
}
22+
// The methods in this module calculate DefIdForests of modules in which a
23+
// AdtDef/VariantDef/FieldDef is visibly uninhabited.
24+
//
25+
// # Example
26+
// ```rust
27+
// enum Void {}
28+
// mod a {
29+
// pub mod b {
30+
// pub struct SecretlyUninhabited {
31+
// _priv: !,
32+
// }
33+
// }
34+
// }
35+
//
36+
// mod c {
37+
// pub struct AlsoSecretlyUninhabited {
38+
// _priv: Void,
39+
// }
40+
// mod d {
41+
// }
42+
// }
43+
//
44+
// struct Foo {
45+
// x: a::b::SecretlyUninhabited,
46+
// y: c::AlsoSecretlyUninhabited,
47+
// }
48+
// ```
49+
// In this code, the type Foo will only be visibly uninhabited inside the
50+
// modules b, c and d. Calling uninhabited_from on Foo or its AdtDef will
51+
// return the forest of modules {b, c->d} (represented in a DefIdForest by the
52+
// set {b, c})
53+
//
54+
// We need this information for pattern-matching on Foo or types that contain
55+
// Foo.
56+
//
57+
// # Example
58+
// ```rust
59+
// let foo_result: Result<T, Foo> = ... ;
60+
// let Ok(t) = foo_result;
61+
// ```
62+
// This code should only compile in modules where the uninhabitedness of Foo is
63+
// visible.
13264

13365
impl<'a, 'gcx, 'tcx> AdtDef {
13466
/// Calculate the forest of DefIds from which this adt is visibly uninhabited.
@@ -189,6 +121,9 @@ impl<'a, 'gcx, 'tcx> FieldDef {
189121
is_enum: bool) -> DefIdForest
190122
{
191123
let mut data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(visited, tcx);
124+
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with
125+
// Visibility::Invisible so we need to override self.vis if we're
126+
// dealing with an enum.
192127
if is_enum {
193128
data_uninhabitedness()
194129
} else {

src/librustc/ty/sty.rs

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -980,20 +980,51 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
980980
}
981981

982982
/// Checks whether a type is visibly uninhabited from a particular module.
983+
/// # Example
984+
/// ```rust
985+
/// enum Void {}
986+
/// mod a {
987+
/// pub mod b {
988+
/// pub struct SecretlyUninhabited {
989+
/// _priv: !,
990+
/// }
991+
/// }
992+
/// }
993+
///
994+
/// mod c {
995+
/// pub struct AlsoSecretlyUninhabited {
996+
/// _priv: Void,
997+
/// }
998+
/// mod d {
999+
/// }
1000+
/// }
1001+
///
1002+
/// struct Foo {
1003+
/// x: a::b::SecretlyUninhabited,
1004+
/// y: c::AlsoSecretlyUninhabited,
1005+
/// }
1006+
/// ```
1007+
/// In this code, the type `Foo` will only be visibly uninhabited inside the
1008+
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
1009+
/// contain `Foo`.
1010+
///
1011+
/// # Example
1012+
/// ```rust
1013+
/// let foo_result: Result<T, Foo> = ... ;
1014+
/// let Ok(t) = foo_result;
1015+
/// ```
1016+
/// This code should only compile in modules where the uninhabitedness of Foo is
1017+
/// visible.
9831018
pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
9841019
let mut visited = FxHashSet::default();
9851020
let forest = self.uninhabited_from(&mut visited, tcx);
986-
forest.contains(tcx, module)
987-
}
9881021

989-
/// Checks whether a type is uninhabited.
990-
/// Note: just because a type is uninhabited, that doesn't mean that it's
991-
/// *visibly* uninhabited outside its module. You sometimes may want
992-
/// `is_uninhabited_from` instead.
993-
pub fn is_uninhabited_anywhere(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
994-
let mut visited = FxHashSet::default();
995-
let node_set = self.uninhabited_from(&mut visited, tcx);
996-
!node_set.is_empty()
1022+
// To check whether this type is uninhabited at all (not just from the
1023+
// given node) you could check whether the forest is empty.
1024+
// ```
1025+
// forest.is_empty()
1026+
// ```
1027+
forest.contains(tcx, module)
9971028
}
9981029

9991030
pub fn is_primitive(&self) -> bool {

0 commit comments

Comments
 (0)