8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use hir:: def_id:: { DefId } ;
12
11
use ty:: { self , Ty , TyCtxt } ;
13
12
use util:: common:: MemoizationMap ;
14
13
use util:: nodemap:: FxHashMap ;
15
14
16
- use std:: fmt;
17
- use std:: ops;
18
-
19
- use syntax:: ast;
20
-
21
- /// Type contents is how the type checker reasons about kinds.
22
- /// They track what kinds of things are found within a type. You can
23
- /// think of them as kind of an "anti-kind". They track the kinds of values
24
- /// and thinks that are contained in types. Having a larger contents for
25
- /// a type tends to rule that type *out* from various kinds. For example,
26
- /// a type that contains a reference is not sendable.
27
- ///
28
- /// The reason we compute type contents and not kinds is that it is
29
- /// easier for me (nmatsakis) to think about what is contained within
30
- /// a type than to think about what is *not* contained within a type.
31
- #[ derive( Clone , Copy ) ]
32
- pub struct TypeContents {
33
- pub bits : u64
34
- }
35
-
36
- macro_rules! def_type_content_sets {
37
- ( mod $mname: ident { $( $name: ident = $bits: expr) ,+ } ) => {
38
- #[ allow( non_snake_case) ]
39
- mod $mname {
40
- use super :: TypeContents ;
41
- $(
42
- #[ allow( non_upper_case_globals) ]
43
- pub const $name: TypeContents = TypeContents { bits: $bits } ;
44
- ) +
45
- }
46
- }
47
- }
48
-
49
- def_type_content_sets ! {
50
- mod TC {
51
- None = 0b0000_0000__0000_0000__0000 ,
52
-
53
- // Things that are interior to the value (first nibble):
54
- InteriorUnsafe = 0b0000_0000__0000_0000__0010 ,
55
- InteriorParam = 0b0000_0000__0000_0000__0100 ,
56
- // InteriorAll = 0b00000000__00000000__1111,
57
-
58
- // Things that are owned by the value (second and third nibbles):
59
- OwnsDtor = 0b0000_0000__0000_0010__0000 ,
60
- // OwnsAll = 0b0000_0000__1111_1111__0000,
61
-
62
- // All bits
63
- All = 0b1111_1111__1111_1111__1111
15
+ bitflags ! {
16
+ /// Type contents is how the type checker reasons about kinds.
17
+ /// They track what kinds of things are found within a type. You can
18
+ /// think of them as kind of an "anti-kind". They track the kinds of values
19
+ /// and thinks that are contained in types. Having a larger contents for
20
+ /// a type tends to rule that type *out* from various kinds. For example,
21
+ /// a type that contains a reference is not sendable.
22
+ ///
23
+ /// The reason we compute type contents and not kinds is that it is
24
+ /// easier for me (nmatsakis) to think about what is contained within
25
+ /// a type than to think about what is *not* contained within a type.
26
+ flags TypeContents : u8 {
27
+ const INTERIOR_UNSAFE = 0b01 ,
28
+ const OWNS_DTOR = 0b10 ,
64
29
}
65
30
}
66
31
67
32
impl TypeContents {
68
33
pub fn when ( & self , cond : bool ) -> TypeContents {
69
- if cond { * self } else { TC :: None }
70
- }
71
-
72
- pub fn intersects ( & self , tc : TypeContents ) -> bool {
73
- ( self . bits & tc. bits ) != 0
74
- }
75
-
76
- pub fn interior_param ( & self ) -> bool {
77
- self . intersects ( TC :: InteriorParam )
34
+ if cond { * self } else { TypeContents :: empty ( ) }
78
35
}
79
36
80
37
pub fn interior_unsafe ( & self ) -> bool {
81
- self . intersects ( TC :: InteriorUnsafe )
38
+ self . intersects ( TypeContents :: INTERIOR_UNSAFE )
82
39
}
83
40
84
41
pub fn needs_drop ( & self , _: TyCtxt ) -> bool {
85
- self . intersects ( TC :: OwnsDtor )
42
+ self . intersects ( TypeContents :: OWNS_DTOR )
86
43
}
87
44
88
45
pub fn union < I , T , F > ( v : I , mut f : F ) -> TypeContents where
89
46
I : IntoIterator < Item =T > ,
90
47
F : FnMut ( T ) -> TypeContents ,
91
48
{
92
- v. into_iter ( ) . fold ( TC :: None , |tc, ty| tc | f ( ty) )
93
- }
94
- }
95
-
96
- impl ops:: BitOr for TypeContents {
97
- type Output = TypeContents ;
98
-
99
- fn bitor ( self , other : TypeContents ) -> TypeContents {
100
- TypeContents { bits : self . bits | other. bits }
101
- }
102
- }
103
-
104
- impl ops:: BitAnd for TypeContents {
105
- type Output = TypeContents ;
106
-
107
- fn bitand ( self , other : TypeContents ) -> TypeContents {
108
- TypeContents { bits : self . bits & other. bits }
109
- }
110
- }
111
-
112
- impl ops:: Sub for TypeContents {
113
- type Output = TypeContents ;
114
-
115
- fn sub ( self , other : TypeContents ) -> TypeContents {
116
- TypeContents { bits : self . bits & !other. bits }
117
- }
118
- }
119
-
120
- impl fmt:: Debug for TypeContents {
121
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
122
- write ! ( f, "TypeContents({:b})" , self . bits)
49
+ v. into_iter ( ) . fold ( TypeContents :: empty ( ) , |tc, ty| tc | f ( ty) )
123
50
}
124
51
}
125
52
@@ -139,52 +66,34 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
139
66
//
140
67
// When computing the type contents of such a type, we wind up deeply
141
68
// recursing as we go. So when we encounter the recursive reference
142
- // to List, we temporarily use TC::None as its contents. Later we'll
69
+ // to List, we temporarily use TypeContents::empty() as its contents. Later we'll
143
70
// patch up the cache with the correct value, once we've computed it
144
71
// (this is basically a co-inductive process, if that helps). So in
145
- // the end we'll compute TC ::OwnsOwned, in this case.
72
+ // the end we'll compute TypeContents ::OwnsOwned, in this case.
146
73
//
147
74
// The problem is, as we are doing the computation, we will also
148
75
// compute an *intermediate* contents for, e.g., Option<List> of
149
- // TC::None . This is ok during the computation of List itself, but if
76
+ // TypeContents::empty() . This is ok during the computation of List itself, but if
150
77
// we stored this intermediate value into tcx.tc_cache, then later
151
- // requests for the contents of Option<List> would also yield TC::None
78
+ // requests for the contents of Option<List> would also yield TypeContents::empty()
152
79
// which is incorrect. This value was computed based on the crutch
153
80
// value for the type contents of list. The correct value is
154
- // TC ::OwnsOwned. This manifested as issue #4821.
81
+ // TypeContents ::OwnsOwned. This manifested as issue #4821.
155
82
if let Some ( tc) = cache. get ( & ty) {
156
83
return * tc;
157
84
}
158
85
// Must check both caches!
159
86
if let Some ( tc) = tcx. tc_cache . borrow ( ) . get ( & ty) {
160
87
return * tc;
161
88
}
162
- cache. insert ( ty, TC :: None ) ;
89
+ cache. insert ( ty, TypeContents :: empty ( ) ) ;
163
90
164
91
let result = match ty. sty {
165
- // usize and isize are ffi-unsafe
166
- ty:: TyUint ( ast:: UintTy :: Us ) | ty:: TyInt ( ast:: IntTy :: Is ) => {
167
- TC :: None
168
- }
169
-
170
- // Scalar and unique types are sendable, and durable
171
92
ty:: TyInfer ( ty:: FreshIntTy ( _) ) | ty:: TyInfer ( ty:: FreshFloatTy ( _) ) |
172
93
ty:: TyBool | ty:: TyInt ( _) | ty:: TyUint ( _) | ty:: TyFloat ( _) | ty:: TyNever |
173
- ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) | ty:: TyChar => {
174
- TC :: None
175
- }
176
-
177
- ty:: TyDynamic ( ..) => {
178
- TC :: All - TC :: InteriorParam
179
- }
180
-
181
- ty:: TyRawPtr ( _) => {
182
- TC :: None
183
- }
184
-
185
- ty:: TyRef ( ..) => {
186
- TC :: None
187
- }
94
+ ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) | ty:: TyChar |
95
+ ty:: TyRawPtr ( _) | ty:: TyRef ( ..) |
96
+ ty:: TyStr => TypeContents :: empty ( ) ,
188
97
189
98
ty:: TyArray ( ty, _) => {
190
99
tc_ty ( tcx, ty, cache)
@@ -193,7 +102,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
193
102
ty:: TySlice ( ty) => {
194
103
tc_ty ( tcx, ty, cache)
195
104
}
196
- ty:: TyStr => TC :: None ,
197
105
198
106
ty:: TyClosure ( def_id, ref substs) => {
199
107
TypeContents :: union (
@@ -207,29 +115,25 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
207
115
}
208
116
209
117
ty:: TyAdt ( def, substs) => {
210
- let mut res =
211
- TypeContents :: union ( & def. variants , |v| {
212
- TypeContents :: union ( & v. fields , |f| {
213
- tc_ty ( tcx, f. ty ( tcx, substs) , cache)
214
- } )
215
- } ) ;
216
-
217
- if def. is_union ( ) {
218
- // unions don't have destructors regardless of the child types
219
- res = res - TC :: OwnsDtor ;
220
- }
221
-
222
- if def. has_dtor ( tcx) {
223
- res = res | TC :: OwnsDtor ;
224
- }
225
-
226
- apply_lang_items ( tcx, def. did , res)
118
+ TypeContents :: union ( & def. variants , |v| {
119
+ TypeContents :: union ( & v. fields , |f| {
120
+ tc_ty ( tcx, f. ty ( tcx, substs) , cache)
121
+ } )
122
+ } )
123
+
124
+ // unions don't have destructors regardless of the child types
125
+ - TypeContents :: OWNS_DTOR . when ( def. is_union ( ) )
126
+ | TypeContents :: OWNS_DTOR . when ( def. has_dtor ( tcx) )
127
+ | TypeContents :: INTERIOR_UNSAFE . when (
128
+ Some ( def. did ) == tcx. lang_items . unsafe_cell_type ( ) )
227
129
}
228
130
131
+
132
+ ty:: TyDynamic ( ..) |
229
133
ty:: TyProjection ( ..) |
230
134
ty:: TyParam ( _) |
231
135
ty:: TyAnon ( ..) => {
232
- TC :: All
136
+ TypeContents :: INTERIOR_UNSAFE | TypeContents :: OWNS_DTOR
233
137
}
234
138
235
139
ty:: TyInfer ( _) |
@@ -241,15 +145,5 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
241
145
cache. insert ( ty, result) ;
242
146
result
243
147
}
244
-
245
- fn apply_lang_items < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
246
- did : DefId , tc : TypeContents )
247
- -> TypeContents {
248
- if Some ( did) == tcx. lang_items . unsafe_cell_type ( ) {
249
- tc | TC :: InteriorUnsafe
250
- } else {
251
- tc
252
- }
253
- }
254
148
}
255
149
}
0 commit comments