Skip to content

Commit a5673de

Browse files
committed
refactor inhabitedness to have clearer public entry points
1 parent abe7c87 commit a5673de

File tree

5 files changed

+100
-86
lines changed

5 files changed

+100
-86
lines changed

src/librustc/ty/inhabitedness/mod.rs

Lines changed: 90 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use util::nodemap::{FxHashMap, FxHashSet};
1212
use ty::context::TyCtxt;
13-
use ty::{AdtDef, VariantDef, FieldDef, TyS};
13+
use ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
1414
use ty::{DefId, Substs};
1515
use ty::{AdtKind, Visibility};
1616
use ty::TypeVariants::*;
@@ -62,13 +62,81 @@ mod def_id_forest;
6262
// This code should only compile in modules where the uninhabitedness of Foo is
6363
// visible.
6464

65+
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
66+
/// Checks whether a type is visibly uninhabited from a particular module.
67+
/// # Example
68+
/// ```rust
69+
/// enum Void {}
70+
/// mod a {
71+
/// pub mod b {
72+
/// pub struct SecretlyUninhabited {
73+
/// _priv: !,
74+
/// }
75+
/// }
76+
/// }
77+
///
78+
/// mod c {
79+
/// pub struct AlsoSecretlyUninhabited {
80+
/// _priv: Void,
81+
/// }
82+
/// mod d {
83+
/// }
84+
/// }
85+
///
86+
/// struct Foo {
87+
/// x: a::b::SecretlyUninhabited,
88+
/// y: c::AlsoSecretlyUninhabited,
89+
/// }
90+
/// ```
91+
/// In this code, the type `Foo` will only be visibly uninhabited inside the
92+
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
93+
/// contain `Foo`.
94+
///
95+
/// # Example
96+
/// ```rust
97+
/// let foo_result: Result<T, Foo> = ... ;
98+
/// let Ok(t) = foo_result;
99+
/// ```
100+
/// This code should only compile in modules where the uninhabitedness of Foo is
101+
/// visible.
102+
pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
103+
let forest = ty.uninhabited_from(&mut FxHashMap(), self);
104+
105+
// To check whether this type is uninhabited at all (not just from the
106+
// given node) you could check whether the forest is empty.
107+
// ```
108+
// forest.is_empty()
109+
// ```
110+
forest.contains(self, module)
111+
}
112+
113+
pub fn is_enum_variant_uninhabited_from(self,
114+
module: DefId,
115+
variant: &'tcx VariantDef,
116+
substs: &'tcx Substs<'tcx>)
117+
-> bool
118+
{
119+
let adt_kind = AdtKind::Enum;
120+
variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).contains(self, module)
121+
}
122+
123+
pub fn is_variant_uninhabited_from_all_modules(self,
124+
variant: &'tcx VariantDef,
125+
substs: &'tcx Substs<'tcx>,
126+
adt_kind: AdtKind)
127+
-> bool
128+
{
129+
!variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).is_empty()
130+
}
131+
}
132+
65133
impl<'a, 'gcx, 'tcx> AdtDef {
66134
/// Calculate the forest of DefIds from which this adt is visibly uninhabited.
67-
pub fn uninhabited_from(
68-
&self,
69-
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
70-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
71-
substs: &'tcx Substs<'tcx>) -> DefIdForest
135+
fn uninhabited_from(
136+
&self,
137+
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
138+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
139+
substs: &'tcx Substs<'tcx>) -> DefIdForest
72140
{
73141
DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
74142
v.uninhabited_from(visited, tcx, substs, self.adt_kind())
@@ -78,12 +146,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
78146

79147
impl<'a, 'gcx, 'tcx> VariantDef {
80148
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
81-
pub fn uninhabited_from(
82-
&self,
83-
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
84-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
85-
substs: &'tcx Substs<'tcx>,
86-
adt_kind: AdtKind) -> DefIdForest
149+
fn uninhabited_from(
150+
&self,
151+
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
152+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
153+
substs: &'tcx Substs<'tcx>,
154+
adt_kind: AdtKind) -> DefIdForest
87155
{
88156
match adt_kind {
89157
AdtKind::Union => {
@@ -107,12 +175,12 @@ impl<'a, 'gcx, 'tcx> VariantDef {
107175

108176
impl<'a, 'gcx, 'tcx> FieldDef {
109177
/// Calculate the forest of DefIds from which this field is visibly uninhabited.
110-
pub fn uninhabited_from(
111-
&self,
112-
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
113-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
114-
substs: &'tcx Substs<'tcx>,
115-
is_enum: bool) -> DefIdForest
178+
fn uninhabited_from(
179+
&self,
180+
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
181+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
182+
substs: &'tcx Substs<'tcx>,
183+
is_enum: bool) -> DefIdForest
116184
{
117185
let mut data_uninhabitedness = move || {
118186
self.ty(tcx, substs).uninhabited_from(visited, tcx)
@@ -138,10 +206,10 @@ impl<'a, 'gcx, 'tcx> FieldDef {
138206

139207
impl<'a, 'gcx, 'tcx> TyS<'tcx> {
140208
/// Calculate the forest of DefIds from which this type is visibly uninhabited.
141-
pub fn uninhabited_from(
142-
&self,
143-
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
144-
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
209+
fn uninhabited_from(
210+
&self,
211+
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
212+
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
145213
{
146214
match tcx.lift_to_global(&self) {
147215
Some(global_ty) => {

src/librustc/ty/sty.rs

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use std::cmp::Ordering;
2424
use syntax::abi;
2525
use syntax::ast::{self, Name};
2626
use syntax::symbol::keywords;
27-
use util::nodemap::FxHashMap;
2827

2928
use serialize;
3029

@@ -1070,54 +1069,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
10701069
}
10711070
}
10721071

1073-
/// Checks whether a type is visibly uninhabited from a particular module.
1074-
/// # Example
1075-
/// ```rust
1076-
/// enum Void {}
1077-
/// mod a {
1078-
/// pub mod b {
1079-
/// pub struct SecretlyUninhabited {
1080-
/// _priv: !,
1081-
/// }
1082-
/// }
1083-
/// }
1084-
///
1085-
/// mod c {
1086-
/// pub struct AlsoSecretlyUninhabited {
1087-
/// _priv: Void,
1088-
/// }
1089-
/// mod d {
1090-
/// }
1091-
/// }
1092-
///
1093-
/// struct Foo {
1094-
/// x: a::b::SecretlyUninhabited,
1095-
/// y: c::AlsoSecretlyUninhabited,
1096-
/// }
1097-
/// ```
1098-
/// In this code, the type `Foo` will only be visibly uninhabited inside the
1099-
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
1100-
/// contain `Foo`.
1101-
///
1102-
/// # Example
1103-
/// ```rust
1104-
/// let foo_result: Result<T, Foo> = ... ;
1105-
/// let Ok(t) = foo_result;
1106-
/// ```
1107-
/// This code should only compile in modules where the uninhabitedness of Foo is
1108-
/// visible.
1109-
pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
1110-
let mut visited = FxHashMap::default();
1111-
let forest = self.uninhabited_from(&mut visited, tcx);
1112-
1113-
// To check whether this type is uninhabited at all (not just from the
1114-
// given node) you could check whether the forest is empty.
1115-
// ```
1116-
// forest.is_empty()
1117-
// ```
1118-
forest.contains(tcx, module)
1119-
}
1120-
11211072
pub fn is_primitive(&self) -> bool {
11221073
match self.sty {
11231074
TyBool | TyChar | TyInt(_) | TyUint(_) | TyFloat(_) => true,

src/librustc_const_eval/_match.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use pattern::{PatternFoldable, PatternFolder};
2525

2626
use rustc::hir::def_id::DefId;
2727
use rustc::hir::RangeEnd;
28-
use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
28+
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2929

3030
use rustc::mir::Field;
3131
use rustc::util::common::ErrorReported;
@@ -202,21 +202,19 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
202202

203203
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
204204
if self.tcx.sess.features.borrow().never_type {
205-
ty.is_uninhabited_from(self.module, self.tcx)
205+
self.tcx.is_ty_uninhabited_from(self.module, ty)
206206
} else {
207207
false
208208
}
209209
}
210210

211211
fn is_variant_uninhabited(&self,
212212
variant: &'tcx ty::VariantDef,
213-
substs: &'tcx ty::subst::Substs<'tcx>) -> bool
213+
substs: &'tcx ty::subst::Substs<'tcx>)
214+
-> bool
214215
{
215216
if self.tcx.sess.features.borrow().never_type {
216-
let forest = variant.uninhabited_from(
217-
&mut FxHashMap::default(), self.tcx, substs, AdtKind::Enum
218-
);
219-
forest.contains(self.tcx, self.module)
217+
self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
220218
} else {
221219
false
222220
}

src/librustc_const_eval/check_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
192192
let module = self.tcx.hir.get_module_parent(scrut.id);
193193
if inlined_arms.is_empty() {
194194
let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
195-
pat_ty.is_uninhabited_from(module, self.tcx)
195+
self.tcx.is_ty_uninhabited_from(module, pat_ty)
196196
} else {
197197
self.conservative_is_uninhabited(pat_ty)
198198
};

src/librustc_mir/build/matches/simplify.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use build::{BlockAnd, BlockAndExtension, Builder};
2626
use build::matches::{Binding, MatchPair, Candidate};
2727
use hair::*;
2828
use rustc::mir::*;
29-
use rustc_data_structures::fx::FxHashMap;
3029

3130
use std::mem;
3231

@@ -102,12 +101,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
102101
if self.hir.tcx().sess.features.borrow().never_type {
103102
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
104103
i == variant_index || {
105-
let mut visited = FxHashMap::default();
106-
let node_set = v.uninhabited_from(&mut visited,
107-
self.hir.tcx(),
108-
substs,
109-
adt_def.adt_kind());
110-
!node_set.is_empty()
104+
let adt_kind = adt_def.adt_kind();
105+
self.hir.tcx().is_variant_uninhabited_from_all_modules(v,
106+
substs,
107+
adt_kind)
111108
}
112109
});
113110
if irrefutable {

0 commit comments

Comments
 (0)