@@ -62,11 +62,14 @@ 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
+ const ARBITRARY_RECURSION_LIMIT : u32 = 24 ;
66
+
65
67
impl < ' a , ' gcx , ' tcx > AdtDef {
66
68
/// Calculate the forest of DefIds from which this adt is visibly uninhabited.
67
69
pub fn uninhabited_from (
68
70
& self ,
69
71
visited : & mut FxHashSet < ( DefId , & ' tcx Substs < ' tcx > ) > ,
72
+ recursion_depth : u32 ,
70
73
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
71
74
substs : & ' tcx Substs < ' tcx > ) -> DefIdForest
72
75
{
@@ -75,7 +78,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
75
78
}
76
79
77
80
let ret = DefIdForest :: intersection ( tcx, self . variants . iter ( ) . map ( |v| {
78
- v. uninhabited_from ( visited, tcx, substs, self . adt_kind ( ) )
81
+ v. uninhabited_from ( visited, recursion_depth , tcx, substs, self . adt_kind ( ) )
79
82
} ) ) ;
80
83
visited. remove ( & ( self . did , substs) ) ;
81
84
ret
@@ -87,24 +90,25 @@ impl<'a, 'gcx, 'tcx> VariantDef {
87
90
pub fn uninhabited_from (
88
91
& self ,
89
92
visited : & mut FxHashSet < ( DefId , & ' tcx Substs < ' tcx > ) > ,
93
+ recursion_depth : u32 ,
90
94
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
91
95
substs : & ' tcx Substs < ' tcx > ,
92
96
adt_kind : AdtKind ) -> DefIdForest
93
97
{
94
98
match adt_kind {
95
99
AdtKind :: Union => {
96
100
DefIdForest :: intersection ( tcx, self . fields . iter ( ) . map ( |f| {
97
- f. uninhabited_from ( visited, tcx, substs, false )
101
+ f. uninhabited_from ( visited, recursion_depth , tcx, substs, false )
98
102
} ) )
99
103
} ,
100
104
AdtKind :: Struct => {
101
105
DefIdForest :: union ( tcx, self . fields . iter ( ) . map ( |f| {
102
- f. uninhabited_from ( visited, tcx, substs, false )
106
+ f. uninhabited_from ( visited, recursion_depth , tcx, substs, false )
103
107
} ) )
104
108
} ,
105
109
AdtKind :: Enum => {
106
110
DefIdForest :: union ( tcx, self . fields . iter ( ) . map ( |f| {
107
- f. uninhabited_from ( visited, tcx, substs, true )
111
+ f. uninhabited_from ( visited, recursion_depth , tcx, substs, true )
108
112
} ) )
109
113
} ,
110
114
}
@@ -116,11 +120,14 @@ impl<'a, 'gcx, 'tcx> FieldDef {
116
120
pub fn uninhabited_from (
117
121
& self ,
118
122
visited : & mut FxHashSet < ( DefId , & ' tcx Substs < ' tcx > ) > ,
123
+ recursion_depth : u32 ,
119
124
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
120
125
substs : & ' tcx Substs < ' tcx > ,
121
126
is_enum : bool ) -> DefIdForest
122
127
{
123
- let mut data_uninhabitedness = move || self . ty ( tcx, substs) . uninhabited_from ( visited, tcx) ;
128
+ let mut data_uninhabitedness = move || {
129
+ self . ty ( tcx, substs) . uninhabited_from ( visited, recursion_depth, tcx)
130
+ } ;
124
131
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with
125
132
// Visibility::Invisible so we need to override self.vis if we're
126
133
// dealing with an enum.
@@ -145,8 +152,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
145
152
pub fn uninhabited_from (
146
153
& self ,
147
154
visited : & mut FxHashSet < ( DefId , & ' tcx Substs < ' tcx > ) > ,
155
+ mut recursion_depth : u32 ,
148
156
tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> DefIdForest
149
157
{
158
+ recursion_depth += 1 ;
159
+ if recursion_depth >= ARBITRARY_RECURSION_LIMIT {
160
+ return DefIdForest :: empty ( ) ;
161
+ }
162
+
150
163
match tcx. lift_to_global ( & self ) {
151
164
Some ( global_ty) => {
152
165
{
@@ -155,13 +168,13 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
155
168
return forest. clone ( ) ;
156
169
}
157
170
}
158
- let forest = global_ty. uninhabited_from_inner ( visited, tcx) ;
171
+ let forest = global_ty. uninhabited_from_inner ( visited, recursion_depth , tcx) ;
159
172
let mut cache = tcx. inhabitedness_cache . borrow_mut ( ) ;
160
173
cache. insert ( global_ty, forest. clone ( ) ) ;
161
174
forest
162
175
} ,
163
176
None => {
164
- let forest = self . uninhabited_from_inner ( visited, tcx) ;
177
+ let forest = self . uninhabited_from_inner ( visited, recursion_depth , tcx) ;
165
178
forest
166
179
} ,
167
180
}
@@ -170,28 +183,29 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
170
183
fn uninhabited_from_inner (
171
184
& self ,
172
185
visited : & mut FxHashSet < ( DefId , & ' tcx Substs < ' tcx > ) > ,
186
+ recursion_depth : u32 ,
173
187
tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> DefIdForest
174
188
{
175
189
match self . sty {
176
190
TyAdt ( def, substs) => {
177
- def. uninhabited_from ( visited, tcx, substs)
191
+ def. uninhabited_from ( visited, recursion_depth , tcx, substs)
178
192
} ,
179
193
180
194
TyNever => DefIdForest :: full ( tcx) ,
181
195
TyTuple ( ref tys, _) => {
182
196
DefIdForest :: union ( tcx, tys. iter ( ) . map ( |ty| {
183
- ty. uninhabited_from ( visited, tcx)
197
+ ty. uninhabited_from ( visited, recursion_depth , tcx)
184
198
} ) )
185
199
} ,
186
200
TyArray ( ty, len) => {
187
201
if len == 0 {
188
202
DefIdForest :: empty ( )
189
203
} else {
190
- ty. uninhabited_from ( visited, tcx)
204
+ ty. uninhabited_from ( visited, recursion_depth , tcx)
191
205
}
192
206
}
193
207
TyRef ( _, ref tm) => {
194
- tm. ty . uninhabited_from ( visited, tcx)
208
+ tm. ty . uninhabited_from ( visited, recursion_depth , tcx)
195
209
}
196
210
197
211
_ => DefIdForest :: empty ( ) ,
0 commit comments