diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 4a85637625a22..6c85330603514 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 f42c6dbdc15a5..0e18cdda8dd89 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -174,6 +174,7 @@ struct RcBox { /// 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 { // 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 { _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 { + // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained + // type via Deref + _ptr: NonZero<*mut RcBox>, +} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +impl !marker::Send for Rc {} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +impl !marker::Sync for Rc {} + impl Rc { /// Constructs a new `Rc`. /// @@ -193,6 +212,7 @@ impl Rc { /// let five = Rc::new(5i); /// ``` #[stable] + #[cfg(stage0)] // NOTE remove after next snapshot pub fn new(value: T) -> Rc { unsafe { Rc { @@ -210,6 +230,32 @@ impl Rc { } } + /// Constructs a new `Rc`. + /// + /// # 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 { + 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` to a `Weak` reference. /// /// # Examples @@ -221,6 +267,7 @@ impl Rc { /// /// 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 { self.inc_weak(); @@ -230,6 +277,24 @@ impl Rc { _noshare: marker::NoSync } } + + /// Downgrades the `Rc` to a `Weak` 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 { + self.inc_weak(); + Weak { _ptr: self._ptr } + } } /// Get the number of weak references to this value. @@ -432,10 +497,31 @@ impl Clone for Rc { /// five.clone(); /// ``` #[inline] + #[cfg(stage0)] // NOTE remove after next snapshot fn clone(&self) -> Rc { self.inc_strong(); Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync } } + + /// Makes a clone of the `Rc`. + /// + /// 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 { + self.inc_strong(); + Rc { _ptr: self._ptr } + } } #[stable] @@ -636,6 +722,7 @@ impl fmt::String for Rc { /// 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 { // 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 { _noshare: marker::NoSync } +/// A weak version of `Rc`. +/// +/// 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 { + // FIXME #12808: strange names to try to avoid interfering with + // field accesses of the contained type via Deref + _ptr: NonZero<*mut RcBox>, +} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +#[allow(unstable)] +impl !marker::Send for Weak {} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +#[allow(unstable)] +impl !marker::Sync for Weak {} + + #[unstable = "Weak pointers may not belong in this module."] impl Weak { /// Upgrades a weak reference to a strong reference. @@ -663,6 +773,7 @@ impl Weak { /// /// let strong_five: Option> = weak_five.upgrade(); /// ``` + #[cfg(stage0)] // NOTE remove after next snapshot pub fn upgrade(&self) -> Option> { if self.strong() == 0 { None @@ -671,6 +782,33 @@ impl Weak { Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }) } } + + /// Upgrades a weak reference to a strong reference. + /// + /// Upgrades the `Weak` reference to an `Rc`, 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> = weak_five.upgrade(); + /// ``` + #[cfg(not(stage0))] // NOTE remove cfg after next snapshot + pub fn upgrade(&self) -> Option> { + if self.strong() == 0 { + None + } else { + self.inc_strong(); + Some(Rc { _ptr: self._ptr }) + } + } } #[unsafe_destructor] @@ -733,10 +871,31 @@ impl Clone for Weak { /// weak_five.clone(); /// ``` #[inline] + #[cfg(stage0)] // NOTE remove after next snapshot fn clone(&self) -> Weak { self.inc_weak(); Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync } } + + /// Makes a clone of the `Weak`. + /// + /// 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 { + self.inc_weak(); + Weak { _ptr: self._ptr } + } } #[unstable = "Show is experimental."] diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 6db01b7cb7afe..ec4007c4c6dd4 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 { /// value: UnsafeCell, -/// marker: marker::NoSync /// } +/// +/// unsafe impl Sync for NotThreadSafe {} /// ``` /// /// **NOTE:** `UnsafeCell` fields are public to allow static initializers. It diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d400cb47cbff6..715a79abe8540 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 0bbd11bea0a48..e34fb37e1c555 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 +{ + 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 dfbff7156886d..6bf1798d246a4 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 { 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 { } } +pub fn get_impl_polarity<'tcx>(cdata: Cmd, + id: ast::NodeId) + -> Option +{ + 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 a38814580f54c..62649653a6972 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>) + 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 { - 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 11b605e2e2fec..c72fbc745651a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1891,7 +1891,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate, 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 { + 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 { 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 e4c333a0e1ea5..7e38321049ed7 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 89de1ea80fcf4..e6390212c6002 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 f618a79e27de7..ce7ba9ac11e65 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 = - 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)> = + 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) { 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) { - 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 1acea6fd58179..e30d0a29938aa 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 03d9030b02517..182344452a484 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 f174771a3e011..17e690e954092 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, } +#[cfg(stage0)] // NOTE remove impl after next snapshot pub struct WaitToken { inner: Arc, no_send: NoSend, no_sync: NoSync, } +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +pub struct WaitToken { + inner: Arc, +} + +#[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 eca7d3155b18b..0ba19b706176b 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -370,12 +370,24 @@ unsafe impl Send for Sender { } /// 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 { inner: Arc>>, // 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 { + inner: Arc>>, +} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +impl !marker::Sync for SyncSender {} + /// 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 Drop for Sender { //////////////////////////////////////////////////////////////////////////////// impl SyncSender { + #[cfg(stage0)] // NOTE remove impl after next snapshot fn new(inner: Arc>>) -> SyncSender { SyncSender { inner: inner, _marker: marker::NoSync } } + #[cfg(not(stage0))] // NOTE remove cfg after next snapshot + fn new(inner: Arc>>) -> SyncSender { + 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 0da458a51f108..62a7b823ec8ac 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, +} + +#[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 c1b55c6ff78db..73d5332d16fe4 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, + __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) -> LockResult> { 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) + -> LockResult> { + 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 7db2111cc4629..237f6d08a9541 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, __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, +} + +#[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, @@ -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, + __poison: poison::Guard, +} + +#[cfg(not(stage0))] // NOTE remove cfg after next snapshot +impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {} + impl RwLock { /// 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) -> LockResult> { 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) + -> LockResult> { + 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) -> LockResult> { 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) + -> LockResult> { + 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 0000000000000..c9dfb8201a98a --- /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 or the MIT license +// , 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; + +unsafe impl Send for TestType {} +//~^ ERROR conflicting implementations for trait `core::marker::Send` +//~^^ ERROR conflicting implementations for trait `core::marker::Send` + +impl !Send for TestType {} +//~^ ERROR conflicting implementations for trait `core::marker::Send` + +unsafe impl Send for TestType {} +//~^ ERROR error: conflicting implementations for trait `core::marker::Send` + +impl !Send for TestType {} + +fn main() {} diff --git a/src/test/compile-fail/marker-no-share.rs b/src/test/compile-fail/coherence-negative-impls-safe.rs similarity index 62% rename from src/test/compile-fail/marker-no-share.rs rename to src/test/compile-fail/coherence-negative-impls-safe.rs index b29f7fab2ccfc..3b335d586f391 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: 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 0bd0224b246d1..f9f965e1ae39d 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 for isize { } //~ ERROR E0117 impl TheTrait for TheType { } +impl !Send for Vec { } //~ 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 394a9cc69bee7..fa8035a79652e 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 d246e4e54d017..90ecfb6015dcd 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}; //~^ 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 79aec386d9a77..5bc769f8e117b 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 f90bb610d3741..1657d602e24c4 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) {} 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 551953af13520..52335ab76bda2 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 cf1f13e8bb868..625d51260c4dc 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) {} 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 82cc319466a6d..d404988bd9848 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 bef7052378726..7f16db0ba947b 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) {} 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 33222eef44e74..9331afdbbb5d7 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) {} 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 0d3e380d4a122..4917db602e175 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 c7028ce978698..b5ccceb3b2a7d 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) {} 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 fe31d81983e16..dc3385f4bb92f 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() {} pub fn main() { test_send::(); //~^ 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 0000000000000..3ef760053c709 --- /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 or the MIT license +// , 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); + +struct TestType; +impl !Send for TestType {} + +struct Outer2(T); + +unsafe impl Sync for Outer2 {} + +fn is_send(_: T) {} +fn is_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 0000000000000..9da79b11cf0b7 --- /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 or the MIT license +// , 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 a9113c6e99f43..38e3b57634838 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 { u: UnsafeCell } -struct NoSync { - m: marker::NoSync -} - -fn test(s: T){ +struct NoSync; +impl !Sync for NoSync {} -} +fn test(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 4b7f11b05609c..322de45daf03e 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 abd93fdfc6c61..f51eee379347c 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 47c36ac7a40de..7d3a921301e34 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 similarity index 66% rename from src/test/compile-fail/marker-no-send.rs rename to src/test/run-pass/coherence-negative-impls-safe.rs index 032718d7e9a10..7844ef3faca45 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: 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 a91e5da153768..3344844d49ff7 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; impl TestType2 {} -unsafe impl !Send for TestType2 {} -impl !TestTrait for TestType2 {} +impl !Send for TestType2 {} 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 0000000000000..09c7d077705b5 --- /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 or the MIT license +// , 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); +unsafe impl Send for Test {} + +pub fn spawn(_: F) -> () where F: FnOnce(), F: Send + 'static {} + +fn main() { + let wt = Test(WaitToken); + spawn(move || { + let x = wt; + println!("Hello, World!"); + }); +}