10
10
11
11
use util:: nodemap:: { FxHashMap , FxHashSet } ;
12
12
use ty:: context:: TyCtxt ;
13
- use ty:: { AdtDef , VariantDef , FieldDef , TyS } ;
13
+ use ty:: { AdtDef , VariantDef , FieldDef , Ty , TyS } ;
14
14
use ty:: { DefId , Substs } ;
15
15
use ty:: { AdtKind , Visibility } ;
16
16
use ty:: TypeVariants :: * ;
@@ -62,13 +62,81 @@ mod def_id_forest;
62
62
// This code should only compile in modules where the uninhabitedness of Foo is
63
63
// visible.
64
64
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
+
65
133
impl < ' a , ' gcx , ' tcx > AdtDef {
66
134
/// 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
72
140
{
73
141
DefIdForest :: intersection ( tcx, self . variants . iter ( ) . map ( |v| {
74
142
v. uninhabited_from ( visited, tcx, substs, self . adt_kind ( ) )
@@ -78,12 +146,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
78
146
79
147
impl < ' a , ' gcx , ' tcx > VariantDef {
80
148
/// 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
87
155
{
88
156
match adt_kind {
89
157
AdtKind :: Union => {
@@ -107,12 +175,12 @@ impl<'a, 'gcx, 'tcx> VariantDef {
107
175
108
176
impl < ' a , ' gcx , ' tcx > FieldDef {
109
177
/// 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
116
184
{
117
185
let mut data_uninhabitedness = move || {
118
186
self . ty ( tcx, substs) . uninhabited_from ( visited, tcx)
@@ -138,10 +206,10 @@ impl<'a, 'gcx, 'tcx> FieldDef {
138
206
139
207
impl < ' a , ' gcx , ' tcx > TyS < ' tcx > {
140
208
/// 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
145
213
{
146
214
match tcx. lift_to_global ( & self ) {
147
215
Some ( global_ty) => {
0 commit comments