]> git.lizzy.rs Git - rust.git/commitdiff
rustc: simplify TypeContents drastically.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Mon, 17 Apr 2017 15:58:01 +0000 (18:58 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Thu, 20 Apr 2017 11:39:30 +0000 (14:39 +0300)
src/librustc/ty/contents.rs
src/librustc/ty/mod.rs

index e14295982916f44ad0578777db464581b6a4554d..c690795b3421dfb82d3e6eaddeccdf5627d49730 100644 (file)
 // 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<I, T, F>(v: I, mut f: F) -> TypeContents where
         I: IntoIterator<Item=T>,
         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 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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<List> 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<List> would also yield TC::None
+            // requests for the contents of Option<List> 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 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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
-            }
-        }
     }
 }
index ab1a06aeacd182990a362773cf9db929a911cccb..78d3885bb988aefca22d1fe06b6762d47e4df7e3 100644 (file)
@@ -2405,7 +2405,7 @@ pub fn type_needs_drop_given_env(self,
         // 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)
     }