Skip to content

Commit 3f5c311

Browse files
committed
rustc: simplify TypeContents drastically.
1 parent fa6b50f commit 3f5c311

File tree

2 files changed

+42
-148
lines changed

2 files changed

+42
-148
lines changed

src/librustc/ty/contents.rs

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

11-
use hir::def_id::{DefId};
1211
use ty::{self, Ty, TyCtxt};
1312
use util::common::MemoizationMap;
1413
use util::nodemap::FxHashMap;
1514

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,
6429
}
6530
}
6631

6732
impl TypeContents {
6833
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()}
7835
}
7936

8037
pub fn interior_unsafe(&self) -> bool {
81-
self.intersects(TC::InteriorUnsafe)
38+
self.intersects(TypeContents::INTERIOR_UNSAFE)
8239
}
8340

8441
pub fn needs_drop(&self, _: TyCtxt) -> bool {
85-
self.intersects(TC::OwnsDtor)
42+
self.intersects(TypeContents::OWNS_DTOR)
8643
}
8744

8845
pub fn union<I, T, F>(v: I, mut f: F) -> TypeContents where
8946
I: IntoIterator<Item=T>,
9047
F: FnMut(T) -> TypeContents,
9148
{
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))
12350
}
12451
}
12552

@@ -139,52 +66,34 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
13966
//
14067
// When computing the type contents of such a type, we wind up deeply
14168
// 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
14370
// patch up the cache with the correct value, once we've computed it
14471
// (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.
14673
//
14774
// The problem is, as we are doing the computation, we will also
14875
// 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
15077
// 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()
15279
// which is incorrect. This value was computed based on the crutch
15380
// 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.
15582
if let Some(tc) = cache.get(&ty) {
15683
return *tc;
15784
}
15885
// Must check both caches!
15986
if let Some(tc) = tcx.tc_cache.borrow().get(&ty) {
16087
return *tc;
16188
}
162-
cache.insert(ty, TC::None);
89+
cache.insert(ty, TypeContents::empty());
16390

16491
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
17192
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
17293
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(),
18897

18998
ty::TyArray(ty, _) => {
19099
tc_ty(tcx, ty, cache)
@@ -193,7 +102,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
193102
ty::TySlice(ty) => {
194103
tc_ty(tcx, ty, cache)
195104
}
196-
ty::TyStr => TC::None,
197105

198106
ty::TyClosure(def_id, ref substs) => {
199107
TypeContents::union(
@@ -207,29 +115,25 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
207115
}
208116

209117
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())
227129
}
228130

131+
132+
ty::TyDynamic(..) |
229133
ty::TyProjection(..) |
230134
ty::TyParam(_) |
231135
ty::TyAnon(..) => {
232-
TC::All
136+
TypeContents::INTERIOR_UNSAFE | TypeContents::OWNS_DTOR
233137
}
234138

235139
ty::TyInfer(_) |
@@ -241,15 +145,5 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
241145
cache.insert(ty, result);
242146
result
243147
}
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-
}
254148
}
255149
}

src/librustc/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2405,7 +2405,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
24052405
// destructor (e.g. zero its memory on move).
24062406

24072407
let contents = ty.type_contents(tcx);
2408-
debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
2408+
debug!("type_needs_drop ty={:?} contents={:?}", ty, contents.bits());
24092409
contents.needs_drop(tcx)
24102410
}
24112411

0 commit comments

Comments
 (0)