about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-03-20 05:51:48 -0700
committerbors <bors@rust-lang.org>2014-03-20 05:51:48 -0700
commit8e285208d550c41d5060bbc4a614c9b63c3bff6a (patch)
tree8c4ca58b43010ac4bb619df96c7425247e9ba55a
parent95ee0a04fd78deb773da2d1b2544696c4f0278c7 (diff)
parent7b19574a2c2faac766c5192b243e5c361e449f3b (diff)
downloadrust-8e285208d550c41d5060bbc4a614c9b63c3bff6a.tar.gz
rust-8e285208d550c41d5060bbc4a614c9b63c3bff6a.zip
auto merge of #12686 : FlaPer87/rust/shared, r=nikomatsakis
`Share` implies that all *reachable* content is *threadsafe*.

Threadsafe is defined as "exposing no operation that permits a data race if multiple threads have access to a &T pointer simultaneously". (NB: the type system should guarantee that if you have access to memory via a &T pointer, the only other way to gain access to that memory is through another &T pointer)...

Fixes #11781
cc #12577 

What this PR will do
================

- [x] Add Share kind and
- [x]  Replace usages of Freeze with Share in bounds.
- [x] Add Unsafe<T> #12577
- [x] Forbid taking the address of a immutable static item with `Unsafe<T>` interior

What's left to do in a separate PR (after the snapshot)?
===========================================

- Remove `Freeze` completely 
-rw-r--r--src/doc/guide-unsafe.md4
-rw-r--r--src/doc/tutorial.md4
-rw-r--r--src/librustc/metadata/tydecode.rs3
-rw-r--r--src/librustc/metadata/tyencode.rs1
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs4
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs118
-rw-r--r--src/librustc/middle/borrowck/mod.rs25
-rw-r--r--src/librustc/middle/check_static.rs25
-rw-r--r--src/librustc/middle/lang_items.rs18
-rw-r--r--src/librustc/middle/mem_categorization.rs23
-rw-r--r--src/librustc/middle/ty.rs69
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/libstd/cell.rs33
-rw-r--r--src/libstd/kinds.rs23
-rw-r--r--src/libstd/lib.rs3
-rw-r--r--src/libstd/prelude.rs2
-rw-r--r--src/libstd/rc.rs21
-rw-r--r--src/libstd/sync/arc.rs12
-rw-r--r--src/libstd/sync/atomics.rs110
-rw-r--r--src/libstd/ty.rs82
-rw-r--r--src/libsync/arc.rs28
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/util/interner.rs2
-rw-r--r--src/test/auxiliary/issue-2526.rs6
-rw-r--r--src/test/compile-fail/borrowck-forbid-static-unsafe-interior.rs47
-rw-r--r--src/test/compile-fail/builtin-superkinds-double-superkind.rs6
-rw-r--r--src/test/compile-fail/builtin-superkinds-self-type.rs4
-rw-r--r--src/test/compile-fail/builtin-superkinds-typaram-not-send.rs2
-rw-r--r--src/test/compile-fail/cant-implement-builtin-kinds.rs2
-rw-r--r--src/test/compile-fail/check-static-values-constraints.rs24
-rw-r--r--src/test/compile-fail/comm-not-freeze.rs8
-rw-r--r--src/test/compile-fail/issue-2611-4.rs2
-rw-r--r--src/test/compile-fail/marker-no-share.rs (renamed from src/test/compile-fail/marker-no-freeze.rs)4
-rw-r--r--src/test/compile-fail/mut-not-freeze.rs4
-rw-r--r--src/test/compile-fail/no_share-enum.rs (renamed from src/test/compile-fail/no_freeze-enum.rs)8
-rw-r--r--src/test/compile-fail/no_share-rc.rs (renamed from src/test/compile-fail/no_freeze-rc.rs)4
-rw-r--r--src/test/compile-fail/no_share-struct.rs (renamed from src/test/compile-fail/no_freeze-struct.rs)8
-rw-r--r--src/test/run-pass/const-bound.rs2
-rw-r--r--src/test/run-pass/issue-2611-3.rs2
-rw-r--r--src/test/run-pass/trait-bounds-in-arc.rs14
40 files changed, 500 insertions, 267 deletions
diff --git a/src/doc/guide-unsafe.md b/src/doc/guide-unsafe.md
index b085fe21fac..9835e50d547 100644
--- a/src/doc/guide-unsafe.md
+++ b/src/doc/guide-unsafe.md
@@ -595,10 +595,10 @@ Other features provided by lang items include:
 - stack unwinding and general failure; the `eh_personality`, `fail_`
   and `fail_bounds_checks` lang items.
 - the traits in `std::kinds` used to indicate types that satisfy
-  various kinds; lang items `send`, `freeze` and `pod`.
+  various kinds; lang items `send`, `share` and `pod`.
 - the marker types and variance indicators found in
   `std::kinds::markers`; lang items `covariant_type`,
-  `contravariant_lifetime`, `no_freeze_bound`, etc.
+  `contravariant_lifetime`, `no_share_bound`, etc.
 
 Lang items are loaded lazily by the compiler; e.g. if one never uses
 `~` then there is no need to define functions for `exchange_malloc`
diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md
index cdb521b96c4..0a417a5a8bf 100644
--- a/src/doc/tutorial.md
+++ b/src/doc/tutorial.md
@@ -2095,6 +2095,10 @@ and may not be overridden:
 Types are sendable
 unless they contain managed boxes, managed closures, or references.
 
+* `Share` - Types that are *threadsafe*
+These are types that are safe to be used across several threads with access to
+a `&T` pointer. `MutexArc` is an example of a *sharable* type with internal mutable data.
+
 * `Freeze` - Constant (immutable) types.
 These are types that do not contain anything intrinsically mutable.
 Intrinsically mutable values include `Cell` in the standard library.
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 029edd73e9f..a990310a648 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -603,6 +603,9 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
             'P' => {
                 param_bounds.builtin_bounds.add(ty::BoundPod);
             }
+            'T' => {
+                param_bounds.builtin_bounds.add(ty::BoundShare);
+            }
             'I' => {
                 param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
             }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 7cec6532699..911729cd68a 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -410,6 +410,7 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
             ty::BoundStatic => mywrite!(w, "O"),
             ty::BoundSized => mywrite!(w, "Z"),
             ty::BoundPod => mywrite!(w, "P"),
+            ty::BoundShare => mywrite!(w, "T"),
         }
     }
 
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 0399ce5954f..5db1324b3fe 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -518,11 +518,11 @@ impl<'a> CheckLoanCtxt<'a> {
                                             expr: &ast::Expr,
                                             cmt: mc::cmt)
                                             -> bool {
-            match cmt.freely_aliasable() {
+            match cmt.freely_aliasable(this.tcx()) {
                 None => {
                     return true;
                 }
-                Some(mc::AliasableStaticMut) => {
+                Some(mc::AliasableStaticMut(..)) => {
                     return true;
                 }
                 Some(cause) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index 66be482eaef..6e98d282f8f 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -82,10 +82,12 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
     fn visit_block(&mut self, b: &Block, _: ()) {
         gather_loans_in_block(self, b);
     }
-    fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block,
-                s: Span, n: NodeId, _: ()) {
-        gather_loans_in_fn(self, fk, fd, b, s, n);
-    }
+
+    /// Do not visit closures or fn items here, the outer loop in
+    /// borrowck/mod will visit them for us in turn.
+    fn visit_fn(&mut self, _: &FnKind, _: &FnDecl, _: &Block,
+                _: Span, _: NodeId, _: ()) {}
+
     fn visit_stmt(&mut self, s: &Stmt, _: ()) {
         visit::walk_stmt(self, s, ());
     }
@@ -99,10 +101,20 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
     // #7740: Do not visit items here, not even fn items nor methods
     // of impl items; the outer loop in borrowck/mod will visit them
     // for us in turn.  Thus override visit_item's walk with a no-op.
-    fn visit_item(&mut self, _: &ast::Item, _: ()) { }
+    fn visit_item(&mut self, _: &ast::Item, _: ()) {}
+}
+
+fn add_pat_to_id_range(this: &mut GatherLoanCtxt,
+                       p: &ast::Pat) {
+    // NB: This visitor function just adds the pat ids into the id
+    // range. We gather loans that occur in patterns using the
+    // `gather_pat()` method below. Eventually these two should be
+    // brought together.
+    this.id_range.add(p.id);
+    visit::walk_pat(this, p, ());
 }
 
-pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
+pub fn gather_loans_in_fn(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
                     -> (IdRange, Vec<Loan>, move_data::MoveData) {
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
@@ -119,27 +131,6 @@ pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
     (id_range, all_loans, move_data)
 }
 
-fn add_pat_to_id_range(this: &mut GatherLoanCtxt,
-                       p: &ast::Pat) {
-    // NB: This visitor function just adds the pat ids into the id
-    // range. We gather loans that occur in patterns using the
-    // `gather_pat()` method below. Eventually these two should be
-    // brought together.
-    this.id_range.add(p.id);
-    visit::walk_pat(this, p, ());
-}
-
-fn gather_loans_in_fn(_v: &mut GatherLoanCtxt,
-                      _fk: &FnKind,
-                      _decl: &ast::FnDecl,
-                      _body: &ast::Block,
-                      _sp: Span,
-                      _id: ast::NodeId) {
-    // Do not visit closures or fn items here, the outer loop in
-    // borrowck/mod will visit them for us in turn.
-    return;
-}
-
 fn gather_loans_in_block(this: &mut GatherLoanCtxt,
                          blk: &ast::Block) {
     this.id_range.add(blk.id);
@@ -171,6 +162,28 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt,
     visit::walk_local(this, local, ());
 }
 
+pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &ast::Expr) {
+
+    debug!("gather_loans_in_item(expr={})", expr.repr(bccx.tcx));
+
+    let mut glcx = GatherLoanCtxt {
+        bccx: bccx,
+        id_range: IdRange::max(),
+        all_loans: Vec::new(),
+        item_ub: expr.id,
+        repeating_ids: vec!(expr.id),
+        move_data: MoveData::new()
+    };
+
+    // FIXME #13005 This should also walk the
+    // expression.
+    match expr.node {
+        ast::ExprAddrOf(..) => {
+            glcx.visit_expr(expr, ());
+        }
+        _ => {}
+    }
+}
 
 fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
                         ex: &ast::Expr) {
@@ -673,34 +686,45 @@ impl<'a> GatherLoanCtxt<'a> {
                               -> Result<(),()> {
             //! Implements the A-* rules in doc.rs.
 
-            match req_kind {
-                ty::ImmBorrow => {
+            match (cmt.freely_aliasable(bccx.tcx), req_kind) {
+                (None, _) => {
+                    /* Uniquely accessible path -- OK for `&` and `&mut` */
                     Ok(())
                 }
-
-                ty::UniqueImmBorrow | ty::MutBorrow => {
-                    // Check for those cases where we cannot control
-                    // the aliasing and make sure that we are not
-                    // being asked to.
-                    match cmt.freely_aliasable() {
-                        None => {
-                            Ok(())
+                (Some(mc::AliasableStatic(safety)), ty::ImmBorrow) => {
+                    // Borrow of an immutable static item:
+                    match safety {
+                        mc::InteriorUnsafe => {
+                            // If the static item contains an Unsafe<T>, it has interior mutability.
+                            // In such cases, we cannot permit it to be borrowed, because the
+                            // static item resides in immutable memory and mutating it would
+                            // cause segfaults.
+                            bccx.tcx.sess.span_err(borrow_span,
+                                                   format!("borrow of immutable static items with \
+                                                            unsafe interior is not allowed"));
+                            Err(())
                         }
-                        Some(mc::AliasableStaticMut) => {
-                            // This is nasty, but we ignore the
-                            // aliasing rules if the data is based in
-                            // a `static mut`, since those are always
-                            // unsafe. At your own peril and all that.
+                        mc::InteriorSafe => {
+                            // Immutable static can be borrowed, no problem.
                             Ok(())
                         }
-                        Some(alias_cause) => {
-                            bccx.report_aliasability_violation(
+                    }
+                }
+                (Some(mc::AliasableStaticMut(..)), _) => {
+                    // Even touching a static mut is considered unsafe. We assume the
+                    // user knows what they're doing in these cases.
+                    Ok(())
+                }
+                (Some(alias_cause), ty::UniqueImmBorrow) |
+                (Some(alias_cause), ty::MutBorrow) => {
+                    bccx.report_aliasability_violation(
                                 borrow_span,
                                 BorrowViolation(loan_cause),
                                 alias_cause);
-                            Err(())
-                        }
-                    }
+                    Err(())
+                }
+                (_, _) => {
+                    Ok(())
                 }
             }
         }
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 99e0ff6472f..1242fdbae6a 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -69,6 +69,10 @@ impl<'a> Visitor<()> for BorrowckCtxt<'a> {
                 b: &Block, s: Span, n: NodeId, _: ()) {
         borrowck_fn(self, fk, fd, b, s, n);
     }
+
+    fn visit_item(&mut self, item: &ast::Item, _: ()) {
+        borrowck_item(self, item);
+    }
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
@@ -117,6 +121,21 @@ pub fn check_crate(tcx: &ty::ctxt,
     }
 }
 
+fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
+    // Gather loans for items. Note that we don't need
+    // to check loans for single expressions. The check
+    // loan step is intended for things that have a data
+    // flow dependent conditions.
+    match item.node {
+        ast::ItemStatic(_, _, ex) => {
+            gather_loans::gather_loans_in_static_initializer(this, ex);
+        }
+        _ => {
+            visit::walk_item(this, item, ());
+        }
+    }
+}
+
 fn borrowck_fn(this: &mut BorrowckCtxt,
                fk: &FnKind,
                decl: &ast::FnDecl,
@@ -127,7 +146,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
     // Check the body of fn items.
     let (id_range, all_loans, move_data) =
-        gather_loans::gather_loans(this, decl, body);
+        gather_loans::gather_loans_in_fn(this, decl, body);
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
                              this.method_map,
@@ -715,8 +734,8 @@ impl<'a> BorrowckCtxt<'a> {
                     span,
                     format!("{} in an aliasable location", prefix));
             }
-            mc::AliasableStatic |
-            mc::AliasableStaticMut => {
+            mc::AliasableStatic(..) |
+            mc::AliasableStaticMut(..) => {
                 self.tcx.sess.span_err(
                     span,
                     format!("{} in a static location", prefix));
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 83f987a0bd0..ecc3ba59dd5 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -18,8 +18,11 @@
 // - For each *immutable* static item, it checks that its **value**:
 //       - doesn't own owned, managed pointers
 //       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
-//           - the type of the struct/enum is not freeze
 //           - the type of the struct/enum has a dtor
+//
+// Rules Enforced Elsewhere:
+// - It's not possible to take the address of a static item with unsafe interior. This is enforced
+// by borrowck::gather_loans
 
 use middle::ty;
 
@@ -121,21 +124,6 @@ impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
                 self.tcx.sess.span_err(e.span,
                                    "static items are not allowed to have owned pointers");
             }
-            ast::ExprProc(..) => {
-                self.report_error(e.span,
-                                  Some(~"immutable static items must be `Freeze`"));
-                return;
-            }
-            ast::ExprAddrOf(mutability, _) => {
-                match mutability {
-                    ast::MutMutable => {
-                        self.report_error(e.span,
-                                  Some(~"immutable static items must be `Freeze`"));
-                        return;
-                    }
-                    _ => {}
-                }
-            }
             _ => {
                 let node_ty = ty::node_id_to_type(self.tcx, e.id);
 
@@ -147,11 +135,6 @@ impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
                                      Some(~"static items are not allowed to have destructors"));
                             return;
                         }
-                        if Some(did) == self.tcx.lang_items.no_freeze_bound() {
-                            self.report_error(e.span,
-                                              Some(~"immutable static items must be `Freeze`"));
-                            return;
-                        }
                     }
                     _ => {}
                 }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6362bb93246..193c924f4e4 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -22,7 +22,7 @@
 
 use driver::session::Session;
 use metadata::csearch::each_lang_item;
-use middle::ty::{BuiltinBound, BoundFreeze, BoundPod, BoundSend, BoundSized};
+use middle::ty;
 use syntax::ast;
 use syntax::ast_util::local_def;
 use syntax::attr::AttrMetaMethods;
@@ -82,15 +82,17 @@ impl LanguageItems {
         }
     }
 
-    pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<BuiltinBound> {
+    pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<ty::BuiltinBound> {
         if Some(id) == self.freeze_trait() {
-            Some(BoundFreeze)
+            Some(ty::BoundFreeze)
         } else if Some(id) == self.send_trait() {
-            Some(BoundSend)
+            Some(ty::BoundSend)
         } else if Some(id) == self.sized_trait() {
-            Some(BoundSized)
+            Some(ty::BoundSized)
         } else if Some(id) == self.pod_trait() {
-            Some(BoundPod)
+            Some(ty::BoundPod)
+        } else if Some(id) == self.share_trait() {
+            Some(ty::BoundShare)
         } else {
             None
         }
@@ -213,6 +215,7 @@ lets_do_this! {
     SendTraitLangItem,               "send",                    send_trait;
     SizedTraitLangItem,              "sized",                   sized_trait;
     PodTraitLangItem,                "pod",                     pod_trait;
+    ShareTraitLangItem,              "share",                   share_trait;
 
     DropTraitLangItem,               "drop",                    drop_trait;
 
@@ -230,6 +233,8 @@ lets_do_this! {
     ShrTraitLangItem,                "shr",                     shr_trait;
     IndexTraitLangItem,              "index",                   index_trait;
 
+    UnsafeTypeLangItem,              "unsafe",                  unsafe_type;
+
     DerefTraitLangItem,              "deref",                   deref_trait;
     DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;
 
@@ -274,5 +279,6 @@ lets_do_this! {
     NoFreezeItem,                    "no_freeze_bound",         no_freeze_bound;
     NoSendItem,                      "no_send_bound",           no_send_bound;
     NoPodItem,                       "no_pod_bound",            no_pod_bound;
+    NoShareItem,                     "no_share_bound",          no_share_bound;
     ManagedItem,                     "managed_bound",           managed_bound;
 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 9efbd3a32d8..04d4b4c67de 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1222,12 +1222,17 @@ pub fn field_mutbl(tcx: &ty::ctxt,
     return None;
 }
 
+pub enum InteriorSafety {
+    InteriorUnsafe,
+    InteriorSafe
+}
+
 pub enum AliasableReason {
     AliasableManaged,
     AliasableBorrowed,
     AliasableOther,
-    AliasableStatic,
-    AliasableStaticMut,
+    AliasableStatic(InteriorSafety),
+    AliasableStaticMut(InteriorSafety),
 }
 
 impl cmt_ {
@@ -1257,7 +1262,7 @@ impl cmt_ {
         }
     }
 
-    pub fn freely_aliasable(&self) -> Option<AliasableReason> {
+    pub fn freely_aliasable(&self, ctxt: &ty::ctxt) -> Option<AliasableReason> {
         /*!
          * Returns `Some(_)` if this lvalue represents a freely aliasable
          * pointer type.
@@ -1275,7 +1280,7 @@ impl cmt_ {
             cat_interior(b, _) |
             cat_discr(b, _) => {
                 // Aliasability depends on base cmt
-                b.freely_aliasable()
+                b.freely_aliasable(ctxt)
             }
 
             cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
@@ -1292,10 +1297,16 @@ impl cmt_ {
             }
 
             cat_static_item(..) => {
+                let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
+                    InteriorUnsafe
+                } else {
+                    InteriorSafe
+                };
+
                 if self.mutbl.is_mutable() {
-                    Some(AliasableStaticMut)
+                    Some(AliasableStaticMut(int_safe))
                 } else {
-                    Some(AliasableStatic)
+                    Some(AliasableStatic(int_safe))
                 }
             }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index afdd9b55812..6dc31f7fdaa 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -850,6 +850,7 @@ pub enum BuiltinBound {
     BoundFreeze,
     BoundSized,
     BoundPod,
+    BoundShare,
 }
 
 pub fn EmptyBuiltinBounds() -> BuiltinBounds {
@@ -862,6 +863,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds {
     set.add(BoundSend);
     set.add(BoundFreeze);
     set.add(BoundSized);
+    set.add(BoundShare);
     set
 }
 
@@ -1872,31 +1874,33 @@ macro_rules! def_type_content_sets(
 
 def_type_content_sets!(
     mod TC {
-        None                                = 0b0000__00000000__0000,
+        None                                = 0b0000_0000__0000_0000__0000,
 
         // Things that are interior to the value (first nibble):
-        InteriorUnsized                     = 0b0000__00000000__0001,
-        // InteriorAll                         = 0b0000__00000000__1111,
+        InteriorUnsized                     = 0b0000_0000__0000_0000__0001,
+        InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
+        // InteriorAll                         = 0b00000000__00000000__1111,
 
         // Things that are owned by the value (second and third nibbles):
-        OwnsOwned                           = 0b0000__00000001__0000,
-        OwnsDtor                            = 0b0000__00000010__0000,
-        OwnsManaged /* see [1] below */     = 0b0000__00000100__0000,
-        OwnsAffine                          = 0b0000__00001000__0000,
-        OwnsAll                             = 0b0000__11111111__0000,
+        OwnsOwned                           = 0b0000_0000__0000_0001__0000,
+        OwnsDtor                            = 0b0000_0000__0000_0010__0000,
+        OwnsManaged /* see [1] below */     = 0b0000_0000__0000_0100__0000,
+        OwnsAffine                          = 0b0000_0000__0000_1000__0000,
+        OwnsAll                             = 0b0000_0000__1111_1111__0000,
 
         // Things that are reachable by the value in any way (fourth nibble):
-        ReachesNonsendAnnot                 = 0b0001__00000000__0000,
-        ReachesBorrowed                     = 0b0010__00000000__0000,
-        // ReachesManaged /* see [1] below */  = 0b0100__00000000__0000,
-        ReachesMutable                      = 0b1000__00000000__0000,
-        ReachesAll                          = 0b1111__00000000__0000,
+        ReachesNonsendAnnot                 = 0b0000_0001__0000_0000__0000,
+        ReachesBorrowed                     = 0b0000_0010__0000_0000__0000,
+        // ReachesManaged /* see [1] below */  = 0b0000_0100__0000_0000__0000,
+        ReachesMutable                      = 0b0000_1000__0000_0000__0000,
+        ReachesNoShare                      = 0b0001_0000__0000_0000__0000,
+        ReachesAll                          = 0b0001_1111__0000_0000__0000,
 
         // Things that cause values to *move* rather than *copy*
-        Moves                               = 0b0000__00001011__0000,
+        Moves                               = 0b0000_0000__0000_1011__0000,
 
         // Things that mean drop glue is necessary
-        NeedsDrop                           = 0b0000__00000111__0000,
+        NeedsDrop                           = 0b0000_0000__0000_0111__0000,
 
         // Things that prevent values from being sent
         //
@@ -1905,31 +1909,34 @@ def_type_content_sets!(
         //       both ReachesManaged and OwnsManaged so that when
         //       a parameter has a bound T:Send, we are able to deduce
         //       that it neither reaches nor owns a managed pointer.
-        Nonsendable                         = 0b0111__00000100__0000,
+        Nonsendable                         = 0b0000_0111__0000_0100__0000,
 
         // Things that prevent values from being considered freezable
-        Nonfreezable                        = 0b1000__00000000__0000,
+        Nonfreezable                        = 0b0000_1000__0000_0000__0000,
 
         // Things that prevent values from being considered 'static
-        Nonstatic                           = 0b0010__00000000__0000,
+        Nonstatic                           = 0b0000_0010__0000_0000__0000,
 
         // Things that prevent values from being considered sized
-        Nonsized                            = 0b0000__00000000__0001,
+        Nonsized                            = 0b0000_0000__0000_0000__0001,
+
+        // Things that prevent values from being shared
+        Nonsharable                         = 0b0001_0000__0000_0000__0000,
 
         // Things that make values considered not POD (would be same
         // as `Moves`, but for the fact that managed data `@` is
         // not considered POD)
-        Nonpod                              = 0b0000__00001111__0000,
+        Nonpod                              = 0b0000_0000__0000_1111__0000,
 
         // Bits to set when a managed value is encountered
         //
         // [1] Do not set the bits TC::OwnsManaged or
         //     TC::ReachesManaged directly, instead reference
         //     TC::Managed to set them both at once.
-        Managed                             = 0b0100__00000100__0000,
+        Managed                             = 0b0000_0100__0000_0100__0000,
 
         // All bits
-        All                                 = 0b1111__11111111__1111
+        All                                 = 0b1111_1111__1111_1111__1111
     }
 )
 
@@ -1945,6 +1952,7 @@ impl TypeContents {
             BoundSend => self.is_sendable(cx),
             BoundSized => self.is_sized(cx),
             BoundPod => self.is_pod(cx),
+            BoundShare => self.is_sharable(cx),
         }
     }
 
@@ -1964,6 +1972,10 @@ impl TypeContents {
         !self.intersects(TC::Nonsendable)
     }
 
+    pub fn is_sharable(&self, _: &ctxt) -> bool {
+        !self.intersects(TC::Nonsharable)
+    }
+
     pub fn owns_managed(&self) -> bool {
         self.intersects(TC::OwnsManaged)
     }
@@ -1984,6 +1996,10 @@ impl TypeContents {
         !self.intersects(TC::Nonpod)
     }
 
+    pub fn interior_unsafe(&self) -> bool {
+        self.intersects(TC::InteriorUnsafe)
+    }
+
     pub fn moves_by_default(&self, _: &ctxt) -> bool {
         self.intersects(TC::Moves)
     }
@@ -2080,6 +2096,10 @@ pub fn type_is_freezable(cx: &ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_freezable(cx)
 }
 
+pub fn type_interior_is_unsafe(cx: &ctxt, t: ty::t) -> bool {
+    type_contents(cx, t).interior_unsafe()
+}
+
 pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
     let ty_id = type_id(ty);
 
@@ -2284,6 +2304,10 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
             tc | TC::Managed
         } else if Some(did) == cx.lang_items.no_pod_bound() {
             tc | TC::OwnsAffine
+        } else if Some(did) == cx.lang_items.no_share_bound() {
+            tc | TC::ReachesNoShare
+        } else if Some(did) == cx.lang_items.unsafe_type() {
+            tc | TC::InteriorUnsafe
         } else {
             tc
         }
@@ -2362,6 +2386,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 BoundFreeze => TC::Nonfreezable,
                 BoundSized => TC::Nonsized,
                 BoundPod => TC::Nonpod,
+                BoundShare => TC::Nonsharable,
             };
         });
         return tc;
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index b6ddcd01950..e43eed9f219 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -674,6 +674,7 @@ impl Repr for ty::ParamBounds {
                 ty::BoundFreeze => ~"Freeze",
                 ty::BoundSized => ~"Sized",
                 ty::BoundPod => ~"Pod",
+                ty::BoundShare => ~"Share",
             });
         }
         for t in self.trait_bounds.iter() {
@@ -961,6 +962,7 @@ impl UserString for ty::BuiltinBound {
             ty::BoundFreeze => ~"Freeze",
             ty::BoundSized => ~"Sized",
             ty::BoundPod => ~"Pod",
+            ty::BoundShare => ~"Share",
         }
     }
 }
diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs
index 398091b60ca..5733504c0d1 100644
--- a/src/libstd/cell.rs
+++ b/src/libstd/cell.rs
@@ -17,35 +17,38 @@ use fmt;
 use kinds::{marker, Pod};
 use ops::{Deref, DerefMut, Drop};
 use option::{None, Option, Some};
+use ty::Unsafe;
 
 /// A mutable memory location that admits only `Pod` data.
 pub struct Cell<T> {
-    priv value: T,
+    priv value: Unsafe<T>,
     priv marker1: marker::InvariantType<T>,
     priv marker2: marker::NoFreeze,
+    priv marker3: marker::NoShare,
 }
 
 impl<T:Pod> Cell<T> {
     /// Creates a new `Cell` containing the given value.
     pub fn new(value: T) -> Cell<T> {
         Cell {
-            value: value,
+            value: Unsafe{value: value, marker1: marker::InvariantType::<T>},
             marker1: marker::InvariantType::<T>,
             marker2: marker::NoFreeze,
+            marker3: marker::NoShare,
         }
     }
 
     /// Returns a copy of the contained value.
     #[inline]
     pub fn get(&self) -> T {
-        self.value
+        unsafe{ *self.value.get() }
     }
 
     /// Sets the contained value.
     #[inline]
     pub fn set(&self, value: T) {
         unsafe {
-            *cast::transmute_mut(&self.value) = value
+            *self.value.get() = value;
         }
     }
 }
@@ -64,17 +67,18 @@ impl<T:Eq + Pod> Eq for Cell<T> {
 
 impl<T: fmt::Show> fmt::Show for Cell<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f.buf, r"Cell \{ value: {} \}", self.value)
+        write!(f.buf, r"Cell \{ value: {} \}", unsafe{*&self.value.get()})
     }
 }
 
 /// A mutable memory location with dynamically checked borrow rules
 pub struct RefCell<T> {
-    priv value: T,
+    priv value: Unsafe<T>,
     priv borrow: BorrowFlag,
     priv marker1: marker::InvariantType<T>,
     priv marker2: marker::NoFreeze,
     priv marker3: marker::NoPod,
+    priv marker4: marker::NoShare,
 }
 
 // Values [1, MAX-1] represent the number of `Ref` active
@@ -90,7 +94,8 @@ impl<T> RefCell<T> {
             marker1: marker::InvariantType::<T>,
             marker2: marker::NoFreeze,
             marker3: marker::NoPod,
-            value: value,
+            marker4: marker::NoShare,
+            value: Unsafe{value: value, marker1: marker::InvariantType::<T>},
             borrow: UNUSED,
         }
     }
@@ -98,7 +103,7 @@ impl<T> RefCell<T> {
     /// Consumes the `RefCell`, returning the wrapped value.
     pub fn unwrap(self) -> T {
         assert!(self.borrow == UNUSED);
-        self.value
+        unsafe{self.value.unwrap()}
     }
 
     unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
@@ -198,7 +203,7 @@ impl<T> RefCell<T> {
     #[inline]
     pub fn set(&self, value: T) {
         let mut reference = self.borrow_mut();
-        *reference.get() = value
+        *reference.get() = value;
     }
 }
 
@@ -247,14 +252,14 @@ impl<'b, T> Ref<'b, T> {
     /// Retrieve an immutable reference to the stored value.
     #[inline]
     pub fn get<'a>(&'a self) -> &'a T {
-        &self.parent.value
+        unsafe{ &*self.parent.value.get() }
     }
 }
 
 impl<'b, T> Deref<T> for Ref<'b, T> {
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
-        &self.parent.value
+        unsafe{ &*self.parent.value.get() }
     }
 }
 
@@ -275,21 +280,21 @@ impl<'b, T> RefMut<'b, T> {
     /// Retrieve a mutable reference to the stored value.
     #[inline]
     pub fn get<'a>(&'a mut self) -> &'a mut T {
-        &mut self.parent.value
+        unsafe{ &mut *self.parent.value.get() }
     }
 }
 
 impl<'b, T> Deref<T> for RefMut<'b, T> {
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
-        &self.parent.value
+        unsafe{ &*self.parent.value.get() }
     }
 }
 
 impl<'b, T> DerefMut<T> for RefMut<'b, T> {
     #[inline]
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
-        &mut self.parent.value
+        unsafe{ &mut *self.parent.value.get() }
     }
 }
 
diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs
index da17119fd98..b44616421d1 100644
--- a/src/libstd/kinds.rs
+++ b/src/libstd/kinds.rs
@@ -46,6 +46,22 @@ pub trait Pod {
     // Empty.
 }
 
+/// Types that can be safely shared between threads, hence thread-safe.
+#[cfg(stage0)]
+pub trait Share {
+    // Empty
+}
+
+#[cfg(stage0)]
+impl<T> Share for T {}
+
+/// Types that can be safely shared between threads, hence thread-safe.
+#[cfg(not(stage0))]
+#[lang="share"]
+pub trait Share {
+    // Empty
+}
+
 /// Marker types are special types that are used with unsafe code to
 /// inform the compiler of special constraints. Marker types should
 /// only be needed when you are creating an abstraction that is
@@ -232,6 +248,13 @@ pub mod marker {
     #[deriving(Eq,Clone)]
     pub struct NoPod;
 
+    /// A type which is considered "not sharable", meaning that
+    /// its contents are not threadsafe, hence they cannot be
+    /// shared between tasks.
+    #[lang="no_share_bound"]
+    #[deriving(Eq,Clone)]
+    pub struct NoShare;
+
     /// A type which is considered managed by the GC. This is typically
     /// embedded in other types.
     #[lang="managed_bound"]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 302f899efda..0431a80d0c4 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -83,6 +83,7 @@
 #[cfg(test)] pub use kinds = realstd::kinds;
 #[cfg(test)] pub use ops = realstd::ops;
 #[cfg(test)] pub use cmp = realstd::cmp;
+#[cfg(test)] pub use ty = realstd::ty;
 
 #[cfg(stage0)]
 pub use vec_ng = vec;
@@ -141,6 +142,7 @@ pub mod gc;
 #[cfg(not(test))] pub mod kinds;
 #[cfg(not(test))] pub mod ops;
 #[cfg(not(test))] pub mod cmp;
+#[cfg(not(test))] pub mod ty;
 
 
 /* Common traits */
@@ -229,5 +231,6 @@ mod std {
     pub use rt;
     pub use str;
     pub use to_str;
+    pub use ty;
     pub use unstable;
 }
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 0b1de74330d..f3a5bd3d3b5 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -20,7 +20,7 @@ generally useful to many Rust programs.
 */
 
 // Reexported core operators
-pub use kinds::{Freeze, Pod, Send, Sized};
+pub use kinds::{Freeze, Pod, Send, Sized, Share};
 pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
 pub use ops::{BitAnd, BitOr, BitXor};
 pub use ops::{Drop, Deref, DerefMut};
diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs
index 5c4b19b4e4b..605cbd3f28a 100644
--- a/src/libstd/rc.rs
+++ b/src/libstd/rc.rs
@@ -42,7 +42,8 @@ struct RcBox<T> {
 #[unsafe_no_drop_flag]
 pub struct Rc<T> {
     priv ptr: *mut RcBox<T>,
-    priv marker: marker::NoSend
+    priv nosend: marker::NoSend,
+    priv noshare: marker::NoShare
 }
 
 impl<T> Rc<T> {
@@ -56,7 +57,8 @@ impl<T> Rc<T> {
                 // strong destructor is running, even if the weak
                 // pointer is stored inside the strong one.
                 ptr: transmute(~RcBox { value: value, strong: 1, weak: 1 }),
-                marker: marker::NoSend,
+                nosend: marker::NoSend,
+                noshare: marker::NoShare
             }
         }
     }
@@ -67,7 +69,11 @@ impl<T> Rc<T> {
     pub fn downgrade(&self) -> Weak<T> {
         unsafe {
             (*self.ptr).weak += 1;
-            Weak { ptr: self.ptr, marker: marker::NoSend }
+            Weak {
+                ptr: self.ptr,
+                nosend: marker::NoSend,
+                noshare: marker::NoShare
+            }
         }
     }
 }
@@ -107,7 +113,7 @@ impl<T> Clone for Rc<T> {
     fn clone(&self) -> Rc<T> {
         unsafe {
             (*self.ptr).strong += 1;
-            Rc { ptr: self.ptr, marker: marker::NoSend }
+            Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }
         }
     }
 }
@@ -138,7 +144,8 @@ impl<T: Ord> Ord for Rc<T> {
 #[unsafe_no_drop_flag]
 pub struct Weak<T> {
     priv ptr: *mut RcBox<T>,
-    priv marker: marker::NoSend
+    priv nosend: marker::NoSend,
+    priv noshare: marker::NoShare
 }
 
 impl<T> Weak<T> {
@@ -149,7 +156,7 @@ impl<T> Weak<T> {
                 None
             } else {
                 (*self.ptr).strong += 1;
-                Some(Rc { ptr: self.ptr, marker: marker::NoSend })
+                Some(Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare })
             }
         }
     }
@@ -176,7 +183,7 @@ impl<T> Clone for Weak<T> {
     fn clone(&self) -> Weak<T> {
         unsafe {
             (*self.ptr).weak += 1;
-            Weak { ptr: self.ptr, marker: marker::NoSend }
+            Weak { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }
         }
     }
 }
diff --git a/src/libstd/sync/arc.rs b/src/libstd/sync/arc.rs
index 883e81355e1..92974005305 100644
--- a/src/libstd/sync/arc.rs
+++ b/src/libstd/sync/arc.rs
@@ -28,6 +28,7 @@ use ops::Drop;
 use ptr::RawPtr;
 use sync::atomics::{fence, AtomicUint, Relaxed, Acquire, Release};
 use slice;
+use ty::Unsafe;
 
 /// An atomically reference counted pointer.
 ///
@@ -39,11 +40,14 @@ pub struct UnsafeArc<T> {
 
 struct ArcData<T> {
     count: AtomicUint,
-    data: T,
+    data: Unsafe<T>,
 }
 
 unsafe fn new_inner<T: Send>(data: T, refcount: uint) -> *mut ArcData<T> {
-    let data = ~ArcData { count: AtomicUint::new(refcount), data: data };
+    let data = ~ArcData {
+                    count: AtomicUint::new(refcount),
+                    data: Unsafe::new(data)
+                 };
     cast::transmute(data)
 }
 
@@ -82,7 +86,7 @@ impl<T: Send> UnsafeArc<T> {
         unsafe {
             // FIXME(#12049): this needs some sort of debug assertion
             if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); }
-            return &mut (*self.data).data as *mut T;
+            return (*self.data).data.get();
         }
     }
 
@@ -93,7 +97,7 @@ impl<T: Send> UnsafeArc<T> {
         unsafe {
             // FIXME(#12049): this needs some sort of debug assertion
             if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); }
-            return &(*self.data).data as *T;
+            return (*self.data).data.get() as *T;
         }
     }
 
diff --git a/src/libstd/sync/atomics.rs b/src/libstd/sync/atomics.rs
index 500ae04869b..cbdb38c1c58 100644
--- a/src/libstd/sync/atomics.rs
+++ b/src/libstd/sync/atomics.rs
@@ -114,35 +114,36 @@ use cast;
 use std::kinds::marker;
 use option::{Option,Some,None};
 use ops::Drop;
+use ty::Unsafe;
 
 /// An atomic boolean type.
 pub struct AtomicBool {
-    priv v: uint,
+    priv v: Unsafe<uint>,
     priv nopod: marker::NoPod
 }
 
 /// A signed atomic integer type, supporting basic atomic arithmetic operations
 pub struct AtomicInt {
-    priv v: int,
+    priv v: Unsafe<int>,
     priv nopod: marker::NoPod
 }
 
 /// An unsigned atomic integer type, supporting basic atomic arithmetic operations
 pub struct AtomicUint {
-    priv v: uint,
+    priv v: Unsafe<uint>,
     priv nopod: marker::NoPod
 }
 
 /// An unsigned atomic integer type that is forced to be 64-bits. This does not
 /// support all operations.
 pub struct AtomicU64 {
-    priv v: u64,
+    priv v: Unsafe<u64>,
     priv nopod: marker::NoPod
 }
 
 /// An unsafe atomic pointer. Only supports basic atomic operations
 pub struct AtomicPtr<T> {
-    priv p: uint,
+    priv p: Unsafe<uint>,
     priv nopod: marker::NoPod
 }
 
@@ -152,7 +153,7 @@ pub struct AtomicPtr<T> {
 /// owned heap objects across tasks.
 #[unsafe_no_drop_flag]
 pub struct AtomicOption<T> {
-    priv p: uint,
+    priv p: Unsafe<uint>,
 }
 
 /// Atomic memory orderings
@@ -186,13 +187,21 @@ pub enum Ordering {
 }
 
 /// An `AtomicBool` initialized to `false`
-pub static INIT_ATOMIC_BOOL : AtomicBool = AtomicBool { v: 0, nopod: marker::NoPod };
+pub static INIT_ATOMIC_BOOL : AtomicBool = AtomicBool { v: Unsafe{value: 0,
+                                                                  marker1: marker::InvariantType},
+                                                        nopod: marker::NoPod };
 /// An `AtomicInt` initialized to `0`
-pub static INIT_ATOMIC_INT  : AtomicInt  = AtomicInt  { v: 0, nopod: marker::NoPod };
+pub static INIT_ATOMIC_INT  : AtomicInt  = AtomicInt  { v: Unsafe{value: 0,
+                                                                  marker1: marker::InvariantType},
+                                                        nopod: marker::NoPod };
 /// An `AtomicUint` initialized to `0`
-pub static INIT_ATOMIC_UINT : AtomicUint = AtomicUint { v: 0, nopod: marker::NoPod };
+pub static INIT_ATOMIC_UINT : AtomicUint = AtomicUint { v: Unsafe{value: 0,
+                                                                  marker1: marker::InvariantType},
+                                                        nopod: marker::NoPod };
 /// An `AtomicU64` initialized to `0`
-pub static INIT_ATOMIC_U64 : AtomicU64 = AtomicU64 { v: 0, nopod: marker::NoPod };
+pub static INIT_ATOMIC_U64 : AtomicU64 = AtomicU64 { v: Unsafe{value: 0,
+                                                               marker1: marker::InvariantType},
+                                                     nopod: marker::NoPod };
 
 
 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
@@ -201,13 +210,14 @@ static UINT_TRUE: uint = -1;
 impl AtomicBool {
     /// Create a new `AtomicBool`
     pub fn new(v: bool) -> AtomicBool {
-        AtomicBool { v: if v { UINT_TRUE } else { 0 }, nopod: marker::NoPod }
+        let val = if v { UINT_TRUE } else { 0 };
+        AtomicBool { v: Unsafe::new(val), nopod: marker::NoPod }
     }
 
     /// Load the value
     #[inline]
     pub fn load(&self, order: Ordering) -> bool {
-        unsafe { atomic_load(&self.v, order) > 0 }
+        unsafe { atomic_load(&*self.v.get(), order) > 0 }
     }
 
     /// Store the value
@@ -215,7 +225,7 @@ impl AtomicBool {
     pub fn store(&mut self, val: bool, order: Ordering) {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_store(&mut self.v, val, order); }
+        unsafe { atomic_store(&mut *self.v.get(), val, order); }
     }
 
     /// Store a value, returning the old value
@@ -223,7 +233,7 @@ impl AtomicBool {
     pub fn swap(&mut self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_swap(&mut self.v, val, order) > 0 }
+        unsafe { atomic_swap(&mut *self.v.get(), val, order) > 0 }
     }
 
     /// If the current value is the same as expected, store a new value
@@ -276,7 +286,7 @@ impl AtomicBool {
         let old = if old { UINT_TRUE } else { 0 };
         let new = if new { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) > 0 }
+        unsafe { atomic_compare_and_swap(&mut *self.v.get(), old, new, order) > 0 }
     }
 
     /// A logical "and" operation
@@ -306,7 +316,7 @@ impl AtomicBool {
     pub fn fetch_and(&mut self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_and(&mut self.v, val, order) > 0 }
+        unsafe { atomic_and(&mut *self.v.get(), val, order) > 0 }
     }
 
     /// A logical "nand" operation
@@ -337,7 +347,7 @@ impl AtomicBool {
     pub fn fetch_nand(&mut self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_nand(&mut self.v, val, order) > 0 }
+        unsafe { atomic_nand(&mut *self.v.get(), val, order) > 0 }
     }
 
     /// A logical "or" operation
@@ -367,7 +377,7 @@ impl AtomicBool {
     pub fn fetch_or(&mut self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_or(&mut self.v, val, order) > 0 }
+        unsafe { atomic_or(&mut *self.v.get(), val, order) > 0 }
     }
 
     /// A logical "xor" operation
@@ -397,32 +407,32 @@ impl AtomicBool {
     pub fn fetch_xor(&mut self, val: bool, order: Ordering) -> bool {
         let val = if val { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_xor(&mut self.v, val, order) > 0 }
+        unsafe { atomic_xor(&mut *self.v.get(), val, order) > 0 }
     }
 }
 
 impl AtomicInt {
     /// Create a new `AtomicInt`
     pub fn new(v: int) -> AtomicInt {
-        AtomicInt { v:v, nopod: marker::NoPod}
+        AtomicInt {v: Unsafe::new(v), nopod: marker::NoPod}
     }
 
     /// Load the value
     #[inline]
     pub fn load(&self, order: Ordering) -> int {
-        unsafe { atomic_load(&self.v, order) }
+        unsafe { atomic_load(&*self.v.get(), order) }
     }
 
     /// Store the value
     #[inline]
     pub fn store(&mut self, val: int, order: Ordering) {
-        unsafe { atomic_store(&mut self.v, val, order); }
+        unsafe { atomic_store(&mut *self.v.get(), val, order); }
     }
 
     /// Store a value, returning the old value
     #[inline]
     pub fn swap(&mut self, val: int, order: Ordering) -> int {
-        unsafe { atomic_swap(&mut self.v, val, order) }
+        unsafe { atomic_swap(&mut *self.v.get(), val, order) }
     }
 
     /// If the current value is the same as expected, store a new value
@@ -432,7 +442,7 @@ impl AtomicInt {
     /// If the return value is equal to `old` then the value was updated.
     #[inline]
     pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int {
-        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
+        unsafe { atomic_compare_and_swap(&mut *self.v.get(), old, new, order) }
     }
 
     /// Add to the current value, returning the previous
@@ -448,7 +458,7 @@ impl AtomicInt {
     /// ```
     #[inline]
     pub fn fetch_add(&mut self, val: int, order: Ordering) -> int {
-        unsafe { atomic_add(&mut self.v, val, order) }
+        unsafe { atomic_add(&mut *self.v.get(), val, order) }
     }
 
     /// Subtract from the current value, returning the previous
@@ -464,7 +474,7 @@ impl AtomicInt {
     /// ```
     #[inline]
     pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int {
-        unsafe { atomic_sub(&mut self.v, val, order) }
+        unsafe { atomic_sub(&mut *self.v.get(), val, order) }
     }
 }
 
@@ -474,62 +484,62 @@ impl AtomicInt {
 #[cfg(not(target_arch = "mips"))]
 impl AtomicU64 {
     pub fn new(v: u64) -> AtomicU64 {
-        AtomicU64 { v:v, nopod: marker::NoPod }
+        AtomicU64 { v: Unsafe::new(v), nopod: marker::NoPod }
     }
 
     #[inline]
     pub fn load(&self, order: Ordering) -> u64 {
-        unsafe { atomic_load(&self.v, order) }
+        unsafe { atomic_load(&*self.v.get(), order) }
     }
 
     #[inline]
     pub fn store(&mut self, val: u64, order: Ordering) {
-        unsafe { atomic_store(&mut self.v, val, order); }
+        unsafe { atomic_store(&mut *self.v.get(), val, order); }
     }
 
     #[inline]
     pub fn swap(&mut self, val: u64, order: Ordering) -> u64 {
-        unsafe { atomic_swap(&mut self.v, val, order) }
+        unsafe { atomic_swap(&mut *self.v.get(), val, order) }
     }
 
     #[inline]
     pub fn compare_and_swap(&mut self, old: u64, new: u64, order: Ordering) -> u64 {
-        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
+        unsafe { atomic_compare_and_swap(&mut *self.v.get(), old, new, order) }
     }
 
     #[inline]
     pub fn fetch_add(&mut self, val: u64, order: Ordering) -> u64 {
-        unsafe { atomic_add(&mut self.v, val, order) }
+        unsafe { atomic_add(&mut *self.v.get(), val, order) }
     }
 
     #[inline]
     pub fn fetch_sub(&mut self, val: u64, order: Ordering) -> u64 {
-        unsafe { atomic_sub(&mut self.v, val, order) }
+        unsafe { atomic_sub(&mut *self.v.get(), val, order) }
     }
 }
 
 impl AtomicUint {
     /// Create a new `AtomicUint`
     pub fn new(v: uint) -> AtomicUint {
-        AtomicUint { v:v, nopod: marker::NoPod }
+        AtomicUint { v: Unsafe::new(v), nopod: marker::NoPod }
     }
 
     /// Load the value
     #[inline]
     pub fn load(&self, order: Ordering) -> uint {
-        unsafe { atomic_load(&self.v, order) }
+        unsafe { atomic_load(&*self.v.get(), order) }
     }
 
     /// Store the value
     #[inline]
     pub fn store(&mut self, val: uint, order: Ordering) {
-        unsafe { atomic_store(&mut self.v, val, order); }
+        unsafe { atomic_store(&mut *self.v.get(), val, order); }
     }
 
     /// Store a value, returning the old value
     #[inline]
     pub fn swap(&mut self, val: uint, order: Ordering) -> uint {
-        unsafe { atomic_swap(&mut self.v, val, order) }
+        unsafe { atomic_swap(&mut *self.v.get(), val, order) }
     }
 
     /// If the current value is the same as expected, store a new value
@@ -539,7 +549,7 @@ impl AtomicUint {
     /// If the return value is equal to `old` then the value was updated.
     #[inline]
     pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint {
-        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
+        unsafe { atomic_compare_and_swap(&mut *self.v.get(), old, new, order) }
     }
 
     /// Add to the current value, returning the previous
@@ -555,7 +565,7 @@ impl AtomicUint {
     /// ```
     #[inline]
     pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint {
-        unsafe { atomic_add(&mut self.v, val, order) }
+        unsafe { atomic_add(&mut *self.v.get(), val, order) }
     }
 
     /// Subtract from the current value, returning the previous
@@ -571,34 +581,34 @@ impl AtomicUint {
     /// ```
     #[inline]
     pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint {
-        unsafe { atomic_sub(&mut self.v, val, order) }
+        unsafe { atomic_sub(&mut *self.v.get(), val, order) }
     }
 }
 
 impl<T> AtomicPtr<T> {
     /// Create a new `AtomicPtr`
     pub fn new(p: *mut T) -> AtomicPtr<T> {
-        AtomicPtr { p: p as uint, nopod: marker::NoPod }
+        AtomicPtr { p: Unsafe::new(p as uint), nopod: marker::NoPod }
     }
 
     /// Load the value
     #[inline]
     pub fn load(&self, order: Ordering) -> *mut T {
         unsafe {
-            atomic_load(&self.p, order) as *mut T
+            atomic_load(&*self.p.get(), order) as *mut T
         }
     }
 
     /// Store the value
     #[inline]
     pub fn store(&mut self, ptr: *mut T, order: Ordering) {
-        unsafe { atomic_store(&mut self.p, ptr as uint, order); }
+        unsafe { atomic_store(&mut *self.p.get(), ptr as uint, order); }
     }
 
     /// Store a value, returning the old value
     #[inline]
     pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T {
-        unsafe { atomic_swap(&mut self.p, ptr as uint, order) as *mut T }
+        unsafe { atomic_swap(&mut *self.p.get(), ptr as uint, order) as *mut T }
     }
 
     /// If the current value is the same as expected, store a new value
@@ -609,7 +619,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
         unsafe {
-            atomic_compare_and_swap(&mut self.p, old as uint,
+            atomic_compare_and_swap(&mut *self.p.get(), old as uint,
                                     new as uint, order) as *mut T
         }
     }
@@ -618,11 +628,11 @@ impl<T> AtomicPtr<T> {
 impl<T> AtomicOption<T> {
     /// Create a new `AtomicOption`
     pub fn new(p: ~T) -> AtomicOption<T> {
-        unsafe { AtomicOption { p: cast::transmute(p) } }
+        unsafe { AtomicOption { p: Unsafe::new(cast::transmute(p)) } }
     }
 
     /// Create a new `AtomicOption` that doesn't contain a value
-    pub fn empty() -> AtomicOption<T> { AtomicOption { p: 0 } }
+    pub fn empty() -> AtomicOption<T> { AtomicOption { p: Unsafe::new(0) } }
 
     /// Store a value, returning the old value
     #[inline]
@@ -630,7 +640,7 @@ impl<T> AtomicOption<T> {
         unsafe {
             let val = cast::transmute(val);
 
-            let p = atomic_swap(&mut self.p, val, order);
+            let p = atomic_swap(&mut *self.p.get(), val, order);
             if p as uint == 0 {
                 None
             } else {
@@ -655,7 +665,7 @@ impl<T> AtomicOption<T> {
         unsafe {
             let val = cast::transmute(val);
             let expected = cast::transmute(0);
-            let oldval = atomic_compare_and_swap(&mut self.p, expected, val, order);
+            let oldval = atomic_compare_and_swap(&mut *self.p.get(), expected, val, order);
             if oldval == expected {
                 None
             } else {
@@ -670,7 +680,7 @@ impl<T> AtomicOption<T> {
     /// result does not get invalidated by another task after this returns.
     #[inline]
     pub fn is_empty(&mut self, order: Ordering) -> bool {
-        unsafe { atomic_load(&self.p, order) as uint == 0 }
+        unsafe { atomic_load(&*self.p.get(), order) as uint == 0 }
     }
 }
 
diff --git a/src/libstd/ty.rs b/src/libstd/ty.rs
new file mode 100644
index 00000000000..344235053f3
--- /dev/null
+++ b/src/libstd/ty.rs
@@ -0,0 +1,82 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Types dealing with unsafe actions.
+
+use cast;
+use kinds::marker;
+
+/// Unsafe type that wraps a type T and indicates unsafe interior operations on the
+/// wrapped type. Types with an `Unsafe<T>` field are considered to have an *unsafe
+/// interior*. The Unsafe type is the only legal way to obtain aliasable data that is
+/// considered mutable. In general, transmuting an &T type into an &mut T is considered
+/// undefined behavior.
+///
+/// Although it is possible to put an Unsafe<T> into static item, it is not permitted to
+/// take the address of the static item if the item is not declared as mutable. This rule
+/// exists because immutable static items are stored in read-only memory, and thus any
+/// attempt to mutate their interior can cause segfaults. Immutable static items containing
+/// Unsafe<T> instances are still useful as read-only initializers, however, so we do not
+/// forbid them altogether.
+///
+/// Types like `Cell` and `RefCell` use this type to wrap their internal data.
+///
+/// Unsafe doesn't opt-out from any kind, instead, types with an `Unsafe` interior
+/// are expected to opt-out from kinds themselves.
+///
+/// # Example:
+///
+/// ```rust
+/// use std::ty::Unsafe;
+/// use std::kinds::marker;
+///
+/// struct NotThreadSafe<T> {
+///     value: Unsafe<T>,
+///     marker1: marker::NoShare
+/// }
+/// ```
+///
+/// **NOTE:** Unsafe<T> fields are public to allow static initializers. It is not recommended
+/// to access its fields directly, `get` should be used instead.
+#[cfg(not(stage0))]
+#[lang="unsafe"]
+pub struct Unsafe<T> {
+    /// Wrapped value
+    value: T,
+
+    /// Invariance marker
+    marker1: marker::InvariantType<T>
+}
+
+/// Unsafe type for stage0
+#[cfg(stage0)]
+pub struct Unsafe<T> {
+    /// Wrapped value
+    value: T,
+
+    /// Invariance marker
+    marker1: marker::InvariantType<T>
+}
+
+impl<T> Unsafe<T> {
+
+    /// Static constructor
+    pub fn new(value: T) -> Unsafe<T> {
+        Unsafe{value: value, marker1: marker::InvariantType}
+    }
+
+    /// Gets a mutable pointer to the wrapped value
+    #[inline]
+    pub unsafe fn get(&self) -> *mut T { cast::transmute(&self.value) }
+
+    /// Unwraps the value
+    #[inline]
+    pub unsafe fn unwrap(self) -> T { self.value }
+}
diff --git a/src/libsync/arc.rs b/src/libsync/arc.rs
index 1d49771ed38..71adab71734 100644
--- a/src/libsync/arc.rs
+++ b/src/libsync/arc.rs
@@ -54,6 +54,9 @@ use std::kinds::marker;
 use std::sync::arc::UnsafeArc;
 use std::task;
 
+#[cfg(stage0)]
+use std::kinds::Share;
+
 /// As sync::condvar, a mechanism for unlock-and-descheduling and
 /// signaling, for use with the Arc types.
 pub struct ArcCondvar<'a> {
@@ -122,7 +125,7 @@ pub struct Arc<T> { priv x: UnsafeArc<T> }
  * Access the underlying data in an atomically reference counted
  * wrapper.
  */
-impl<T:Freeze+Send> Arc<T> {
+impl<T: Share + Send> Arc<T> {
     /// Create an atomically reference counted wrapper.
     #[inline]
     pub fn new(data: T) -> Arc<T> {
@@ -135,7 +138,7 @@ impl<T:Freeze+Send> Arc<T> {
     }
 }
 
-impl<T:Freeze + Send> Clone for Arc<T> {
+impl<T: Share + Send> Clone for Arc<T> {
     /**
     * Duplicate an atomically reference counted wrapper.
     *
@@ -295,19 +298,21 @@ struct RWArcInner<T> { lock: RWLock, failed: bool, data: T }
 pub struct RWArc<T> {
     priv x: UnsafeArc<RWArcInner<T>>,
     priv marker: marker::NoFreeze,
+    priv marker1: marker::NoShare,
 }
 
-impl<T:Freeze + Send> Clone for RWArc<T> {
+impl<T: Share + Send> Clone for RWArc<T> {
     /// Duplicate a rwlock-protected Arc. See arc::clone for more details.
     #[inline]
     fn clone(&self) -> RWArc<T> {
         RWArc { x: self.x.clone(),
-                marker: marker::NoFreeze, }
+                marker: marker::NoFreeze,
+                marker1: marker::NoShare, }
     }
 
 }
 
-impl<T:Freeze + Send> RWArc<T> {
+impl<T: Share + Send> RWArc<T> {
     /// Create a reader/writer Arc with the supplied data.
     pub fn new(user_data: T) -> RWArc<T> {
         RWArc::new_with_condvars(user_data, 1)
@@ -323,7 +328,8 @@ impl<T:Freeze + Send> RWArc<T> {
             failed: false, data: user_data
         };
         RWArc { x: UnsafeArc::new(data),
-                marker: marker::NoFreeze, }
+                marker: marker::NoFreeze,
+                marker1: marker::NoShare, }
     }
 
     /**
@@ -454,7 +460,7 @@ impl<T:Freeze + Send> RWArc<T> {
 // lock it. This wraps the unsafety, with the justification that the 'lock'
 // field is never overwritten; only 'failed' and 'data'.
 #[doc(hidden)]
-fn borrow_rwlock<T:Freeze + Send>(state: *mut RWArcInner<T>) -> *RWLock {
+fn borrow_rwlock<T: Share + Send>(state: *mut RWArcInner<T>) -> *RWLock {
     unsafe { cast::transmute(&(*state).lock) }
 }
 
@@ -471,7 +477,7 @@ pub struct RWReadMode<'a, T> {
     priv token: sync::RWLockReadMode<'a>,
 }
 
-impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
+impl<'a, T: Share + Send> RWWriteMode<'a, T> {
     /// Access the pre-downgrade RWArc in write mode.
     pub fn write<U>(&mut self, blk: |x: &mut T| -> U) -> U {
         match *self {
@@ -510,7 +516,7 @@ impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
     }
 }
 
-impl<'a, T:Freeze + Send> RWReadMode<'a, T> {
+impl<'a, T: Share + Send> RWReadMode<'a, T> {
     /// Access the post-downgrade rwlock in read mode.
     pub fn read<U>(&self, blk: |x: &T| -> U) -> U {
         match *self {
@@ -534,7 +540,7 @@ pub struct CowArc<T> { priv x: UnsafeArc<T> }
 /// mutation of the contents if there is only a single reference to
 /// the data. If there are multiple references the data is automatically
 /// cloned and the task modifies the cloned data in place of the shared data.
-impl<T:Clone+Send+Freeze> CowArc<T> {
+impl<T: Clone + Send + Share> CowArc<T> {
     /// Create a copy-on-write atomically reference counted wrapper
     #[inline]
     pub fn new(data: T) -> CowArc<T> {
@@ -558,7 +564,7 @@ impl<T:Clone+Send+Freeze> CowArc<T> {
     }
 }
 
-impl<T:Clone+Send+Freeze> Clone for CowArc<T> {
+impl<T: Clone + Send + Share> Clone for CowArc<T> {
     /// Duplicate a Copy-on-write Arc. See arc::clone for more details.
     fn clone(&self) -> CowArc<T> {
         CowArc { x: self.x.clone() }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index cbf5242271d..fce9ddcc2ee 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1159,14 +1159,6 @@ mod test {
 
     use std::vec::Vec;
 
-    fn is_freeze<T: Freeze>() {}
-
-    // Assert that the AST remains Freeze (#10693).
-    #[test]
-    fn ast_is_freeze() {
-        is_freeze::<Item>();
-    }
-
     // are ASTs encodable?
     #[test]
     fn check_asts_encodable() {
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 8a8bf1fdfb3..0406f5f5ba9 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -29,7 +29,7 @@ pub struct Interner<T> {
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
-impl<T:Eq + Hash + Freeze + Clone + 'static> Interner<T> {
+impl<T: Eq + Hash + Clone + 'static> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
             map: RefCell::new(HashMap::new()),
diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs
index ef5c141a3d5..51bbb59b77e 100644
--- a/src/test/auxiliary/issue-2526.rs
+++ b/src/test/auxiliary/issue-2526.rs
@@ -16,17 +16,17 @@ struct arc_destruct<T> {
 }
 
 #[unsafe_destructor]
-impl<T:Freeze> Drop for arc_destruct<T> {
+impl<T: Share> Drop for arc_destruct<T> {
     fn drop(&mut self) {}
 }
 
-fn arc_destruct<T:Freeze>(data: int) -> arc_destruct<T> {
+fn arc_destruct<T: Share>(data: int) -> arc_destruct<T> {
     arc_destruct {
         _data: data
     }
 }
 
-fn arc<T:Freeze>(_data: T) -> arc_destruct<T> {
+fn arc<T: Share>(_data: T) -> arc_destruct<T> {
     arc_destruct(0)
 }
 
diff --git a/src/test/compile-fail/borrowck-forbid-static-unsafe-interior.rs b/src/test/compile-fail/borrowck-forbid-static-unsafe-interior.rs
new file mode 100644
index 00000000000..c790a040a91
--- /dev/null
+++ b/src/test/compile-fail/borrowck-forbid-static-unsafe-interior.rs
@@ -0,0 +1,47 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Verify that it is not possible to take the address of
+// static items with usnafe interior.
+
+use std::kinds::marker;
+use std::ty::Unsafe;
+
+struct MyUnsafe<T> {
+    value: Unsafe<T>
+}
+
+impl<T> MyUnsafe<T> {
+    fn forbidden(&self) {}
+}
+
+enum UnsafeEnum<T> {
+    VariantSafe,
+    VariantUnsafe(Unsafe<T>)
+}
+
+static STATIC1: UnsafeEnum<int> = VariantSafe;
+
+static STATIC2: Unsafe<int> = Unsafe{value: 1, marker1: marker::InvariantType};
+static STATIC3: MyUnsafe<int> = MyUnsafe{value: STATIC2};
+
+static STATIC4: &'static Unsafe<int> = &'static STATIC2;
+//~^ ERROR borrow of immutable static items with unsafe interior is not allowed
+
+
+fn main() {
+    let a = &STATIC1;
+    //~^ ERROR borrow of immutable static items with unsafe interior is not allowed
+
+    STATIC3.forbidden()
+    //~^ ERROR borrow of immutable static items with unsafe interior is not allowed
+}
+
+
diff --git a/src/test/compile-fail/builtin-superkinds-double-superkind.rs b/src/test/compile-fail/builtin-superkinds-double-superkind.rs
index 15fa0b66433..7de38e6173b 100644
--- a/src/test/compile-fail/builtin-superkinds-double-superkind.rs
+++ b/src/test/compile-fail/builtin-superkinds-double-superkind.rs
@@ -11,12 +11,12 @@
 // Test for traits that inherit from multiple builtin kinds at once,
 // testing that all such kinds must be present on implementing types.
 
-trait Foo : Send+Freeze { }
+trait Foo : Send+Share { }
 
-impl <T: Freeze> Foo for (T,) { } //~ ERROR cannot implement this trait
+impl <T: Share> Foo for (T,) { } //~ ERROR cannot implement this trait
 
 impl <T: Send> Foo for (T,T) { } //~ ERROR cannot implement this trait
 
-impl <T: Send+Freeze> Foo for (T,T,T) { } // (ok)
+impl <T: Send+Share> Foo for (T,T,T) { } // (ok)
 
 fn main() { }
diff --git a/src/test/compile-fail/builtin-superkinds-self-type.rs b/src/test/compile-fail/builtin-superkinds-self-type.rs
index 074c5d7bb76..0d5a71559e8 100644
--- a/src/test/compile-fail/builtin-superkinds-self-type.rs
+++ b/src/test/compile-fail/builtin-superkinds-self-type.rs
@@ -11,13 +11,13 @@
 // Tests (negatively) the ability for the Self type in default methods
 // to use capabilities granted by builtin kinds as supertraits.
 
-trait Foo : Freeze {
+trait Foo : Share {
     fn foo(self, mut chan: Sender<Self>) {
         chan.send(self); //~ ERROR does not fulfill `Send`
     }
 }
 
-impl <T: Freeze> Foo for T { }
+impl <T: Share> Foo for T { }
 
 fn main() {
     let (tx, rx) = channel();
diff --git a/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs
index 2a3d3c7df61..bc0ad6dbb29 100644
--- a/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs
+++ b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs
@@ -12,6 +12,6 @@
 
 trait Foo : Send { }
 
-impl <T: Freeze> Foo for T { } //~ ERROR cannot implement this trait
+impl <T: Share> Foo for T { } //~ ERROR cannot implement this trait
 
 fn main() { }
diff --git a/src/test/compile-fail/cant-implement-builtin-kinds.rs b/src/test/compile-fail/cant-implement-builtin-kinds.rs
index c35ca098372..6bedac6d12d 100644
--- a/src/test/compile-fail/cant-implement-builtin-kinds.rs
+++ b/src/test/compile-fail/cant-implement-builtin-kinds.rs
@@ -14,6 +14,6 @@ struct X<T>(T);
 
 impl <T> Send for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind
 impl <T> Sized for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind
-impl <T> Freeze for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind
+impl <T> Share for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind
 
 fn main() { }
diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs
index 852b06d00a6..8ae40a74af1 100644
--- a/src/test/compile-fail/check-static-values-constraints.rs
+++ b/src/test/compile-fail/check-static-values-constraints.rs
@@ -124,30 +124,6 @@ static STATIC18: @SafeStruct = @SafeStruct{field1: Variant1, field2: Variant2(0)
 static STATIC19: ~int = box 3;
 //~^ ERROR static items are not allowed to have owned pointers
 
-
-struct StructNoFreeze<'a> {
-    nf: &'a int
-}
-
-enum EnumNoFreeze<'a> {
-    FreezableVariant,
-    NonFreezableVariant(StructNoFreeze<'a>)
-}
-
-static STATIC20: StructNoFreeze<'static> = StructNoFreeze{nf: &'static mut 4};
-//~^ ERROR immutable static items must be `Freeze`
-
-static STATIC21: EnumNoFreeze<'static> = FreezableVariant;
-static STATIC22: EnumNoFreeze<'static> = NonFreezableVariant(StructNoFreeze{nf: &'static mut 4});
-//~^ ERROR immutable static items must be `Freeze`
-
-struct NFMarker {
-    nf: marker::NoFreeze
-}
-
-static STATIC23: NFMarker = NFMarker{nf: marker::NoFreeze};
-//~^ ERROR immutable static items must be `Freeze`
-
 pub fn main() {
     let y = { static x: ~int = ~3; x };
     //~^ ERROR static items are not allowed to have owned pointers
diff --git a/src/test/compile-fail/comm-not-freeze.rs b/src/test/compile-fail/comm-not-freeze.rs
index b7b87b28264..3550922dc14 100644
--- a/src/test/compile-fail/comm-not-freeze.rs
+++ b/src/test/compile-fail/comm-not-freeze.rs
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn test<T: Freeze>() {}
+fn test<T: Share>() {}
 
 fn main() {
-    test::<Sender<int>>();        //~ ERROR: does not fulfill `Freeze`
-    test::<Receiver<int>>();        //~ ERROR: does not fulfill `Freeze`
-    test::<Sender<int>>();  //~ ERROR: does not fulfill `Freeze`
+    test::<Sender<int>>();        //~ ERROR: does not fulfill `Share`
+    test::<Receiver<int>>();        //~ ERROR: does not fulfill `Share`
+    test::<Sender<int>>();  //~ ERROR: does not fulfill `Share`
 }
diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs
index c62c2874525..b159337765e 100644
--- a/src/test/compile-fail/issue-2611-4.rs
+++ b/src/test/compile-fail/issue-2611-4.rs
@@ -20,7 +20,7 @@ struct E {
 }
 
 impl A for E {
-  fn b<F:Freeze,G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Freeze`
+  fn b<F: Share, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Share`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/marker-no-freeze.rs b/src/test/compile-fail/marker-no-share.rs
index 85f4f4fefd4..84e856f5ac9 100644
--- a/src/test/compile-fail/marker-no-freeze.rs
+++ b/src/test/compile-fail/marker-no-share.rs
@@ -10,9 +10,9 @@
 
 use std::kinds::marker;
 
-fn foo<P:Freeze>(p: P) { }
+fn foo<P: Share>(p: P) { }
 
 fn main()
 {
-    foo(marker::NoFreeze); //~ ERROR does not fulfill `Freeze`
+    foo(marker::NoShare); //~ ERROR does not fulfill `Share`
 }
diff --git a/src/test/compile-fail/mut-not-freeze.rs b/src/test/compile-fail/mut-not-freeze.rs
index 97fe49ca087..f1e7ef216c3 100644
--- a/src/test/compile-fail/mut-not-freeze.rs
+++ b/src/test/compile-fail/mut-not-freeze.rs
@@ -10,9 +10,9 @@
 
 use std::cell::RefCell;
 
-fn f<T: Freeze>(_: T) {}
+fn f<T: Share>(_: T) {}
 
 fn main() {
     let x = RefCell::new(0);
-    f(x); //~ ERROR: which does not fulfill `Freeze`
+    f(x); //~ ERROR: which does not fulfill `Share`
 }
diff --git a/src/test/compile-fail/no_freeze-enum.rs b/src/test/compile-fail/no_share-enum.rs
index e27b9dd85b4..e68274fcb79 100644
--- a/src/test/compile-fail/no_freeze-enum.rs
+++ b/src/test/compile-fail/no_share-enum.rs
@@ -10,13 +10,13 @@
 
 use std::kinds::marker;
 
-enum Foo { A(marker::NoFreeze) }
+enum Foo { A(marker::NoShare) }
 
-fn bar<T: Freeze>(_: T) {}
+fn bar<T: Share>(_: T) {}
 
 fn main() {
-    let x = A(marker::NoFreeze);
+    let x = A(marker::NoShare);
     bar(x);
     //~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
-    //         which does not fulfill `Freeze`
+    //         which does not fulfill `Share`
 }
diff --git a/src/test/compile-fail/no_freeze-rc.rs b/src/test/compile-fail/no_share-rc.rs
index b814a71dcbe..ad79d038212 100644
--- a/src/test/compile-fail/no_freeze-rc.rs
+++ b/src/test/compile-fail/no_share-rc.rs
@@ -11,11 +11,11 @@
 use std::rc::Rc;
 use std::cell::RefCell;
 
-fn bar<T: Freeze>(_: T) {}
+fn bar<T: Share>(_: T) {}
 
 fn main() {
     let x = Rc::new(RefCell::new(5));
     bar(x);
     //~^ ERROR instantiating a type parameter with an incompatible type
-    //         `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
+    //         `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Share`
 }
diff --git a/src/test/compile-fail/no_freeze-struct.rs b/src/test/compile-fail/no_share-struct.rs
index c85574438ba..7bb7d86e8d8 100644
--- a/src/test/compile-fail/no_freeze-struct.rs
+++ b/src/test/compile-fail/no_share-struct.rs
@@ -10,13 +10,13 @@
 
 use std::kinds::marker;
 
-struct Foo { a: int, m: marker::NoFreeze }
+struct Foo { a: int, m: marker::NoShare }
 
-fn bar<T: Freeze>(_: T) {}
+fn bar<T: Share>(_: T) {}
 
 fn main() {
-    let x = Foo { a: 5, m: marker::NoFreeze };
+    let x = Foo { a: 5, m: marker::NoShare };
     bar(x);
     //~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
-    //         which does not fulfill `Freeze`
+    //         which does not fulfill `Share`
 }
diff --git a/src/test/run-pass/const-bound.rs b/src/test/run-pass/const-bound.rs
index 635ae704e41..c8c2a11d8d6 100644
--- a/src/test/run-pass/const-bound.rs
+++ b/src/test/run-pass/const-bound.rs
@@ -12,7 +12,7 @@
 // are const.
 
 
-fn foo<T:Freeze>(x: T) -> T { x }
+fn foo<T: Share>(x: T) -> T { x }
 
 struct F { field: int }
 
diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs
index a3d51bb9014..f48a49a15eb 100644
--- a/src/test/run-pass/issue-2611-3.rs
+++ b/src/test/run-pass/issue-2611-3.rs
@@ -12,7 +12,7 @@
 // than the traits require.
 
 trait A {
-  fn b<C:Freeze,D>(x: C) -> C;
+  fn b<C:Share,D>(x: C) -> C;
 }
 
 struct E {
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index f157f8ea95c..0ed4fdb2c05 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -65,10 +65,10 @@ pub fn main() {
     let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" };
     let dogge2 = Dogge { bark_decibels: 55,  tricks_known: 11, name: ~"albert_einstein" };
     let fishe = Goldfyshe { swim_speed: 998, name: ~"alec_guinness" };
-    let arc = Arc::new(~[~catte  as ~Pet:Freeze+Send,
-                         ~dogge1 as ~Pet:Freeze+Send,
-                         ~fishe  as ~Pet:Freeze+Send,
-                         ~dogge2 as ~Pet:Freeze+Send]);
+    let arc = Arc::new(~[~catte  as ~Pet:Share+Send,
+                         ~dogge1 as ~Pet:Share+Send,
+                         ~fishe  as ~Pet:Share+Send,
+                         ~dogge2 as ~Pet:Share+Send]);
     let (tx1, rx1) = channel();
     let arc1 = arc.clone();
     task::spawn(proc() { check_legs(arc1); tx1.send(()); });
@@ -83,21 +83,21 @@ pub fn main() {
     rx3.recv();
 }
 
-fn check_legs(arc: Arc<~[~Pet:Freeze+Send]>) {
+fn check_legs(arc: Arc<~[~Pet:Share+Send]>) {
     let mut legs = 0;
     for pet in arc.get().iter() {
         legs += pet.num_legs();
     }
     assert!(legs == 12);
 }
-fn check_names(arc: Arc<~[~Pet:Freeze+Send]>) {
+fn check_names(arc: Arc<~[~Pet:Share+Send]>) {
     for pet in arc.get().iter() {
         pet.name(|name| {
             assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
         })
     }
 }
-fn check_pedigree(arc: Arc<~[~Pet:Freeze+Send]>) {
+fn check_pedigree(arc: Arc<~[~Pet:Share+Send]>) {
     for pet in arc.get().iter() {
         assert!(pet.of_good_pedigree());
     }