]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/contents.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc / ty / contents.rs
CommitLineData
e9174d1e
SL
1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
54a0048b
SL
11use hir::def_id::{DefId};
12use ty::{self, Ty, TyCtxt};
9cc50fc6 13use util::common::MemoizationMap;
476ff2be 14use util::nodemap::FxHashMap;
e9174d1e
SL
15
16use std::fmt;
17use std::ops;
18
b039eaaf 19use syntax::ast;
e9174d1e
SL
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)]
32pub struct TypeContents {
33 pub bits: u64
34}
35
36macro_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
49def_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):
e9174d1e 59 OwnsDtor = 0b0000_0000__0000_0010__0000,
32a655c1 60 // OwnsAll = 0b0000_0000__1111_1111__0000,
e9174d1e
SL
61
62 // All bits
63 All = 0b1111_1111__1111_1111__1111
64 }
65}
66
67impl TypeContents {
68 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
e9174d1e
SL
76 pub fn interior_param(&self) -> bool {
77 self.intersects(TC::InteriorParam)
78 }
79
80 pub fn interior_unsafe(&self) -> bool {
81 self.intersects(TC::InteriorUnsafe)
82 }
83
a7813a04 84 pub fn needs_drop(&self, _: TyCtxt) -> bool {
32a655c1 85 self.intersects(TC::OwnsDtor)
e9174d1e
SL
86 }
87
476ff2be
SL
88 pub fn union<I, T, F>(v: I, mut f: F) -> TypeContents where
89 I: IntoIterator<Item=T>,
90 F: FnMut(T) -> TypeContents,
e9174d1e 91 {
476ff2be 92 v.into_iter().fold(TC::None, |tc, ty| tc | f(ty))
e9174d1e 93 }
e9174d1e
SL
94}
95
96impl 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
104impl 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
112impl 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
120impl fmt::Debug for TypeContents {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 write!(f, "TypeContents({:b})", self.bits)
123 }
124}
125
a7813a04
XL
126impl<'a, 'tcx> ty::TyS<'tcx> {
127 pub fn type_contents(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> TypeContents {
476ff2be 128 return tcx.tc_cache.memoize(self, || tc_ty(tcx, self, &mut FxHashMap()));
e9174d1e 129
a7813a04
XL
130 fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
131 ty: Ty<'tcx>,
476ff2be 132 cache: &mut FxHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
e9174d1e 133 {
a7813a04 134 // Subtle: Note that we are *not* using tcx.tc_cache here but rather a
e9174d1e
SL
135 // private cache for this walk. This is needed in the case of cyclic
136 // types like:
137 //
138 // struct List { next: Box<Option<List>>, ... }
139 //
140 // When computing the type contents of such a type, we wind up deeply
141 // 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
143 // patch up the cache with the correct value, once we've computed it
144 // (this is basically a co-inductive process, if that helps). So in
145 // the end we'll compute TC::OwnsOwned, in this case.
146 //
147 // The problem is, as we are doing the computation, we will also
148 // compute an *intermediate* contents for, e.g., Option<List> of
149 // TC::None. This is ok during the computation of List itself, but if
a7813a04 150 // we stored this intermediate value into tcx.tc_cache, then later
e9174d1e
SL
151 // requests for the contents of Option<List> would also yield TC::None
152 // which is incorrect. This value was computed based on the crutch
153 // value for the type contents of list. The correct value is
154 // TC::OwnsOwned. This manifested as issue #4821.
3157f602
XL
155 if let Some(tc) = cache.get(&ty) {
156 return *tc;
e9174d1e 157 }
3157f602
XL
158 // Must check both caches!
159 if let Some(tc) = tcx.tc_cache.borrow().get(&ty) {
160 return *tc;
e9174d1e
SL
161 }
162 cache.insert(ty, TC::None);
163
164 let result = match ty.sty {
165 // usize and isize are ffi-unsafe
7453a54e 166 ty::TyUint(ast::UintTy::Us) | ty::TyInt(ast::IntTy::Is) => {
e9174d1e
SL
167 TC::None
168 }
169
170 // Scalar and unique types are sendable, and durable
171 ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
5bcae85e 172 ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
54a0048b 173 ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => {
e9174d1e
SL
174 TC::None
175 }
176
476ff2be 177 ty::TyDynamic(..) => {
e9174d1e
SL
178 TC::All - TC::InteriorParam
179 }
180
181 ty::TyRawPtr(_) => {
182 TC::None
183 }
184
9e0c209e 185 ty::TyRef(..) => {
e9174d1e
SL
186 TC::None
187 }
188
189 ty::TyArray(ty, _) => {
a7813a04 190 tc_ty(tcx, ty, cache)
e9174d1e
SL
191 }
192
193 ty::TySlice(ty) => {
a7813a04 194 tc_ty(tcx, ty, cache)
e9174d1e
SL
195 }
196 ty::TyStr => TC::None,
197
476ff2be
SL
198 ty::TyClosure(def_id, ref substs) => {
199 TypeContents::union(
200 substs.upvar_tys(def_id, tcx),
201 |ty| tc_ty(tcx, &ty, cache))
e9174d1e
SL
202 }
203
8bb4bdeb 204 ty::TyTuple(ref tys, _) => {
e9174d1e 205 TypeContents::union(&tys[..],
a7813a04 206 |ty| tc_ty(tcx, *ty, cache))
e9174d1e
SL
207 }
208
9e0c209e 209 ty::TyAdt(def, substs) => {
e9174d1e
SL
210 let mut res =
211 TypeContents::union(&def.variants, |v| {
212 TypeContents::union(&v.fields, |f| {
a7813a04 213 tc_ty(tcx, f.ty(tcx, substs), cache)
e9174d1e
SL
214 })
215 });
216
32a655c1
SL
217 if def.is_union() {
218 // unions don't have destructors regardless of the child types
219 res = res - TC::OwnsDtor;
220 }
221
8bb4bdeb 222 if def.has_dtor(tcx) {
e9174d1e
SL
223 res = res | TC::OwnsDtor;
224 }
225
a7813a04 226 apply_lang_items(tcx, def.did, res)
e9174d1e
SL
227 }
228
229 ty::TyProjection(..) |
5bcae85e
SL
230 ty::TyParam(_) |
231 ty::TyAnon(..) => {
e9174d1e
SL
232 TC::All
233 }
234
235 ty::TyInfer(_) |
236 ty::TyError => {
54a0048b 237 bug!("asked to compute contents of error type");
e9174d1e
SL
238 }
239 };
240
241 cache.insert(ty, result);
242 result
243 }
244
a7813a04
XL
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() {
e9174d1e
SL
249 tc | TC::InteriorUnsafe
250 } else {
251 tc
252 }
253 }
254 }
255}