about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/ty/contents.rs14
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc/ty/util.rs44
4 files changed, 55 insertions, 12 deletions
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 5989fa9007c..32dfb63d615 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -274,6 +274,7 @@ language_item_table! {
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
     CopyTraitLangItem,               "copy",                    copy_trait;
     SyncTraitLangItem,               "sync",                    sync_trait;
+    FreezeTraitLangItem,             "freeze",                  freeze_trait;
 
     DropTraitLangItem,               "drop",                    drop_trait;
 
diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs
index c690795b342..a1cb848213a 100644
--- a/src/librustc/ty/contents.rs
+++ b/src/librustc/ty/contents.rs
@@ -24,8 +24,7 @@ bitflags! {
     /// 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,
+        const OWNS_DTOR         = 0b1,
     }
 }
 
@@ -34,10 +33,6 @@ impl TypeContents {
         if cond {*self} else {TypeContents::empty()}
     }
 
-    pub fn interior_unsafe(&self) -> bool {
-        self.intersects(TypeContents::INTERIOR_UNSAFE)
-    }
-
     pub fn needs_drop(&self, _: TyCtxt) -> bool {
         self.intersects(TypeContents::OWNS_DTOR)
     }
@@ -124,17 +119,12 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
                     // 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(..) => {
-                    TypeContents::INTERIOR_UNSAFE | TypeContents::OWNS_DTOR
-                }
+                ty::TyAnon(..) => TypeContents::OWNS_DTOR,
 
                 ty::TyInfer(_) |
                 ty::TyError => {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 78d3885bb98..7325235ca7b 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -425,6 +425,8 @@ bitflags! {
         const IS_SIZED          = 1 << 17,
         const MOVENESS_CACHED   = 1 << 18,
         const MOVES_BY_DEFAULT  = 1 << 19,
+        const FREEZENESS_CACHED = 1 << 20,
+        const IS_FREEZE         = 1 << 21,
     }
 }
 
@@ -1181,6 +1183,9 @@ pub struct ParameterEnvironment<'tcx> {
 
     /// A cache for `type_is_sized`
     pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+
+    /// A cache for `type_is_freeze`
+    pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'tcx> {
@@ -1195,6 +1200,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             free_id_outlive: self.free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
 
@@ -2531,6 +2537,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         }
     }
 
@@ -2603,6 +2610,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             free_id_outlive: free_id_outlive,
             is_copy_cache: RefCell::new(FxHashMap()),
             is_sized_cache: RefCell::new(FxHashMap()),
+            is_freeze_cache: RefCell::new(FxHashMap()),
         };
 
         let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 5334ee2835d..d43d570397b 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -655,6 +655,50 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
         result
     }
 
+    /// Returns `true` if and only if there are no `UnsafeCell`s
+    /// nested within the type (ignoring `PhantomData` or pointers).
+    #[inline]
+    pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                     param_env: &ParameterEnvironment<'tcx>,
+                     span: Span) -> bool
+    {
+        if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::IS_FREEZE);
+        }
+
+        self.is_freeze_uncached(tcx, param_env, span)
+    }
+
+    fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          param_env: &ParameterEnvironment<'tcx>,
+                          span: Span) -> bool {
+        assert!(!self.needs_infer());
+
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
+            TyStr | TyNever => Some(true),
+
+            TyArray(..) | TySlice(_) |
+            TyTuple(..) | TyClosure(..) | TyAdt(..) |
+            TyDynamic(..) | TyProjection(..) | TyParam(..) |
+            TyInfer(..) | TyAnon(..) | TyError => None
+        }.unwrap_or_else(|| {
+            self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
+                              &param_env.is_freeze_cache, span) });
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
+            } else {
+                TypeFlags::FREEZENESS_CACHED
+            });
+        }
+
+        result
+    }
+
     #[inline]
     pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
                         -> Result<&'tcx Layout, LayoutError<'tcx>> {