Skip to content

Commit

Permalink
auto merge of #20972 : FlaPer87/rust/oibit-send-and-friends, r=nikoma…
Browse files Browse the repository at this point in the history
…tsakis

This PR adds rules for negative implementations. It follows pretty much what the [RFC](https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md) says with 1 main difference:

Instead of positive implementations override negative implementations, this have been implemented in a way that a negative implementation of `Trait` for `T` will overlap with a positive implementation, causing a coherence error.

@nikomatsakis r?

cc #13231

[breaking-change]
  • Loading branch information
bors committed Jan 16, 2015
2 parents f3d71be + cb85223 commit ee2bfae
Show file tree
Hide file tree
Showing 42 changed files with 676 additions and 105 deletions.
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Expand Up @@ -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]
Expand Down
159 changes: 159 additions & 0 deletions src/liballoc/rc.rs
Expand Up @@ -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
Expand All @@ -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>`.
///
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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();
Expand All @@ -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.
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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."]
Expand Down
5 changes: 3 additions & 2 deletions src/libcore/cell.rs
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/marker.rs
Expand Up @@ -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
Expand All @@ -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
Expand Down
9 changes: 9 additions & 0 deletions src/librustc/metadata/csearch.rs
Expand Up @@ -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>,
Expand Down
23 changes: 23 additions & 0 deletions src/librustc/metadata/decoder.rs
Expand Up @@ -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();
Expand Down Expand Up @@ -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>)
Expand Down

0 comments on commit ee2bfae

Please sign in to comment.