about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs159
-rw-r--r--src/libcore/cell.rs5
-rw-r--r--src/libcore/marker.rs2
-rw-r--r--src/librustc/metadata/csearch.rs9
-rw-r--r--src/librustc/metadata/decoder.rs23
-rw-r--r--src/librustc/middle/traits/select.rs31
-rw-r--r--src/librustc/middle/ty.rs21
-rw-r--r--src/librustc_typeck/check/mod.rs1
-rw-r--r--src/librustc_typeck/check/wf.rs31
-rw-r--r--src/librustc_typeck/coherence/overlap.rs39
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs23
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/sync/mpsc/blocking.rs29
-rw-r--r--src/libstd/sync/mpsc/mod.rs18
-rw-r--r--src/libstd/sync/mpsc/select.rs28
-rw-r--r--src/libstd/sync/mutex.rs33
-rw-r--r--src/libstd/sync/rwlock.rs54
-rw-r--r--src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs29
-rw-r--r--src/test/compile-fail/coherence-negative-impls-safe.rs (renamed from src/test/compile-fail/marker-no-share.rs)16
-rw-r--r--src/test/compile-fail/coherence-orphan.rs6
-rw-r--r--src/test/compile-fail/issue-17718-static-sync.rs9
-rw-r--r--src/test/compile-fail/issue-7013.rs1
-rw-r--r--src/test/compile-fail/kindck-nonsendable-1.rs1
-rw-r--r--src/test/compile-fail/mutable-enum-indirect.rs11
-rw-r--r--src/test/compile-fail/no-send-res-ports.rs1
-rw-r--r--src/test/compile-fail/no_send-enum.rs11
-rw-r--r--src/test/compile-fail/no_send-rc.rs1
-rw-r--r--src/test/compile-fail/no_send-struct.rs9
-rw-r--r--src/test/compile-fail/no_share-enum.rs11
-rw-r--r--src/test/compile-fail/no_share-rc.rs1
-rw-r--r--src/test/compile-fail/no_share-struct.rs9
-rw-r--r--src/test/compile-fail/task-rng-isnt-sendable.rs1
-rw-r--r--src/test/compile-fail/traits-negative-impls.rs58
-rw-r--r--src/test/compile-fail/typeck-negative-impls-builtin.rs20
-rw-r--r--src/test/compile-fail/typeck-unsafe-always-share.rs18
-rw-r--r--src/test/compile-fail/unique-unique-kind.rs1
-rw-r--r--src/test/compile-fail/unsendable-class.rs1
-rw-r--r--src/test/pretty/trait-polarity.rs8
-rw-r--r--src/test/run-pass/coherence-negative-impls-safe.rs (renamed from src/test/compile-fail/marker-no-send.rs)15
-rw-r--r--src/test/run-pass/syntax-trait-polarity.rs6
-rw-r--r--src/test/run-pass/traits-negative-impls.rs29
42 files changed, 676 insertions, 105 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 4a85637625a..6c853306035 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -68,6 +68,7 @@
 #![allow(unknown_features)]
 #![feature(lang_items, unsafe_destructor)]
 #![feature(box_syntax)]
+#![feature(optin_builtin_traits)]
 #![allow(unknown_features)] #![feature(int_uint)]
 
 #[macro_use]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index f42c6dbdc15..0e18cdda8dd 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -174,6 +174,7 @@ struct RcBox<T> {
 /// See the [module level documentation](../index.html) for more details.
 #[unsafe_no_drop_flag]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Rc<T> {
     // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
     // type via Deref
@@ -182,6 +183,24 @@ pub struct Rc<T> {
     _noshare: marker::NoSync
 }
 
+/// An immutable reference-counted pointer type.
+///
+/// See the [module level documentation](../index.html) for more details.
+#[unsafe_no_drop_flag]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Rc<T> {
+    // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
+    // type via Deref
+    _ptr: NonZero<*mut RcBox<T>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Send for Rc<T> {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Sync for Rc<T> {}
+
 impl<T> Rc<T> {
     /// Constructs a new `Rc<T>`.
     ///
@@ -193,6 +212,7 @@ impl<T> Rc<T> {
     /// let five = Rc::new(5i);
     /// ```
     #[stable]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     pub fn new(value: T) -> Rc<T> {
         unsafe {
             Rc {
@@ -210,6 +230,32 @@ impl<T> Rc<T> {
         }
     }
 
+    /// Constructs a new `Rc<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    /// ```
+    #[stable]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn new(value: T) -> Rc<T> {
+        unsafe {
+            Rc {
+                // there is an implicit weak pointer owned by all the strong pointers, which
+                // ensures that the weak destructor never frees the allocation while the strong
+                // destructor is running, even if the weak pointer is stored inside the strong one.
+                _ptr: NonZero::new(transmute(box RcBox {
+                    value: value,
+                    strong: Cell::new(1),
+                    weak: Cell::new(1)
+                })),
+            }
+        }
+    }
+
     /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
     ///
     /// # Examples
@@ -221,6 +267,7 @@ impl<T> Rc<T> {
     ///
     /// let weak_five = five.downgrade();
     /// ```
+    #[cfg(stage0)] // NOTE remove after next snapshot
     #[unstable = "Weak pointers may not belong in this module"]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
@@ -230,6 +277,24 @@ impl<T> Rc<T> {
             _noshare: marker::NoSync
         }
     }
+
+    /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// let weak_five = five.downgrade();
+    /// ```
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    #[unstable = "Weak pointers may not belong in this module"]
+    pub fn downgrade(&self) -> Weak<T> {
+        self.inc_weak();
+        Weak { _ptr: self._ptr }
+    }
 }
 
 /// Get the number of weak references to this value.
@@ -432,10 +497,31 @@ impl<T> Clone for Rc<T> {
     /// five.clone();
     /// ```
     #[inline]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     fn clone(&self) -> Rc<T> {
         self.inc_strong();
         Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
     }
+
+    /// Makes a clone of the `Rc<T>`.
+    ///
+    /// This increases the strong reference count.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// five.clone();
+    /// ```
+    #[inline]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn clone(&self) -> Rc<T> {
+        self.inc_strong();
+        Rc { _ptr: self._ptr }
+    }
 }
 
 #[stable]
@@ -636,6 +722,7 @@ impl<T: fmt::String> fmt::String for Rc<T> {
 /// See the [module level documentation](../index.html) for more.
 #[unsafe_no_drop_flag]
 #[unstable = "Weak pointers may not belong in this module."]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Weak<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -644,6 +731,29 @@ pub struct Weak<T> {
     _noshare: marker::NoSync
 }
 
+/// A weak version of `Rc<T>`.
+///
+/// Weak references do not count when determining if the inner value should be dropped.
+///
+/// See the [module level documentation](../index.html) for more.
+#[unsafe_no_drop_flag]
+#[unstable = "Weak pointers may not belong in this module."]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Weak<T> {
+    // FIXME #12808: strange names to try to avoid interfering with
+    // field accesses of the contained type via Deref
+    _ptr: NonZero<*mut RcBox<T>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+#[allow(unstable)]
+impl<T> !marker::Send for Weak<T> {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+#[allow(unstable)]
+impl<T> !marker::Sync for Weak<T> {}
+
+
 #[unstable = "Weak pointers may not belong in this module."]
 impl<T> Weak<T> {
     /// Upgrades a weak reference to a strong reference.
@@ -663,6 +773,7 @@ impl<T> Weak<T> {
     ///
     /// let strong_five: Option<Rc<_>> = weak_five.upgrade();
     /// ```
+    #[cfg(stage0)] // NOTE remove after next snapshot
     pub fn upgrade(&self) -> Option<Rc<T>> {
         if self.strong() == 0 {
             None
@@ -671,6 +782,33 @@ impl<T> Weak<T> {
             Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
         }
     }
+
+    /// Upgrades a weak reference to a strong reference.
+    ///
+    /// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
+    ///
+    /// Returns `None` if there were no strong references and the data was destroyed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// let weak_five = five.downgrade();
+    ///
+    /// let strong_five: Option<Rc<_>> = weak_five.upgrade();
+    /// ```
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn upgrade(&self) -> Option<Rc<T>> {
+        if self.strong() == 0 {
+            None
+        } else {
+            self.inc_strong();
+            Some(Rc { _ptr: self._ptr })
+        }
+    }
 }
 
 #[unsafe_destructor]
@@ -733,10 +871,31 @@ impl<T> Clone for Weak<T> {
     /// weak_five.clone();
     /// ```
     #[inline]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     fn clone(&self) -> Weak<T> {
         self.inc_weak();
         Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
     }
+
+    /// Makes a clone of the `Weak<T>`.
+    ///
+    /// This increases the weak reference count.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let weak_five = Rc::new(5i).downgrade();
+    ///
+    /// weak_five.clone();
+    /// ```
+    #[inline]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn clone(&self) -> Weak<T> {
+        self.inc_weak();
+        Weak { _ptr: self._ptr }
+    }
 }
 
 #[unstable = "Show is experimental."]
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 6db01b7cb7a..ec4007c4c6d 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -509,12 +509,13 @@ impl<'b, T> DerefMut for RefMut<'b, T> {
 ///
 /// ```rust
 /// use std::cell::UnsafeCell;
-/// use std::marker;
+/// use std::marker::Sync;
 ///
 /// struct NotThreadSafe<T> {
 ///     value: UnsafeCell<T>,
-///     marker: marker::NoSync
 /// }
+///
+/// unsafe impl<T> Sync for NotThreadSafe<T> {}
 /// ```
 ///
 /// **NOTE:** `UnsafeCell<T>` fields are public to allow static initializers. It
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index d400cb47cbf..715a79abe85 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -286,6 +286,7 @@ pub struct InvariantLifetime<'a>;
 #[unstable = "likely to change with new variance strategy"]
 #[lang="no_send_bound"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct NoSend;
 
 /// A type which is considered "not POD", meaning that it is not
@@ -303,6 +304,7 @@ pub struct NoCopy;
 #[unstable = "likely to change with new variance strategy"]
 #[lang="no_sync_bound"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct NoSync;
 
 /// A type which is considered managed by the GC. This is typically
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 0bbd11bea0a..e34fb37e1c5 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -262,6 +262,15 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
     }
 }
 
+pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
+                               def: ast::DefId)
+                               -> Option<ast::ImplPolarity>
+{
+    let cstore = &tcx.sess.cstore;
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_impl_polarity(&*cdata, def.node)
+}
+
 // Given a def_id for an impl, return the trait it implements,
 // if there is one.
 pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index dfbff715688..6bf1798d246 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -371,6 +371,15 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
     }
 }
 
+fn parse_polarity(item_doc: rbml::Doc) -> ast::ImplPolarity {
+    let polarity_doc = reader::get_doc(item_doc, tag_polarity);
+    if reader::doc_as_u8(polarity_doc) != 0 {
+        ast::ImplPolarity::Negative
+    } else {
+        ast::ImplPolarity::Positive
+    }
+}
+
 fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
     let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
     let mut names = Vec::new();
@@ -436,6 +445,20 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
     }
 }
 
+pub fn get_impl_polarity<'tcx>(cdata: Cmd,
+                               id: ast::NodeId)
+                               -> Option<ast::ImplPolarity>
+{
+    let item_doc = lookup_item(id, cdata.data());
+    let fam = item_family(item_doc);
+    match fam {
+        Family::Impl => {
+            Some(parse_polarity(item_doc))
+        }
+        _ => None
+    }
+}
+
 pub fn get_impl_trait<'tcx>(cdata: Cmd,
                             id: ast::NodeId,
                             tcx: &ty::ctxt<'tcx>)
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index a38814580f5..62649653a69 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -611,6 +611,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return Ok(None);
         }
 
+
         // If there are *NO* candidates, that there are no impls --
         // that we know of, anyway. Note that in the case where there
         // are unbound type variables within the obligation, it might
@@ -626,6 +627,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Just one candidate left.
         let candidate = candidates.pop().unwrap();
+
+        match candidate {
+            ImplCandidate(def_id) => {
+                match ty::trait_impl_polarity(self.tcx(), def_id) {
+                    Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
         Ok(Some(candidate))
     }
 
@@ -714,7 +726,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 debug!("obligation self ty is {}",
                        obligation.predicate.0.self_ty().repr(self.tcx()));
 
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
                 try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
                                                             stack,
@@ -722,10 +734,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
             Some(bound @ ty::BoundSend) |
             Some(bound @ ty::BoundSync) => {
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
                 // No explicit impls were declared for this type, consider the fallback rules.
-                if candidates.vec.is_empty() {
+                if candidates.vec.is_empty() && !candidates.ambiguous {
                     try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
                 }
             }
@@ -741,7 +753,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
                 try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
                 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
             }
         }
@@ -1013,9 +1025,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Search for impls that might apply to `obligation`.
     fn assemble_candidates_from_impls(&mut self,
                                       obligation: &TraitObligation<'tcx>,
-                                      candidate_vec: &mut Vec<SelectionCandidate<'tcx>>)
+                                      candidates: &mut SelectionCandidateSet<'tcx>)
                                       -> Result<(), SelectionError<'tcx>>
     {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx()));
+
         let all_impls = self.all_impls(obligation.predicate.def_id());
         for &impl_def_id in all_impls.iter() {
             self.infcx.probe(|snapshot| {
@@ -1024,7 +1039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 match self.match_impl(impl_def_id, obligation, snapshot,
                                       &skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
                     Ok(_) => {
-                        candidate_vec.push(ImplCandidate(impl_def_id));
+                        candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                     Err(()) => { }
                 }
@@ -2214,8 +2229,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     /// Returns set of all impls for a given trait.
     fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
-        ty::populate_implementations_for_trait_if_necessary(self.tcx(),
-                                                            trait_def_id);
+        ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_def_id);
+
         match self.tcx().trait_impls.borrow().get(&trait_def_id) {
             None => Vec::new(),
             Some(impls) => impls.borrow().clone()
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 11b605e2e2f..c72fbc74565 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -1891,7 +1891,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::R
 /// normal trait predicate (`T : TraitRef<...>`) and one of these
 /// predicates. Form #2 is a broader form in that it also permits
 /// equality between arbitrary types. Processing an instance of Form
-/// \#2 eventually yields one of these `ProjectionPredicate`
+/// #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
 #[derive(Clone, PartialEq, Eq, Hash, Show)]
 pub struct ProjectionPredicate<'tcx> {
@@ -5035,6 +5035,23 @@ pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId)
     }
 }
 
+pub fn trait_impl_polarity<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
+                            -> Option<ast::ImplPolarity> {
+     if id.krate == ast::LOCAL_CRATE {
+         match cx.map.find(id.node) {
+             Some(ast_map::NodeItem(item)) => {
+                 match item.node {
+                     ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
+                     _ => None
+                 }
+             }
+             _ => None
+         }
+     } else {
+         csearch::get_impl_polarity(cx, id)
+     }
+}
+
 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                                 -> ImplOrTraitItem<'tcx> {
     lookup_locally_or_in_crate_store("impl_or_trait_items",
@@ -5984,6 +6001,7 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
 pub fn record_trait_implementation(tcx: &ctxt,
                                    trait_def_id: DefId,
                                    impl_def_id: DefId) {
+
     match tcx.trait_impls.borrow().get(&trait_def_id) {
         Some(impls_for_trait) => {
             impls_for_trait.borrow_mut().push(impl_def_id);
@@ -5991,6 +6009,7 @@ pub fn record_trait_implementation(tcx: &ctxt,
         }
         None => {}
     }
+
     tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e4c333a0e1e..7e38321049e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1597,7 +1597,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     {
         debug!("register_predicate({})",
                obligation.repr(self.tcx()));
-
         self.inh.fulfillment_cx
             .borrow_mut()
             .register_predicate_obligation(self.infcx(), obligation);
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 89de1ea80fc..e6390212c60 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -56,9 +56,38 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                ty::item_path_str(ccx.tcx, local_def(item.id)));
 
         match item.node {
-            ast::ItemImpl(..) => {
+            /// Right now we check that every default trait implementation
+            /// has an implementation of itself. Basically, a case like:
+            ///
+            /// `impl Trait for T {}`
+            ///
+            /// has a requirement of `T: Trait` which was required for default
+            /// method implementations. Although this could be improved now that
+            /// there's a better infrastructure in place for this, it's being left
+            /// for a follow-up work.
+            ///
+            /// Since there's such a requirement, we need to check *just* positive
+            /// implementations, otherwise things like:
+            ///
+            /// impl !Send for T {}
+            ///
+            /// won't be allowed unless there's an *explicit* implementation of `Send`
+            /// for `T`
+            ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
                 self.check_impl(item);
             }
+            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
+                let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
+                match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
+                    Some(ty::BoundSend) | Some(ty::BoundSync) => {}
+                    Some(_) | None => {
+                        ccx.tcx.sess.span_err(
+                            item.span,
+                            format!("negative impls are currently \
+                                     allowed just for `Send` and `Sync`").as_slice())
+                    }
+                }
+            }
             ast::ItemFn(..) => {
                 self.check_item_type(item);
             }
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index f618a79e27d..ce7ba9ac11e 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -38,36 +38,34 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         // check_for_overlapping_impls_of_trait() check, since that
         // check can populate this table further with impls from other
         // crates.
-        let trait_def_ids: Vec<ast::DefId> =
-            self.tcx.trait_impls.borrow().keys().map(|&d| d).collect();
-
-        for trait_def_id in trait_def_ids.iter() {
-            self.check_for_overlapping_impls_of_trait(*trait_def_id);
+        let trait_def_ids: Vec<(ast::DefId, Vec<ast::DefId>)> =
+            self.tcx.trait_impls.borrow().iter().map(|(&k, v)| {
+                // FIXME -- it seems like this method actually pushes
+                // duplicate impls onto the list
+                ty::populate_implementations_for_trait_if_necessary(self.tcx, k);
+                (k, v.borrow().clone())
+            }).collect();
+
+        for &(trait_def_id, ref impls) in trait_def_ids.iter() {
+            self.check_for_overlapping_impls_of_trait(trait_def_id, impls);
         }
     }
 
     fn check_for_overlapping_impls_of_trait(&self,
-                                            trait_def_id: ast::DefId)
+                                            trait_def_id: ast::DefId,
+                                            trait_impls: &Vec<ast::DefId>)
     {
         debug!("check_for_overlapping_impls_of_trait(trait_def_id={})",
                trait_def_id.repr(self.tcx));
 
-        // FIXME -- it seems like this method actually pushes
-        // duplicate impls onto the list
-        ty::populate_implementations_for_trait_if_necessary(self.tcx,
-                                                            trait_def_id);
-
-        let mut impls = Vec::new();
-        self.push_impls_of_trait(trait_def_id, &mut impls);
-
-        for (i, &impl1_def_id) in impls.iter().enumerate() {
+        for (i, &impl1_def_id) in trait_impls.iter().enumerate() {
             if impl1_def_id.krate != ast::LOCAL_CRATE {
                 // we don't need to check impls if both are external;
                 // that's the other crate's job.
                 continue;
             }
 
-            for &impl2_def_id in impls.slice_from(i+1).iter() {
+            for &impl2_def_id in trait_impls.slice_from(i+1).iter() {
                 self.check_if_impls_overlap(trait_def_id,
                                             impl1_def_id,
                                             impl2_def_id);
@@ -108,15 +106,6 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         }
     }
 
-    fn push_impls_of_trait(&self,
-                           trait_def_id: ast::DefId,
-                           out: &mut Vec<ast::DefId>) {
-        match self.tcx.trait_impls.borrow().get(&trait_def_id) {
-            Some(impls) => { out.push_all(impls.borrow().as_slice()); }
-            None => { /* no impls */ }
-        }
-    }
-
     fn span_of_impl(&self, impl_did: ast::DefId) -> Span {
         assert_eq!(impl_did.krate, ast::LOCAL_CRATE);
         self.tcx.map.span(impl_did.node)
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 1acea6fd581..e30d0a29938 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -30,7 +30,7 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         match item.node {
-            ast::ItemImpl(unsafety, _, _, _, _, _) => {
+            ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
                 match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
                     None => {
                         // Inherent impl.
@@ -46,23 +46,34 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
 
                     Some(trait_ref) => {
                         let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
-                        match (trait_def.unsafety, unsafety) {
-                            (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
+                        match (trait_def.unsafety, unsafety, polarity) {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
+                                self.tcx.sess.span_err(
+                                    item.span,
+                                    format!("negative implementations are not unsafe").as_slice());
+                            }
+
+                            (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
                                 self.tcx.sess.span_err(
                                     item.span,
                                     format!("implementing the trait `{}` is not unsafe",
                                             trait_ref.user_string(self.tcx)).as_slice());
                             }
 
-                            (ast::Unsafety::Unsafe, ast::Unsafety::Normal) => {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
                                 self.tcx.sess.span_err(
                                     item.span,
                                     format!("the trait `{}` requires an `unsafe impl` declaration",
                                             trait_ref.user_string(self.tcx)).as_slice());
                             }
 
-                            (ast::Unsafety::Unsafe, ast::Unsafety::Unsafe) |
-                            (ast::Unsafety::Normal, ast::Unsafety::Normal) => {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
+                            (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
                                 /* OK */
                             }
                         }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 03d9030b025..182344452a4 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -110,6 +110,7 @@
 #![feature(slicing_syntax, unboxed_closures)]
 #![feature(box_syntax)]
 #![feature(old_impl_check)]
+#![feature(optin_builtin_traits)]
 #![allow(unknown_features)] #![feature(int_uint)]
 
 // Don't link to std. We are std.
diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs
index f174771a3e0..17e690e9540 100644
--- a/src/libstd/sync/mpsc/blocking.rs
+++ b/src/libstd/sync/mpsc/blocking.rs
@@ -14,6 +14,7 @@ use thread::Thread;
 use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 use sync::Arc;
 use marker::{Sync, Send};
+#[cfg(stage0)] // NOTE remove use after next snapshot
 use marker::{NoSend, NoSync};
 use mem;
 use clone::Clone;
@@ -31,12 +32,25 @@ pub struct SignalToken {
     inner: Arc<Inner>,
 }
 
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct WaitToken {
     inner: Arc<Inner>,
     no_send: NoSend,
     no_sync: NoSync,
 }
 
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct WaitToken {
+    inner: Arc<Inner>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !Send for WaitToken {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !Sync for WaitToken {}
+
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub fn tokens() -> (WaitToken, SignalToken) {
     let inner = Arc::new(Inner {
         thread: Thread::current(),
@@ -53,6 +67,21 @@ pub fn tokens() -> (WaitToken, SignalToken) {
     (wait_token, signal_token)
 }
 
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub fn tokens() -> (WaitToken, SignalToken) {
+    let inner = Arc::new(Inner {
+        thread: Thread::current(),
+        woken: ATOMIC_BOOL_INIT,
+    });
+    let wait_token = WaitToken {
+        inner: inner.clone(),
+    };
+    let signal_token = SignalToken {
+        inner: inner
+    };
+    (wait_token, signal_token)
+}
+
 impl SignalToken {
     pub fn signal(&self) -> bool {
         let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index eca7d3155b1..0ba19b70617 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -370,12 +370,24 @@ unsafe impl<T:Send> Send for Sender<T> { }
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct SyncSender<T> {
     inner: Arc<RacyCell<sync::Packet<T>>>,
     // can't share in an arc
     _marker: marker::NoSync,
 }
 
+/// The sending-half of Rust's synchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct SyncSender<T> {
+    inner: Arc<RacyCell<sync::Packet<T>>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Sync for SyncSender<T> {}
+
 /// An error returned from the `send` function on channels.
 ///
 /// A `send` operation can only fail if the receiving end of a channel is
@@ -677,10 +689,16 @@ impl<T: Send> Drop for Sender<T> {
 ////////////////////////////////////////////////////////////////////////////////
 
 impl<T: Send> SyncSender<T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner, _marker: marker::NoSync }
     }
 
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
+        SyncSender { inner: inner }
+    }
+
     /// Sends a value on this synchronous channel.
     ///
     /// This function will *block* until space in the internal buffer becomes
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 0da458a51f1..62a7b823ec8 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -66,6 +66,7 @@ use sync::mpsc::blocking::{self, SignalToken};
 
 /// The "receiver set" of the select interface. This structure is used to manage
 /// a set of receivers which are being selected over.
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Select {
     head: *mut Handle<'static, ()>,
     tail: *mut Handle<'static, ()>,
@@ -73,6 +74,18 @@ pub struct Select {
     marker1: marker::NoSend,
 }
 
+/// The "receiver set" of the select interface. This structure is used to manage
+/// a set of receivers which are being selected over.
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Select {
+    head: *mut Handle<'static, ()>,
+    tail: *mut Handle<'static, ()>,
+    next_id: Cell<uint>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !marker::Send for Select {}
+
 /// A handle to a receiver which is currently a member of a `Select` set of
 /// receivers.  This handle is used to keep the receiver in the set as well as
 /// interact with the underlying receiver.
@@ -113,6 +126,7 @@ impl Select {
     ///
     /// Usage of this struct directly can sometimes be burdensome, and usage is
     /// rather much easier through the `select!` macro.
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     pub fn new() -> Select {
         Select {
             marker1: marker::NoSend,
@@ -122,6 +136,20 @@ impl Select {
         }
     }
 
+    /// Creates a new selection structure. This set is initially empty and
+    /// `wait` will panic!() if called.
+    ///
+    /// Usage of this struct directly can sometimes be burdensome, and usage is
+    /// rather much easier through the `select!` macro.
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn new() -> Select {
+        Select {
+            head: 0 as *mut Handle<'static, ()>,
+            tail: 0 as *mut Handle<'static, ()>,
+            next_id: Cell::new(1),
+        }
+    }
+
     /// Creates a new handle into this receiver set for a new receiver. Note
     /// that this does *not* add the receiver to the receiver set, for that you
     /// must call the `add` method on the handle itself.
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index c1b55c6ff78..73d5332d16f 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -160,6 +160,7 @@ unsafe impl Sync for StaticMutex {}
 /// Deref and DerefMut implementations
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct MutexGuard<'a, T: 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
@@ -169,6 +170,25 @@ pub struct MutexGuard<'a, T: 'a> {
     __marker: marker::NoSend,
 }
 
+/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
+/// dropped (falls out of scope), the lock will be unlocked.
+///
+/// The data protected by the mutex can be access through this guard via its
+/// Deref and DerefMut implementations
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct MutexGuard<'a, T: 'a> {
+    // funny underscores due to how Deref/DerefMut currently work (they
+    // disregard field privacy).
+    __lock: &'a StaticMutex,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
+
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
 #[unstable = "may be merged with Mutex in the future"]
@@ -279,6 +299,7 @@ impl StaticMutex {
 }
 
 impl<'mutex, T> MutexGuard<'mutex, T> {
+    #[cfg(stage0)] // NOTE remove afte next snapshot
     fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
            -> LockResult<MutexGuard<'mutex, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
@@ -290,6 +311,18 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg afte next snapshot
+    fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
+           -> LockResult<MutexGuard<'mutex, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            MutexGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+            }
+        })
+    }
 }
 
 #[stable]
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 7db2111cc46..237f6d08a95 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -110,16 +110,31 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
 /// dropped.
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct RwLockReadGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
     __marker: marker::NoSend,
 }
 
+/// RAII structure used to release the shared read access of a lock when
+/// dropped.
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct RwLockReadGuard<'a, T: 'a> {
+    __lock: &'a StaticRwLock,
+    __data: &'a UnsafeCell<T>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {}
+
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct RwLockWriteGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
@@ -127,6 +142,20 @@ pub struct RwLockWriteGuard<'a, T: 'a> {
     __marker: marker::NoSend,
 }
 
+/// RAII structure used to release the exclusive write access of a lock when
+/// dropped.
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct RwLockWriteGuard<'a, T: 'a> {
+    __lock: &'a StaticRwLock,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {}
+
 impl<T: Send + Sync> RwLock<T> {
     /// Creates a new instance of an RwLock which is unlocked and read to go.
     #[stable]
@@ -303,6 +332,7 @@ impl StaticRwLock {
 }
 
 impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockReadGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |_| {
@@ -313,8 +343,20 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RwLockReadGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |_| {
+            RwLockReadGuard {
+                __lock: lock,
+                __data: data,
+            }
+        })
+    }
 }
 impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockWriteGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
@@ -326,6 +368,18 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RwLockWriteGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            RwLockWriteGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+            }
+        })
+    }
 }
 
 #[stable]
diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
new file mode 100644
index 00000000000..c9dfb8201a9
--- /dev/null
+++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
@@ -0,0 +1,29 @@
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+trait MyTrait {}
+
+struct TestType<T>;
+
+unsafe impl<T: MyTrait> Send for TestType<T> {}
+//~^ ERROR conflicting implementations for trait `core::marker::Send`
+//~^^ ERROR conflicting implementations for trait `core::marker::Send`
+
+impl<T: MyTrait> !Send for TestType<T> {}
+//~^ ERROR conflicting implementations for trait `core::marker::Send`
+
+unsafe impl<T> Send for TestType<T> {}
+//~^ ERROR error: conflicting implementations for trait `core::marker::Send`
+
+impl !Send for TestType<i32> {}
+
+fn main() {}
diff --git a/src/test/compile-fail/marker-no-share.rs b/src/test/compile-fail/coherence-negative-impls-safe.rs
index b29f7fab2cc..3b335d586f3 100644
--- a/src/test/compile-fail/marker-no-share.rs
+++ b/src/test/compile-fail/coherence-negative-impls-safe.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-fn foo<P: Sync>(p: P) { }
+use std::marker::Send;
 
-fn main()
-{
-    foo(marker::NoSync); //~ ERROR the trait `core::marker::Sync` is not implemented
-}
+struct TestType;
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative implementations are not unsafe
+
+fn main() {}
diff --git a/src/test/compile-fail/coherence-orphan.rs b/src/test/compile-fail/coherence-orphan.rs
index 0bd0224b246..f9f965e1ae3 100644
--- a/src/test/compile-fail/coherence-orphan.rs
+++ b/src/test/compile-fail/coherence-orphan.rs
@@ -8,8 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
 // aux-build:coherence-orphan-lib.rs
 
+#![feature(optin_builtin_traits)]
+
 extern crate "coherence-orphan-lib" as lib;
 
 use lib::TheTrait;
@@ -22,4 +25,7 @@ impl TheTrait<TheType> for isize { } //~ ERROR E0117
 
 impl TheTrait<isize> for TheType { }
 
+impl !Send for Vec<isize> { } //~ ERROR E0117
+//~^ ERROR conflicting
+
 fn main() { }
diff --git a/src/test/compile-fail/issue-17718-static-sync.rs b/src/test/compile-fail/issue-17718-static-sync.rs
index 394a9cc69be..fa8035a7965 100644
--- a/src/test/compile-fail/issue-17718-static-sync.rs
+++ b/src/test/compile-fail/issue-17718-static-sync.rs
@@ -8,12 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-struct Foo { marker: marker::NoSync }
+use std::marker::Sync;
+
+struct Foo;
+impl !Sync for Foo {}
 
 static FOO: usize = 3;
-static BAR: Foo = Foo { marker: marker::NoSync };
+static BAR: Foo = Foo;
 //~^ ERROR: the trait `core::marker::Sync` is not implemented
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs
index d246e4e54d0..90ecfb6015d 100644
--- a/src/test/compile-fail/issue-7013.rs
+++ b/src/test/compile-fail/issue-7013.rs
@@ -35,5 +35,4 @@ struct A {
 fn main() {
     let a = A {v: box B{v: None} as Box<Foo+Send>};
     //~^ ERROR the trait `core::marker::Send` is not implemented
-    //~^^ ERROR the trait `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs
index 79aec386d9a..5bc769f8e11 100644
--- a/src/test/compile-fail/kindck-nonsendable-1.rs
+++ b/src/test/compile-fail/kindck-nonsendable-1.rs
@@ -19,6 +19,5 @@ fn main() {
     let x = Rc::new(3us);
     bar(move|| foo(x));
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
 
diff --git a/src/test/compile-fail/mutable-enum-indirect.rs b/src/test/compile-fail/mutable-enum-indirect.rs
index f90bb610d37..1657d602e24 100644
--- a/src/test/compile-fail/mutable-enum-indirect.rs
+++ b/src/test/compile-fail/mutable-enum-indirect.rs
@@ -11,13 +11,18 @@
 // Tests that an `&` pointer to something inherently mutable is itself
 // to be considered mutable.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-enum Foo { A(marker::NoSync) }
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSync);
+    let x = Foo::A(NoSync);
     bar(&x); //~ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs
index 551953af135..52335ab76bd 100644
--- a/src/test/compile-fail/no-send-res-ports.rs
+++ b/src/test/compile-fail/no-send-res-ports.rs
@@ -37,7 +37,6 @@ fn main() {
 
     Thread::spawn(move|| {
         //~^ ERROR `core::marker::Send` is not implemented
-        //~^^ ERROR `core::marker::Send` is not implemented
         let y = x;
         println!("{:?}", y);
     });
diff --git a/src/test/compile-fail/no_send-enum.rs b/src/test/compile-fail/no_send-enum.rs
index cf1f13e8bb8..625d51260c4 100644
--- a/src/test/compile-fail/no_send-enum.rs
+++ b/src/test/compile-fail/no_send-enum.rs
@@ -8,16 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct NoSend;
+impl !Send for NoSend {}
 
 enum Foo {
-    A(marker::NoSend)
+    A(NoSend)
 }
 
 fn bar<T: Send>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSend);
+    let x = Foo::A(NoSend);
     bar(x);
     //~^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_send-rc.rs b/src/test/compile-fail/no_send-rc.rs
index 82cc319466a..d404988bd98 100644
--- a/src/test/compile-fail/no_send-rc.rs
+++ b/src/test/compile-fail/no_send-rc.rs
@@ -16,5 +16,4 @@ fn main() {
     let x = Rc::new(5is);
     bar(x);
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_send-struct.rs b/src/test/compile-fail/no_send-struct.rs
index bef70523787..7f16db0ba94 100644
--- a/src/test/compile-fail/no_send-struct.rs
+++ b/src/test/compile-fail/no_send-struct.rs
@@ -8,17 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
 
 struct Foo {
     a: isize,
-    ns: marker::NoSend
 }
 
+impl !Send for Foo {}
+
 fn bar<T: Send>(_: T) {}
 
 fn main() {
-    let x = Foo { a: 5, ns: marker::NoSend };
+    let x = Foo { a: 5 };
     bar(x);
     //~^ ERROR the trait `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-enum.rs b/src/test/compile-fail/no_share-enum.rs
index 33222eef44e..9331afdbbb5 100644
--- a/src/test/compile-fail/no_share-enum.rs
+++ b/src/test/compile-fail/no_share-enum.rs
@@ -8,14 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-enum Foo { A(marker::NoSync) }
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSync);
+    let x = Foo::A(NoSync);
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-rc.rs b/src/test/compile-fail/no_share-rc.rs
index 0d3e380d4a1..4917db602e1 100644
--- a/src/test/compile-fail/no_share-rc.rs
+++ b/src/test/compile-fail/no_share-rc.rs
@@ -17,5 +17,4 @@ fn main() {
     let x = Rc::new(RefCell::new(5is));
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
-    //~^^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-struct.rs b/src/test/compile-fail/no_share-struct.rs
index c7028ce9786..b5ccceb3b2a 100644
--- a/src/test/compile-fail/no_share-struct.rs
+++ b/src/test/compile-fail/no_share-struct.rs
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-struct Foo { a: isize, m: marker::NoSync }
+use std::marker::Sync;
+
+struct Foo { a: isize }
+impl !Sync for Foo {}
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo { a: 5, m: marker::NoSync };
+    let x = Foo { a: 5 };
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/task-rng-isnt-sendable.rs b/src/test/compile-fail/task-rng-isnt-sendable.rs
index fe31d81983e..dc3385f4bb9 100644
--- a/src/test/compile-fail/task-rng-isnt-sendable.rs
+++ b/src/test/compile-fail/task-rng-isnt-sendable.rs
@@ -17,5 +17,4 @@ fn test_send<S: Send>() {}
 pub fn main() {
     test_send::<rand::ThreadRng>();
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/traits-negative-impls.rs b/src/test/compile-fail/traits-negative-impls.rs
new file mode 100644
index 00000000000..3ef760053c7
--- /dev/null
+++ b/src/test/compile-fail/traits-negative-impls.rs
@@ -0,0 +1,58 @@
+// Copyright 2015 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.
+
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct TestType;
+impl !Send for TestType {}
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+    Outer(TestType);
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+    is_send(TestType);
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+    is_send((8, TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn dummy2() {
+    is_send(Box::new(TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn dummy3() {
+    is_send(Box::new(Outer2(TestType)));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn main() {
+    // This will complain about a missing Send impl because `Sync` is implement *just*
+    // for T that are `Send`. Look at #20366 and #19950
+    is_sync(Outer2(TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs
new file mode 100644
index 00000000000..9da79b11cf0
--- /dev/null
+++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+struct TestType;
+
+trait TestTrait {}
+
+impl !TestTrait for TestType {}
+//~^ ERROR  negative impls are currently allowed just for `Send` and `Sync`
+
+fn main() {}
diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs
index a9113c6e99f..38e3b576348 100644
--- a/src/test/compile-fail/typeck-unsafe-always-share.rs
+++ b/src/test/compile-fail/typeck-unsafe-always-share.rs
@@ -10,29 +10,26 @@
 
 // Verify that UnsafeCell is *always* sync regardless if `T` is sync.
 
-// ignore-tidy-linelength
+#![feature(optin_builtin_traits)]
 
 use std::cell::UnsafeCell;
-use std::marker;
+use std::marker::Sync;
 
 struct MySync<T> {
     u: UnsafeCell<T>
 }
 
-struct NoSync {
-    m: marker::NoSync
-}
-
-fn test<T: Sync>(s: T){
+struct NoSync;
+impl !Sync for NoSync {}
 
-}
+fn test<T: Sync>(s: T) {}
 
 fn main() {
     let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0is)});
     test(us);
     //~^ ERROR `core::marker::Sync` is not implemented
 
-    let uns = UnsafeCell::new(NoSync{m: marker::NoSync});
+    let uns = UnsafeCell::new(NoSync);
     test(uns);
     //~^ ERROR `core::marker::Sync` is not implemented
 
@@ -40,7 +37,6 @@ fn main() {
     test(ms);
     //~^ ERROR `core::marker::Sync` is not implemented
 
-    let ns = NoSync{m: marker::NoSync};
-    test(ns);
+    test(NoSync);
     //~^ ERROR `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs
index 4b7f11b0560..322de45daf0 100644
--- a/src/test/compile-fail/unique-unique-kind.rs
+++ b/src/test/compile-fail/unique-unique-kind.rs
@@ -19,5 +19,4 @@ fn main() {
     let i = box Rc::new(100is);
     f(i);
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs
index abd93fdfc6c..f51eee37934 100644
--- a/src/test/compile-fail/unsendable-class.rs
+++ b/src/test/compile-fail/unsendable-class.rs
@@ -31,6 +31,5 @@ fn main() {
   let cat = "kitty".to_string();
   let (tx, _) = channel();
   //~^ ERROR `core::marker::Send` is not implemented
-  //~^^ ERROR `core::marker::Send` is not implemented
   tx.send(foo(42, Rc::new(cat)));
 }
diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs
index 47c36ac7a40..7d3a921301e 100644
--- a/src/test/pretty/trait-polarity.rs
+++ b/src/test/pretty/trait-polarity.rs
@@ -12,12 +12,8 @@
 
 // pp-exact
 
-trait UnsafeTrait {
-    fn foo(&self);
-}
+struct Test;
 
-impl !UnsafeTrait for int {
-    fn foo(&self) { }
-}
+impl !Send for Test { }
 
 pub fn main() { }
diff --git a/src/test/compile-fail/marker-no-send.rs b/src/test/run-pass/coherence-negative-impls-safe.rs
index 032718d7e9a..7844ef3faca 100644
--- a/src/test/compile-fail/marker-no-send.rs
+++ b/src/test/run-pass/coherence-negative-impls-safe.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-fn foo<P:Send>(p: P) { }
+use std::marker::Send;
 
-fn main()
-{
-    foo(marker::NoSend); //~ ERROR the trait `core::marker::Send` is not implemented
-}
+struct TestType;
+
+impl !Send for TestType {}
+
+fn main() {}
diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs
index a91e5da1537..3344844d49f 100644
--- a/src/test/run-pass/syntax-trait-polarity.rs
+++ b/src/test/run-pass/syntax-trait-polarity.rs
@@ -18,14 +18,12 @@ impl TestType {}
 
 trait TestTrait {}
 
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
+impl !Send for TestType {}
 
 struct TestType2<T>;
 
 impl<T> TestType2<T> {}
 
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
+impl<T> !Send for TestType2<T> {}
 
 fn main() {}
diff --git a/src/test/run-pass/traits-negative-impls.rs b/src/test/run-pass/traits-negative-impls.rs
new file mode 100644
index 00000000000..09c7d077705
--- /dev/null
+++ b/src/test/run-pass/traits-negative-impls.rs
@@ -0,0 +1,29 @@
+// Copyright 2015 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.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(T);
+unsafe impl<T: 'static> Send for Test<T> {}
+
+pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
+
+fn main() {
+    let wt = Test(WaitToken);
+    spawn(move || {
+        let x = wt;
+        println!("Hello, World!");
+    });
+}