From 3f5c311dc1dcb5bfe65d6eecd0dfda04d77c7594 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 17 Apr 2017 18:58:01 +0300 Subject: rustc: simplify TypeContents drastically. --- src/librustc/ty/contents.rs | 188 ++++++++++---------------------------------- src/librustc/ty/mod.rs | 2 +- 2 files changed, 42 insertions(+), 148 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index e1429598291..c690795b342 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -8,118 +8,45 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::{DefId}; use ty::{self, Ty, TyCtxt}; use util::common::MemoizationMap; use util::nodemap::FxHashMap; -use std::fmt; -use std::ops; - -use syntax::ast; - -/// Type contents is how the type checker reasons about kinds. -/// They track what kinds of things are found within a type. You can -/// think of them as kind of an "anti-kind". They track the kinds of values -/// and thinks that are contained in types. Having a larger contents for -/// a type tends to rule that type *out* from various kinds. For example, -/// a type that contains a reference is not sendable. -/// -/// The reason we compute type contents and not kinds is that it is -/// easier for me (nmatsakis) to think about what is contained within -/// a type than to think about what is *not* contained within a type. -#[derive(Clone, Copy)] -pub struct TypeContents { - pub bits: u64 -} - -macro_rules! def_type_content_sets { - (mod $mname:ident { $($name:ident = $bits:expr),+ }) => { - #[allow(non_snake_case)] - mod $mname { - use super::TypeContents; - $( - #[allow(non_upper_case_globals)] - pub const $name: TypeContents = TypeContents { bits: $bits }; - )+ - } - } -} - -def_type_content_sets! { - mod TC { - None = 0b0000_0000__0000_0000__0000, - - // Things that are interior to the value (first nibble): - InteriorUnsafe = 0b0000_0000__0000_0000__0010, - InteriorParam = 0b0000_0000__0000_0000__0100, - // InteriorAll = 0b00000000__00000000__1111, - - // Things that are owned by the value (second and third nibbles): - OwnsDtor = 0b0000_0000__0000_0010__0000, - // OwnsAll = 0b0000_0000__1111_1111__0000, - - // All bits - All = 0b1111_1111__1111_1111__1111 +bitflags! { + /// Type contents is how the type checker reasons about kinds. + /// They track what kinds of things are found within a type. You can + /// think of them as kind of an "anti-kind". They track the kinds of values + /// and thinks that are contained in types. Having a larger contents for + /// a type tends to rule that type *out* from various kinds. For example, + /// a type that contains a reference is not sendable. + /// + /// The reason we compute type contents and not kinds is that it is + /// easier for me (nmatsakis) to think about what is contained within + /// a type than to think about what is *not* contained within a type. + flags TypeContents: u8 { + const INTERIOR_UNSAFE = 0b01, + const OWNS_DTOR = 0b10, } } impl TypeContents { pub fn when(&self, cond: bool) -> TypeContents { - if cond {*self} else {TC::None} - } - - pub fn intersects(&self, tc: TypeContents) -> bool { - (self.bits & tc.bits) != 0 - } - - pub fn interior_param(&self) -> bool { - self.intersects(TC::InteriorParam) + if cond {*self} else {TypeContents::empty()} } pub fn interior_unsafe(&self) -> bool { - self.intersects(TC::InteriorUnsafe) + self.intersects(TypeContents::INTERIOR_UNSAFE) } pub fn needs_drop(&self, _: TyCtxt) -> bool { - self.intersects(TC::OwnsDtor) + self.intersects(TypeContents::OWNS_DTOR) } pub fn union(v: I, mut f: F) -> TypeContents where I: IntoIterator, F: FnMut(T) -> TypeContents, { - v.into_iter().fold(TC::None, |tc, ty| tc | f(ty)) - } -} - -impl ops::BitOr for TypeContents { - type Output = TypeContents; - - fn bitor(self, other: TypeContents) -> TypeContents { - TypeContents {bits: self.bits | other.bits} - } -} - -impl ops::BitAnd for TypeContents { - type Output = TypeContents; - - fn bitand(self, other: TypeContents) -> TypeContents { - TypeContents {bits: self.bits & other.bits} - } -} - -impl ops::Sub for TypeContents { - type Output = TypeContents; - - fn sub(self, other: TypeContents) -> TypeContents { - TypeContents {bits: self.bits & !other.bits} - } -} - -impl fmt::Debug for TypeContents { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TypeContents({:b})", self.bits) + v.into_iter().fold(TypeContents::empty(), |tc, ty| tc | f(ty)) } } @@ -139,19 +66,19 @@ impl<'a, 'tcx> ty::TyS<'tcx> { // // When computing the type contents of such a type, we wind up deeply // recursing as we go. So when we encounter the recursive reference - // to List, we temporarily use TC::None as its contents. Later we'll + // to List, we temporarily use TypeContents::empty() as its contents. Later we'll // patch up the cache with the correct value, once we've computed it // (this is basically a co-inductive process, if that helps). So in - // the end we'll compute TC::OwnsOwned, in this case. + // the end we'll compute TypeContents::OwnsOwned, in this case. // // The problem is, as we are doing the computation, we will also // compute an *intermediate* contents for, e.g., Option of - // TC::None. This is ok during the computation of List itself, but if + // TypeContents::empty(). This is ok during the computation of List itself, but if // we stored this intermediate value into tcx.tc_cache, then later - // requests for the contents of Option would also yield TC::None + // requests for the contents of Option would also yield TypeContents::empty() // which is incorrect. This value was computed based on the crutch // value for the type contents of list. The correct value is - // TC::OwnsOwned. This manifested as issue #4821. + // TypeContents::OwnsOwned. This manifested as issue #4821. if let Some(tc) = cache.get(&ty) { return *tc; } @@ -159,32 +86,14 @@ impl<'a, 'tcx> ty::TyS<'tcx> { if let Some(tc) = tcx.tc_cache.borrow().get(&ty) { return *tc; } - cache.insert(ty, TC::None); + cache.insert(ty, TypeContents::empty()); let result = match ty.sty { - // usize and isize are ffi-unsafe - ty::TyUint(ast::UintTy::Us) | ty::TyInt(ast::IntTy::Is) => { - TC::None - } - - // Scalar and unique types are sendable, and durable ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) | ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever | - ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => { - TC::None - } - - ty::TyDynamic(..) => { - TC::All - TC::InteriorParam - } - - ty::TyRawPtr(_) => { - TC::None - } - - ty::TyRef(..) => { - TC::None - } + ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | + ty::TyRawPtr(_) | ty::TyRef(..) | + ty::TyStr => TypeContents::empty(), ty::TyArray(ty, _) => { tc_ty(tcx, ty, cache) @@ -193,7 +102,6 @@ impl<'a, 'tcx> ty::TyS<'tcx> { ty::TySlice(ty) => { tc_ty(tcx, ty, cache) } - ty::TyStr => TC::None, ty::TyClosure(def_id, ref substs) => { TypeContents::union( @@ -207,29 +115,25 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } ty::TyAdt(def, substs) => { - let mut res = - TypeContents::union(&def.variants, |v| { - TypeContents::union(&v.fields, |f| { - tc_ty(tcx, f.ty(tcx, substs), cache) - }) - }); - - if def.is_union() { - // unions don't have destructors regardless of the child types - res = res - TC::OwnsDtor; - } - - if def.has_dtor(tcx) { - res = res | TC::OwnsDtor; - } - - apply_lang_items(tcx, def.did, res) + TypeContents::union(&def.variants, |v| { + TypeContents::union(&v.fields, |f| { + tc_ty(tcx, f.ty(tcx, substs), cache) + }) + }) + + // unions don't have destructors regardless of the child types + - TypeContents::OWNS_DTOR.when(def.is_union()) + | TypeContents::OWNS_DTOR.when(def.has_dtor(tcx)) + | TypeContents::INTERIOR_UNSAFE.when( + Some(def.did) == tcx.lang_items.unsafe_cell_type()) } + + ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) | ty::TyAnon(..) => { - TC::All + TypeContents::INTERIOR_UNSAFE | TypeContents::OWNS_DTOR } ty::TyInfer(_) | @@ -241,15 +145,5 @@ impl<'a, 'tcx> ty::TyS<'tcx> { cache.insert(ty, result); result } - - fn apply_lang_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - did: DefId, tc: TypeContents) - -> TypeContents { - if Some(did) == tcx.lang_items.unsafe_cell_type() { - tc | TC::InteriorUnsafe - } else { - tc - } - } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ab1a06aeacd..78d3885bb98 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2405,7 +2405,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // destructor (e.g. zero its memory on move). let contents = ty.type_contents(tcx); - debug!("type_needs_drop ty={:?} contents={:?}", ty, contents); + debug!("type_needs_drop ty={:?} contents={:?}", ty, contents.bits()); contents.needs_drop(tcx) } -- cgit 1.4.1-3-g733a5