Rename Share
to Sync
This leaves the `Share` trait at `std::kinds` via a `#[deprecated]` `pub use` statement, but the `NoShare` struct is no longer part of `std::kinds::marker` due to #12660 (the build cannot bootstrap otherwise). All code referencing the `Share` trait should now reference the `Sync` trait, and all code referencing the `NoShare` type should now reference the `NoSync` type. The functionality and meaning of this trait have not changed, only the naming. Closes #16281 [breaking-change]
This commit is contained in:
parent
b09a02b415
commit
1f760d5d1a
59 changed files with 199 additions and 190 deletions
|
@ -50,15 +50,15 @@ non-deterministic behavior. Rust provides the tools to make using a GC
|
|||
possible and even pleasant, but it should not be a requirement for
|
||||
implementing the language.
|
||||
|
||||
## Non-`Share` `static mut` is unsafe
|
||||
## Non-`Sync` `static mut` is unsafe
|
||||
|
||||
Types which are [`Share`][share] are thread-safe when multiple shared
|
||||
references to them are used concurrently. Types which are not `Share` are not
|
||||
Types which are [`Sync`][sync] are thread-safe when multiple shared
|
||||
references to them are used concurrently. Types which are not `Sync` are not
|
||||
thread-safe, and thus when used in a global require unsafe code to use.
|
||||
|
||||
[share]: http://doc.rust-lang.org/core/kinds/trait.Share.html
|
||||
[sync]: http://doc.rust-lang.org/core/kinds/trait.Sync.html
|
||||
|
||||
### If mutable static items that implement `Share` are safe, why is taking &mut SHARABLE unsafe?
|
||||
### If mutable static items that implement `Sync` are safe, why is taking &mut SHARABLE unsafe?
|
||||
|
||||
Having multiple aliasing `&mut T`s is never allowed. Due to the nature of
|
||||
globals, the borrow checker cannot possibly ensure that a static obeys the
|
||||
|
|
|
@ -699,10 +699,10 @@ Other features provided by lang items include:
|
|||
- stack unwinding and general failure; the `eh_personality`, `fail_`
|
||||
and `fail_bounds_checks` lang items.
|
||||
- the traits in `std::kinds` used to indicate types that satisfy
|
||||
various kinds; lang items `send`, `share` and `copy`.
|
||||
various kinds; lang items `send`, `sync` and `copy`.
|
||||
- the marker types and variance indicators found in
|
||||
`std::kinds::markers`; lang items `covariant_type`,
|
||||
`contravariant_lifetime`, `no_share_bound`, etc.
|
||||
`contravariant_lifetime`, `no_sync_bound`, etc.
|
||||
|
||||
Lang items are loaded lazily by the compiler; e.g. if one never uses
|
||||
`Box` then there is no need to define functions for `exchange_malloc`
|
||||
|
|
|
@ -2111,7 +2111,7 @@ A complete list of the built-in language items follows:
|
|||
: Has a size known at compile time.
|
||||
* `copy`
|
||||
: Types that do not move ownership when used by-value.
|
||||
* `share`
|
||||
* `sync`
|
||||
: Able to be safely shared between tasks when aliased.
|
||||
* `drop`
|
||||
: Have destructors.
|
||||
|
@ -2191,8 +2191,8 @@ These types help drive the compiler's analysis
|
|||
: This type does not implement "send", even if eligible
|
||||
* `no_copy_bound`
|
||||
: This type does not implement "copy", even if eligible
|
||||
* `no_share_bound`
|
||||
: This type does not implement "share", even if eligible
|
||||
* `no_sync_bound`
|
||||
: This type does not implement "sync", even if eligible
|
||||
* `managed_bound`
|
||||
: This type implements "managed"
|
||||
|
||||
|
|
|
@ -2196,7 +2196,7 @@ and may not be overridden:
|
|||
Types are sendable
|
||||
unless they contain references.
|
||||
|
||||
* `Share` - Types that are *threadsafe*.
|
||||
* `Sync` - Types that are *threadsafe*.
|
||||
These are types that are safe to be used across several threads with access to
|
||||
a `&T` pointer. `Mutex<T>` is an example of a *sharable* type with internal mutable data.
|
||||
|
||||
|
@ -2250,7 +2250,7 @@ We say that the `Printable` trait _provides_ a `print` method with the
|
|||
given signature. This means that we can call `print` on an argument
|
||||
of any type that implements the `Printable` trait.
|
||||
|
||||
Rust's built-in `Send` and `Share` types are examples of traits that
|
||||
Rust's built-in `Send` and `Sync` types are examples of traits that
|
||||
don't provide any methods.
|
||||
|
||||
Traits may be implemented for specific types with [impls]. An impl for
|
||||
|
@ -2535,7 +2535,7 @@ select the method to call at runtime.
|
|||
|
||||
This usage of traits is similar to Java interfaces.
|
||||
|
||||
There are some built-in bounds, such as `Send` and `Share`, which are properties
|
||||
There are some built-in bounds, such as `Send` and `Sync`, which are properties
|
||||
of the components of types. By design, trait objects don't know the exact type
|
||||
of their contents and so the compiler cannot reason about those properties.
|
||||
|
||||
|
@ -2548,7 +2548,7 @@ trait Foo {}
|
|||
trait Bar<T> {}
|
||||
|
||||
fn sendable_foo(f: Box<Foo + Send>) { /* ... */ }
|
||||
fn shareable_bar<T: Share>(b: &Bar<T> + Share) { /* ... */ }
|
||||
fn sync_bar<T: Sync>(b: &Bar<T> + Sync) { /* ... */ }
|
||||
~~~
|
||||
|
||||
When no colon is specified (such as the type `Box<Foo>`), it is inferred that the
|
||||
|
|
|
@ -76,7 +76,7 @@ syn keyword rustType f64 i8 i16 i32 i64 str Self
|
|||
" to make it easy to update.
|
||||
|
||||
" Core operators {{{3
|
||||
syn keyword rustTrait Copy Send Sized Share
|
||||
syn keyword rustTrait Copy Send Sized Sync
|
||||
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
|
||||
syn keyword rustTrait BitAnd BitOr BitXor
|
||||
syn keyword rustTrait Drop Deref DerefMut
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use core::atomic;
|
||||
use core::clone::Clone;
|
||||
use core::kinds::{Share, Send};
|
||||
use core::kinds::{Sync, Send};
|
||||
use core::mem::{min_align_of, size_of, drop};
|
||||
use core::mem;
|
||||
use core::ops::{Drop, Deref};
|
||||
|
@ -76,7 +76,7 @@ struct ArcInner<T> {
|
|||
data: T,
|
||||
}
|
||||
|
||||
impl<T: Share + Send> Arc<T> {
|
||||
impl<T: Sync + Send> Arc<T> {
|
||||
/// Create an atomically reference counted wrapper.
|
||||
#[inline]
|
||||
#[stable]
|
||||
|
@ -95,8 +95,8 @@ impl<T: Share + Send> Arc<T> {
|
|||
fn inner(&self) -> &ArcInner<T> {
|
||||
// This unsafety is ok because while this arc is alive we're guaranteed
|
||||
// that the inner pointer is valid. Furthermore, we know that the
|
||||
// `ArcInner` structure itself is `Share` because the inner data is
|
||||
// `Share` as well, so we're ok loaning out an immutable pointer to
|
||||
// `ArcInner` structure itself is `Sync` because the inner data is
|
||||
// `Sync` as well, so we're ok loaning out an immutable pointer to
|
||||
// these contents.
|
||||
unsafe { &*self._ptr }
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ impl<T: Share + Send> Arc<T> {
|
|||
}
|
||||
|
||||
#[unstable = "waiting on stability of Clone"]
|
||||
impl<T: Share + Send> Clone for Arc<T> {
|
||||
impl<T: Sync + Send> Clone for Arc<T> {
|
||||
/// Duplicate an atomically reference counted wrapper.
|
||||
///
|
||||
/// The resulting two `Arc` objects will point to the same underlying data
|
||||
|
@ -140,14 +140,14 @@ impl<T: Share + Send> Clone for Arc<T> {
|
|||
}
|
||||
|
||||
#[experimental = "Deref is experimental."]
|
||||
impl<T: Send + Share> Deref<T> for Arc<T> {
|
||||
impl<T: Send + Sync> Deref<T> for Arc<T> {
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
&self.inner().data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Share + Clone> Arc<T> {
|
||||
impl<T: Send + Sync + Clone> Arc<T> {
|
||||
/// Acquires a mutable pointer to the inner contents by guaranteeing that
|
||||
/// the reference count is one (no sharing is possible).
|
||||
///
|
||||
|
@ -175,7 +175,7 @@ impl<T: Send + Share + Clone> Arc<T> {
|
|||
|
||||
#[unsafe_destructor]
|
||||
#[experimental = "waiting on stability of Drop"]
|
||||
impl<T: Share + Send> Drop for Arc<T> {
|
||||
impl<T: Sync + Send> Drop for Arc<T> {
|
||||
fn drop(&mut self) {
|
||||
// This structure has #[unsafe_no_drop_flag], so this drop glue may run
|
||||
// more than once (but it is guaranteed to be zeroed after the first if
|
||||
|
@ -219,7 +219,7 @@ impl<T: Share + Send> Drop for Arc<T> {
|
|||
}
|
||||
|
||||
#[experimental = "Weak pointers may not belong in this module."]
|
||||
impl<T: Share + Send> Weak<T> {
|
||||
impl<T: Sync + Send> Weak<T> {
|
||||
/// Attempts to upgrade this weak reference to a strong reference.
|
||||
///
|
||||
/// This method will fail to upgrade this reference if the strong reference
|
||||
|
@ -245,7 +245,7 @@ impl<T: Share + Send> Weak<T> {
|
|||
}
|
||||
|
||||
#[experimental = "Weak pointers may not belong in this module."]
|
||||
impl<T: Share + Send> Clone for Weak<T> {
|
||||
impl<T: Sync + Send> Clone for Weak<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Weak<T> {
|
||||
// See comments in Arc::clone() for why this is relaxed
|
||||
|
@ -256,7 +256,7 @@ impl<T: Share + Send> Clone for Weak<T> {
|
|||
|
||||
#[unsafe_destructor]
|
||||
#[experimental = "Weak pointers may not belong in this module."]
|
||||
impl<T: Share + Send> Drop for Weak<T> {
|
||||
impl<T: Sync + Send> Drop for Weak<T> {
|
||||
fn drop(&mut self) {
|
||||
// see comments above for why this check is here
|
||||
if self._ptr.is_null() { return }
|
||||
|
|
|
@ -179,7 +179,7 @@ pub struct Rc<T> {
|
|||
// field accesses of the contained type via Deref
|
||||
_ptr: *mut RcBox<T>,
|
||||
_nosend: marker::NoSend,
|
||||
_noshare: marker::NoShare
|
||||
_noshare: marker::NoSync
|
||||
}
|
||||
|
||||
#[stable]
|
||||
|
@ -199,7 +199,7 @@ impl<T> Rc<T> {
|
|||
weak: Cell::new(1)
|
||||
}),
|
||||
_nosend: marker::NoSend,
|
||||
_noshare: marker::NoShare
|
||||
_noshare: marker::NoSync
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ impl<T> Rc<T> {
|
|||
Weak {
|
||||
_ptr: self._ptr,
|
||||
_nosend: marker::NoSend,
|
||||
_noshare: marker::NoShare
|
||||
_noshare: marker::NoSync
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ impl<T> Clone for Rc<T> {
|
|||
#[inline]
|
||||
fn clone(&self) -> Rc<T> {
|
||||
self.inc_strong();
|
||||
Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare }
|
||||
Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ pub struct Weak<T> {
|
|||
// field accesses of the contained type via Deref
|
||||
_ptr: *mut RcBox<T>,
|
||||
_nosend: marker::NoSend,
|
||||
_noshare: marker::NoShare
|
||||
_noshare: marker::NoSync
|
||||
}
|
||||
|
||||
#[experimental = "Weak pointers may not belong in this module."]
|
||||
|
@ -423,7 +423,7 @@ impl<T> Weak<T> {
|
|||
None
|
||||
} else {
|
||||
self.inc_strong();
|
||||
Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare })
|
||||
Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ impl<T> Clone for Weak<T> {
|
|||
#[inline]
|
||||
fn clone(&self) -> Weak<T> {
|
||||
self.inc_weak();
|
||||
Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoShare }
|
||||
Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ use option::{None, Option, Some};
|
|||
#[unstable = "likely to be renamed; otherwise stable"]
|
||||
pub struct Cell<T> {
|
||||
value: UnsafeCell<T>,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
|
@ -174,7 +174,7 @@ impl<T:Copy> Cell<T> {
|
|||
pub fn new(value: T) -> Cell<T> {
|
||||
Cell {
|
||||
value: UnsafeCell::new(value),
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ pub struct RefCell<T> {
|
|||
value: UnsafeCell<T>,
|
||||
borrow: Cell<BorrowFlag>,
|
||||
nocopy: marker::NoCopy,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
// Values [1, MAX-1] represent the number of `Ref` active
|
||||
|
@ -230,7 +230,7 @@ impl<T> RefCell<T> {
|
|||
value: UnsafeCell::new(value),
|
||||
borrow: Cell::new(UNUSED),
|
||||
nocopy: marker::NoCopy,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,7 +430,7 @@ impl<'b, T> DerefMut<T> for RefMut<'b, T> {
|
|||
///
|
||||
/// struct NotThreadSafe<T> {
|
||||
/// value: UnsafeCell<T>,
|
||||
/// marker: marker::NoShare
|
||||
/// marker: marker::NoSync
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -20,6 +20,9 @@ by the compiler automatically for the types to which they apply.
|
|||
|
||||
*/
|
||||
|
||||
#[deprecated = "This has been renamed to Sync"]
|
||||
pub use Share = self::Sync;
|
||||
|
||||
/// Types able to be transferred across task boundaries.
|
||||
#[lang="send"]
|
||||
pub trait Send {
|
||||
|
@ -40,32 +43,32 @@ pub trait Copy {
|
|||
|
||||
/// Types that can be safely shared between tasks when aliased.
|
||||
///
|
||||
/// The precise definition is: a type `T` is `Share` if `&T` is
|
||||
/// The precise definition is: a type `T` is `Sync` if `&T` is
|
||||
/// thread-safe. In other words, there is no possibility of data races
|
||||
/// when passing `&T` references between tasks.
|
||||
///
|
||||
/// As one would expect, primitive types like `u8` and `f64` are all
|
||||
/// `Share`, and so are simple aggregate types containing them (like
|
||||
/// tuples, structs and enums). More instances of basic `Share` types
|
||||
/// `Sync`, and so are simple aggregate types containing them (like
|
||||
/// tuples, structs and enums). More instances of basic `Sync` types
|
||||
/// include "immutable" types like `&T` and those with simple
|
||||
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
|
||||
/// collection types. (Generic parameters need to be `Share` for their
|
||||
/// container to be `Share`.)
|
||||
/// collection types. (Generic parameters need to be `Sync` for their
|
||||
/// container to be `Sync`.)
|
||||
///
|
||||
/// A somewhat surprising consequence of the definition is `&mut T` is
|
||||
/// `Share` (if `T` is `Share`) even though it seems that it might
|
||||
/// `Sync` (if `T` is `Sync`) even though it seems that it might
|
||||
/// provide unsynchronised mutation. The trick is a mutable reference
|
||||
/// stored in an aliasable reference (that is, `& &mut T`) becomes
|
||||
/// read-only, as if it were a `& &T`, hence there is no risk of a data
|
||||
/// race.
|
||||
///
|
||||
/// Types that are not `Share` are those that have "interior
|
||||
/// Types that are not `Sync` are those that have "interior
|
||||
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
|
||||
/// in `std::cell`. These types allow for mutation of their contents
|
||||
/// even when in an immutable, aliasable slot, e.g. the contents of
|
||||
/// `&Cell<T>` can be `.set`, and do not ensure data races are
|
||||
/// impossible, hence they cannot be `Share`. A higher level example
|
||||
/// of a non-`Share` type is the reference counted pointer
|
||||
/// impossible, hence they cannot be `Sync`. A higher level example
|
||||
/// of a non-`Sync` type is the reference counted pointer
|
||||
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
|
||||
/// reference, which modifies the reference counts in a non-atomic
|
||||
/// way.
|
||||
|
@ -73,18 +76,25 @@ pub trait Copy {
|
|||
/// For cases when one does need thread-safe interior mutability,
|
||||
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
|
||||
/// the `sync` crate do ensure that any mutation cannot cause data
|
||||
/// races. Hence these types are `Share`.
|
||||
/// races. Hence these types are `Sync`.
|
||||
///
|
||||
/// Users writing their own types with interior mutability (or anything
|
||||
/// else that is not thread-safe) should use the `NoShare` marker type
|
||||
/// else that is not thread-safe) should use the `NoSync` marker type
|
||||
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
|
||||
/// consider the user-defined type to be `Share`. Any types with
|
||||
/// consider the user-defined type to be `Sync`. Any types with
|
||||
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
|
||||
/// around the value(s) which can be mutated when behind a `&`
|
||||
/// reference; not doing this is undefined behaviour (for example,
|
||||
/// `transmute`-ing from `&T` to `&mut T` is illegal).
|
||||
#[lang="sync"]
|
||||
#[cfg(not(stage0))]
|
||||
pub trait Sync {
|
||||
// Empty
|
||||
}
|
||||
/// dox
|
||||
#[lang="share"]
|
||||
pub trait Share {
|
||||
#[cfg(stage0)]
|
||||
pub trait Sync {
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
@ -94,7 +104,6 @@ pub trait Share {
|
|||
/// implemented using unsafe code. In that case, you may want to embed
|
||||
/// some of the marker types below into your type.
|
||||
pub mod marker {
|
||||
|
||||
/// A marker type whose type parameter `T` is considered to be
|
||||
/// covariant with respect to the type itself. This is (typically)
|
||||
/// used to indicate that an instance of the type `T` is being stored
|
||||
|
@ -266,12 +275,12 @@ pub mod marker {
|
|||
#[deriving(PartialEq,Clone)]
|
||||
pub struct NoCopy;
|
||||
|
||||
/// A type which is considered "not shareable", meaning that
|
||||
/// A type which is considered "not sync", meaning that
|
||||
/// its contents are not threadsafe, hence they cannot be
|
||||
/// shared between tasks.
|
||||
#[lang="no_share_bound"]
|
||||
#[deriving(PartialEq,Clone)]
|
||||
pub struct NoShare;
|
||||
pub struct NoSync;
|
||||
|
||||
/// A type which is considered managed by the GC. This is typically
|
||||
/// embedded in other types.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
//! ```
|
||||
|
||||
// Reexported core operators
|
||||
pub use kinds::{Copy, Send, Sized, Share};
|
||||
pub use kinds::{Copy, Send, Sized, Sync};
|
||||
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
|
||||
pub use ops::{BitAnd, BitOr, BitXor};
|
||||
pub use ops::{Drop, Deref, DerefMut};
|
||||
|
|
|
@ -20,18 +20,18 @@ pub enum PopResult<T> {
|
|||
|
||||
pub fn queue<T: Send>() -> (Consumer<T>, Producer<T>) {
|
||||
let a = Arc::new(mpsc::Queue::new());
|
||||
(Consumer { inner: a.clone(), noshare: marker::NoShare },
|
||||
Producer { inner: a, noshare: marker::NoShare })
|
||||
(Consumer { inner: a.clone(), noshare: marker::NoSync },
|
||||
Producer { inner: a, noshare: marker::NoSync })
|
||||
}
|
||||
|
||||
pub struct Producer<T> {
|
||||
inner: Arc<mpsc::Queue<T>>,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
pub struct Consumer<T> {
|
||||
inner: Arc<mpsc::Queue<T>>,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
impl<T: Send> Consumer<T> {
|
||||
|
@ -60,6 +60,6 @@ impl<T: Send> Producer<T> {
|
|||
|
||||
impl<T: Send> Clone for Producer<T> {
|
||||
fn clone(&self) -> Producer<T> {
|
||||
Producer { inner: self.inner.clone(), noshare: marker::NoShare }
|
||||
Producer { inner: self.inner.clone(), noshare: marker::NoSync }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -633,7 +633,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
|
|||
param_bounds.builtin_bounds.add(ty::BoundCopy);
|
||||
}
|
||||
'T' => {
|
||||
param_bounds.builtin_bounds.add(ty::BoundShare);
|
||||
param_bounds.builtin_bounds.add(ty::BoundSync);
|
||||
}
|
||||
'I' => {
|
||||
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
|
||||
|
|
|
@ -352,7 +352,7 @@ fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
|
|||
ty::BoundStatic => mywrite!(w, "O"),
|
||||
ty::BoundSized => mywrite!(w, "Z"),
|
||||
ty::BoundCopy => mywrite!(w, "P"),
|
||||
ty::BoundShare => mywrite!(w, "T"),
|
||||
ty::BoundSync => mywrite!(w, "T"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// Language items are items that represent concepts intrinsic to the language
|
||||
// itself. Examples are:
|
||||
//
|
||||
// * Traits that specify "kinds"; e.g. "Share", "Send".
|
||||
// * Traits that specify "kinds"; e.g. "Sync", "Send".
|
||||
//
|
||||
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
|
||||
//
|
||||
|
@ -92,8 +92,8 @@ impl LanguageItems {
|
|||
Some(ty::BoundSized)
|
||||
} else if Some(id) == self.copy_trait() {
|
||||
Some(ty::BoundCopy)
|
||||
} else if Some(id) == self.share_trait() {
|
||||
Some(ty::BoundShare)
|
||||
} else if Some(id) == self.sync_trait() {
|
||||
Some(ty::BoundSync)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ lets_do_this! {
|
|||
SendTraitLangItem, "send", send_trait;
|
||||
SizedTraitLangItem, "sized", sized_trait;
|
||||
CopyTraitLangItem, "copy", copy_trait;
|
||||
ShareTraitLangItem, "share", share_trait;
|
||||
SyncTraitLangItem, "sync", sync_trait;
|
||||
|
||||
DropTraitLangItem, "drop", drop_trait;
|
||||
|
||||
|
@ -296,7 +296,7 @@ lets_do_this! {
|
|||
|
||||
NoSendItem, "no_send_bound", no_send_bound;
|
||||
NoCopyItem, "no_copy_bound", no_copy_bound;
|
||||
NoShareItem, "no_share_bound", no_share_bound;
|
||||
NoSyncItem, "no_share_bound", no_share_bound;
|
||||
ManagedItem, "managed_bound", managed_bound;
|
||||
|
||||
IteratorItem, "iterator", iterator;
|
||||
|
|
|
@ -499,7 +499,7 @@ impl TypeMap {
|
|||
ty::BoundSend => unique_type_id.push_str("Send"),
|
||||
ty::BoundSized => unique_type_id.push_str("Sized"),
|
||||
ty::BoundCopy => unique_type_id.push_str("Copy"),
|
||||
ty::BoundShare => unique_type_id.push_str("Share"),
|
||||
ty::BoundSync => unique_type_id.push_str("Sync"),
|
||||
};
|
||||
unique_type_id.push_char('+');
|
||||
}
|
||||
|
|
|
@ -833,7 +833,7 @@ pub enum BuiltinBound {
|
|||
BoundSend,
|
||||
BoundSized,
|
||||
BoundCopy,
|
||||
BoundShare,
|
||||
BoundSync,
|
||||
}
|
||||
|
||||
pub fn empty_builtin_bounds() -> BuiltinBounds {
|
||||
|
@ -845,7 +845,7 @@ pub fn all_builtin_bounds() -> BuiltinBounds {
|
|||
set.add(BoundStatic);
|
||||
set.add(BoundSend);
|
||||
set.add(BoundSized);
|
||||
set.add(BoundShare);
|
||||
set.add(BoundSync);
|
||||
set
|
||||
}
|
||||
|
||||
|
@ -1804,7 +1804,7 @@ def_type_content_sets!(
|
|||
ReachesBorrowed = 0b0000_0010__0000_0000__0000,
|
||||
// ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
|
||||
ReachesMutable = 0b0000_1000__0000_0000__0000,
|
||||
ReachesNoShare = 0b0001_0000__0000_0000__0000,
|
||||
ReachesNoSync = 0b0001_0000__0000_0000__0000,
|
||||
ReachesAll = 0b0001_1111__0000_0000__0000,
|
||||
|
||||
// Things that cause values to *move* rather than *copy*
|
||||
|
@ -1828,8 +1828,8 @@ def_type_content_sets!(
|
|||
// Things that prevent values from being considered sized
|
||||
Nonsized = 0b0000_0000__0000_0000__0001,
|
||||
|
||||
// Things that prevent values from being shared
|
||||
Nonsharable = 0b0001_0000__0000_0000__0000,
|
||||
// Things that prevent values from being sync
|
||||
Nonsync = 0b0001_0000__0000_0000__0000,
|
||||
|
||||
// Things that make values considered not POD (would be same
|
||||
// as `Moves`, but for the fact that managed data `@` is
|
||||
|
@ -1855,7 +1855,7 @@ impl TypeContents {
|
|||
BoundSend => self.is_sendable(cx),
|
||||
BoundSized => self.is_sized(cx),
|
||||
BoundCopy => self.is_copy(cx),
|
||||
BoundShare => self.is_sharable(cx),
|
||||
BoundSync => self.is_sync(cx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1875,8 +1875,8 @@ impl TypeContents {
|
|||
!self.intersects(TC::Nonsendable)
|
||||
}
|
||||
|
||||
pub fn is_sharable(&self, _: &ctxt) -> bool {
|
||||
!self.intersects(TC::Nonsharable)
|
||||
pub fn is_sync(&self, _: &ctxt) -> bool {
|
||||
!self.intersects(TC::Nonsync)
|
||||
}
|
||||
|
||||
pub fn owns_managed(&self) -> bool {
|
||||
|
@ -2169,11 +2169,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
|
|||
} else if Some(did) == cx.lang_items.no_copy_bound() {
|
||||
tc | TC::OwnsAffine
|
||||
} else if Some(did) == cx.lang_items.no_share_bound() {
|
||||
tc | TC::ReachesNoShare
|
||||
tc | TC::ReachesNoSync
|
||||
} else if Some(did) == cx.lang_items.unsafe_type() {
|
||||
// FIXME(#13231): This shouldn't be needed after
|
||||
// opt-in built-in bounds are implemented.
|
||||
(tc | TC::InteriorUnsafe) - TC::Nonsharable
|
||||
(tc | TC::InteriorUnsafe) - TC::Nonsync
|
||||
} else {
|
||||
tc
|
||||
}
|
||||
|
@ -2237,7 +2237,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
|
|||
BoundSend => TC::Nonsendable,
|
||||
BoundSized => TC::Nonsized,
|
||||
BoundCopy => TC::Noncopy,
|
||||
BoundShare => TC::Nonsharable,
|
||||
BoundSync => TC::Nonsync,
|
||||
};
|
||||
});
|
||||
return tc;
|
||||
|
|
|
@ -646,7 +646,7 @@ impl Repr for ty::ParamBounds {
|
|||
ty::BoundSend => "Send".to_string(),
|
||||
ty::BoundSized => "Sized".to_string(),
|
||||
ty::BoundCopy => "Copy".to_string(),
|
||||
ty::BoundShare => "Share".to_string(),
|
||||
ty::BoundSync => "Sync".to_string(),
|
||||
});
|
||||
}
|
||||
for t in self.trait_bounds.iter() {
|
||||
|
@ -931,7 +931,7 @@ impl UserString for ty::BuiltinBound {
|
|||
ty::BoundSend => "Send".to_string(),
|
||||
ty::BoundSized => "Sized".to_string(),
|
||||
ty::BoundCopy => "Copy".to_string(),
|
||||
ty::BoundShare => "Share".to_string(),
|
||||
ty::BoundSync => "Sync".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -535,9 +535,9 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
|
|||
ty::BoundCopy =>
|
||||
(tcx.lang_items.copy_trait().unwrap(),
|
||||
external_path("Copy", &empty)),
|
||||
ty::BoundShare =>
|
||||
(tcx.lang_items.share_trait().unwrap(),
|
||||
external_path("Share", &empty)),
|
||||
ty::BoundSync =>
|
||||
(tcx.lang_items.sync_trait().unwrap(),
|
||||
external_path("Sync", &empty)),
|
||||
};
|
||||
let fqn = csearch::get_item_path(tcx, did);
|
||||
let fqn = fqn.move_iter().map(|i| i.to_string()).collect();
|
||||
|
|
|
@ -112,7 +112,7 @@ struct TLDValueBox<T> {
|
|||
// refcount of 0 means uninitialized value, 1 means initialized, 2+ means
|
||||
// borrowed.
|
||||
// NB: we use UnsafeCell instead of Cell because Ref should be allowed to
|
||||
// be Share. The only mutation occurs when a Ref is created or destroyed,
|
||||
// be Sync. The only mutation occurs when a Ref is created or destroyed,
|
||||
// so there's no issue with &Ref being thread-safe.
|
||||
refcount: UnsafeCell<uint>
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#![experimental]
|
||||
|
||||
// Reexported core operators
|
||||
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Share};
|
||||
#[doc(no_inline)] pub use kinds::{Copy, Send, Sized, Sync};
|
||||
#[doc(no_inline)] pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
|
||||
#[doc(no_inline)] pub use ops::{BitAnd, BitOr, BitXor};
|
||||
#[doc(no_inline)] pub use ops::{Drop, Deref, DerefMut};
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
//!
|
||||
//! [1]: http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
|
||||
//!
|
||||
//! Atomic variables are safe to share between threads (they implement `Share`)
|
||||
//! Atomic variables are safe to share between threads (they implement `Sync`)
|
||||
//! but they do not themselves provide the mechanism for sharing. The most
|
||||
//! common way to share an atomic variable is to put it into an `Arc` (an
|
||||
//! atomically-reference-counted shared pointer).
|
||||
|
|
|
@ -375,7 +375,7 @@ pub struct Receiver<T> {
|
|||
inner: UnsafeCell<Flavor<T>>,
|
||||
receives: Cell<uint>,
|
||||
// can't share in an arc
|
||||
marker: marker::NoShare,
|
||||
marker: marker::NoSync,
|
||||
}
|
||||
|
||||
/// An iterator over messages on a receiver, this iterator will block
|
||||
|
@ -393,7 +393,7 @@ pub struct Sender<T> {
|
|||
inner: UnsafeCell<Flavor<T>>,
|
||||
sends: Cell<uint>,
|
||||
// can't share in an arc
|
||||
marker: marker::NoShare,
|
||||
marker: marker::NoSync,
|
||||
}
|
||||
|
||||
/// The sending-half of Rust's synchronous channel type. This half can only be
|
||||
|
@ -402,7 +402,7 @@ pub struct Sender<T> {
|
|||
pub struct SyncSender<T> {
|
||||
inner: Arc<UnsafeCell<sync::Packet<T>>>,
|
||||
// can't share in an arc
|
||||
marker: marker::NoShare,
|
||||
marker: marker::NoSync,
|
||||
}
|
||||
|
||||
/// This enumeration is the list of the possible reasons that try_recv could not
|
||||
|
@ -537,7 +537,7 @@ impl<T: Send> Sender<T> {
|
|||
Sender {
|
||||
inner: UnsafeCell::new(inner),
|
||||
sends: Cell::new(0),
|
||||
marker: marker::NoShare,
|
||||
marker: marker::NoSync,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,7 +713,7 @@ impl<T: Send> Drop for Sender<T> {
|
|||
|
||||
impl<T: Send> SyncSender<T> {
|
||||
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
|
||||
SyncSender { inner: inner, marker: marker::NoShare }
|
||||
SyncSender { inner: inner, marker: marker::NoSync }
|
||||
}
|
||||
|
||||
/// Sends a value on this synchronous channel.
|
||||
|
@ -801,7 +801,7 @@ impl<T: Send> Drop for SyncSender<T> {
|
|||
|
||||
impl<T: Send> Receiver<T> {
|
||||
fn new(inner: Flavor<T>) -> Receiver<T> {
|
||||
Receiver { inner: UnsafeCell::new(inner), receives: Cell::new(0), marker: marker::NoShare }
|
||||
Receiver { inner: UnsafeCell::new(inner), receives: Cell::new(0), marker: marker::NoSync }
|
||||
}
|
||||
|
||||
/// Blocks waiting for a value on this receiver
|
||||
|
|
|
@ -87,7 +87,7 @@ struct Deque<T> {
|
|||
/// There may only be one worker per deque.
|
||||
pub struct Worker<T> {
|
||||
deque: Arc<Deque<T>>,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
/// The stealing half of the work-stealing deque. Stealers have access to the
|
||||
|
@ -95,7 +95,7 @@ pub struct Worker<T> {
|
|||
/// `steal` method.
|
||||
pub struct Stealer<T> {
|
||||
deque: Arc<Deque<T>>,
|
||||
noshare: marker::NoShare,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
/// When stealing some data, this is an enumeration of the possible outcomes.
|
||||
|
@ -153,8 +153,8 @@ impl<T: Send> BufferPool<T> {
|
|||
pub fn deque(&self) -> (Worker<T>, Stealer<T>) {
|
||||
let a = Arc::new(Deque::new(self.clone()));
|
||||
let b = a.clone();
|
||||
(Worker { deque: a, noshare: marker::NoShare },
|
||||
Stealer { deque: b, noshare: marker::NoShare })
|
||||
(Worker { deque: a, noshare: marker::NoSync },
|
||||
Stealer { deque: b, noshare: marker::NoSync })
|
||||
}
|
||||
|
||||
fn alloc(&mut self, bits: uint) -> Box<Buffer<T>> {
|
||||
|
@ -217,7 +217,7 @@ impl<T: Send> Stealer<T> {
|
|||
|
||||
impl<T: Send> Clone for Stealer<T> {
|
||||
fn clone(&self) -> Stealer<T> {
|
||||
Stealer { deque: self.deque.clone(), noshare: marker::NoShare }
|
||||
Stealer { deque: self.deque.clone(), noshare: marker::NoSync }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ pub struct RWLockReadGuard<'a, T> {
|
|||
_guard: raw::RWLockReadGuard<'a>,
|
||||
}
|
||||
|
||||
impl<T: Send + Share> RWLock<T> {
|
||||
impl<T: Send + Sync> RWLock<T> {
|
||||
/// Create a reader/writer lock with the supplied data.
|
||||
pub fn new(user_data: T) -> RWLock<T> {
|
||||
RWLock::new_with_condvars(user_data, 1)
|
||||
|
@ -359,7 +359,7 @@ impl<T: Send + Share> RWLock<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Send + Share> RWLockWriteGuard<'a, T> {
|
||||
impl<'a, T: Send + Sync> RWLockWriteGuard<'a, T> {
|
||||
/// Consumes this write lock token, returning a new read lock token.
|
||||
///
|
||||
/// This will allow pending readers to come into the lock.
|
||||
|
@ -375,13 +375,13 @@ impl<'a, T: Send + Share> RWLockWriteGuard<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Send + Share> Deref<T> for RWLockReadGuard<'a, T> {
|
||||
impl<'a, T: Send + Sync> Deref<T> for RWLockReadGuard<'a, T> {
|
||||
fn deref<'a>(&'a self) -> &'a T { self._data }
|
||||
}
|
||||
impl<'a, T: Send + Share> Deref<T> for RWLockWriteGuard<'a, T> {
|
||||
impl<'a, T: Send + Sync> Deref<T> for RWLockWriteGuard<'a, T> {
|
||||
fn deref<'a>(&'a self) -> &'a T { &*self._data }
|
||||
}
|
||||
impl<'a, T: Send + Share> DerefMut<T> for RWLockWriteGuard<'a, T> {
|
||||
impl<'a, T: Send + Sync> DerefMut<T> for RWLockWriteGuard<'a, T> {
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut T { &mut *self._data }
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ impl WaitQueue {
|
|||
// The building-block used to make semaphores, mutexes, and rwlocks.
|
||||
struct Sem<Q> {
|
||||
lock: mutex::Mutex,
|
||||
// n.b, we need Sem to be `Share`, but the WaitQueue type is not send/share
|
||||
// n.b, we need Sem to be `Sync`, but the WaitQueue type is not send/share
|
||||
// (for good reason). We have an internal invariant on this semaphore,
|
||||
// however, that the queue is never accessed outside of a locked
|
||||
// context.
|
||||
|
|
|
@ -208,7 +208,7 @@ pub static DUMMY_NODE_ID: NodeId = -1;
|
|||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Share.
|
||||
/// detects Copy, Send and Sync.
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(TraitRef),
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn expand_deriving_bound(cx: &mut ExtCtxt,
|
|||
match tname.get() {
|
||||
"Copy" => "Copy",
|
||||
"Send" => "Send",
|
||||
"Share" => "Share",
|
||||
"Sync" => "Sync",
|
||||
ref tname => {
|
||||
cx.span_bug(span,
|
||||
format!("expected built-in trait name but \
|
||||
|
|
|
@ -94,7 +94,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
|
|||
"FromPrimitive" => expand!(primitive::expand_deriving_from_primitive),
|
||||
|
||||
"Send" => expand!(bounds::expand_deriving_bound),
|
||||
"Share" => expand!(bounds::expand_deriving_bound),
|
||||
"Sync" => expand!(bounds::expand_deriving_bound),
|
||||
"Copy" => expand!(bounds::expand_deriving_bound),
|
||||
|
||||
ref tname => {
|
||||
|
|
|
@ -18,17 +18,17 @@ struct arc_destruct<T> {
|
|||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T: Share> Drop for arc_destruct<T> {
|
||||
impl<T: Sync> Drop for arc_destruct<T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn arc_destruct<T: Share>(data: int) -> arc_destruct<T> {
|
||||
fn arc_destruct<T: Sync>(data: int) -> arc_destruct<T> {
|
||||
arc_destruct {
|
||||
_data: data
|
||||
}
|
||||
}
|
||||
|
||||
fn arc<T: Share>(_data: T) -> arc_destruct<T> {
|
||||
fn arc<T: Sync>(_data: T) -> arc_destruct<T> {
|
||||
arc_destruct(0)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
|
||||
#![crate_type="lib"]
|
||||
|
||||
pub trait RequiresShare : Share { }
|
||||
pub trait RequiresShare : Sync { }
|
||||
pub trait RequiresRequiresShareAndSend : RequiresShare + Send { }
|
||||
pub trait RequiresCopy : Copy { }
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
// Test for traits that inherit from multiple builtin kinds at once,
|
||||
// testing that all such kinds must be present on implementing types.
|
||||
|
||||
trait Foo : Send+Share { }
|
||||
trait Foo : Send+Sync { }
|
||||
|
||||
impl <T: Share> Foo for (T,) { } //~ ERROR cannot implement this trait
|
||||
impl <T: Sync> Foo for (T,) { } //~ ERROR cannot implement this trait
|
||||
|
||||
impl <T: Send> Foo for (T,T) { } //~ ERROR cannot implement this trait
|
||||
|
||||
impl <T: Send+Share> Foo for (T,T,T) { } // (ok)
|
||||
impl <T: Send+Sync> Foo for (T,T,T) { } // (ok)
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -19,8 +19,8 @@ use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
|
|||
|
||||
struct X<T>(T);
|
||||
|
||||
impl <T:Share> RequiresShare for X<T> { }
|
||||
impl <T:Sync> RequiresShare for X<T> { }
|
||||
|
||||
impl <T:Share> RequiresRequiresShareAndSend for X<T> { } //~ ERROR cannot implement this trait
|
||||
impl <T:Sync> RequiresRequiresShareAndSend for X<T> { } //~ ERROR cannot implement this trait
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
// Tests (negatively) the ability for the Self type in default methods
|
||||
// to use capabilities granted by builtin kinds as supertraits.
|
||||
|
||||
trait Foo : Share {
|
||||
trait Foo : Sync {
|
||||
fn foo(self, mut chan: Sender<Self>) {
|
||||
chan.send(self); //~ ERROR does not fulfill `Send`
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: Share> Foo for T { }
|
||||
impl <T: Sync> Foo for T { }
|
||||
|
||||
fn main() {
|
||||
let (tx, rx) = channel();
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
|
||||
trait Foo : Send { }
|
||||
|
||||
impl <T: Share> Foo for T { } //~ ERROR cannot implement this trait
|
||||
impl <T: Sync> Foo for T { } //~ ERROR cannot implement this trait
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
fn take_any(_: ||:) {
|
||||
}
|
||||
|
||||
fn take_const_owned(_: ||:Share+Send) {
|
||||
fn take_const_owned(_: ||:Sync+Send) {
|
||||
}
|
||||
|
||||
fn give_any(f: ||:) {
|
||||
|
@ -21,7 +21,7 @@ fn give_any(f: ||:) {
|
|||
|
||||
fn give_owned(f: ||:Send) {
|
||||
take_any(f);
|
||||
take_const_owned(f); //~ ERROR expected bounds `Send+Share` but found bounds `Send`
|
||||
take_const_owned(f); //~ ERROR expected bounds `Send+Sync` but found bounds `Send`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn test<T: Share>() {}
|
||||
fn test<T: Sync>() {}
|
||||
|
||||
fn main() {
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Share`
|
||||
test::<Receiver<int>>(); //~ ERROR: does not fulfill `Share`
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Share`
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Sync`
|
||||
test::<Receiver<int>>(); //~ ERROR: does not fulfill `Sync`
|
||||
test::<Sender<int>>(); //~ ERROR: does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[deriving(Share(Bad),Send,Copy)]
|
||||
#[deriving(Sync(Bad),Send,Copy)]
|
||||
//~^ ERROR unexpected value in deriving, expected a trait
|
||||
struct Test;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct E {
|
|||
}
|
||||
|
||||
impl A for E {
|
||||
fn b<F: Share, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Share`
|
||||
fn b<F: Sync, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Sync`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
use std::kinds::marker;
|
||||
|
||||
fn foo<P: Share>(p: P) { }
|
||||
fn foo<P: Sync>(p: P) { }
|
||||
|
||||
fn main()
|
||||
{
|
||||
foo(marker::NoShare); //~ ERROR does not fulfill `Share`
|
||||
foo(marker::NoSync); //~ ERROR does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn f<T: Share>(_: T) {}
|
||||
fn f<T: Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = RefCell::new(0i);
|
||||
f(x); //~ ERROR: which does not fulfill `Share`
|
||||
f(x); //~ ERROR: which does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
use std::kinds::marker;
|
||||
|
||||
enum Foo { A(marker::NoShare) }
|
||||
enum Foo { A(marker::NoSync) }
|
||||
|
||||
fn bar<T: Share>(_: T) {}
|
||||
fn bar<T: Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = A(marker::NoShare);
|
||||
let x = A(marker::NoSync);
|
||||
bar(&x); //~ ERROR type parameter with an incompatible type
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
|
||||
use std::kinds::marker;
|
||||
|
||||
enum Foo { A(marker::NoShare) }
|
||||
enum Foo { A(marker::NoSync) }
|
||||
|
||||
fn bar<T: Share>(_: T) {}
|
||||
fn bar<T: Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = A(marker::NoShare);
|
||||
let x = A(marker::NoSync);
|
||||
bar(x);
|
||||
//~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
|
||||
// which does not fulfill `Share`
|
||||
// which does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn bar<T: Share>(_: T) {}
|
||||
fn bar<T: Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = Rc::new(RefCell::new(5i));
|
||||
bar(x);
|
||||
//~^ ERROR instantiating a type parameter with an incompatible type
|
||||
// `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Share`
|
||||
// `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
|
||||
use std::kinds::marker;
|
||||
|
||||
struct Foo { a: int, m: marker::NoShare }
|
||||
struct Foo { a: int, m: marker::NoSync }
|
||||
|
||||
fn bar<T: Share>(_: T) {}
|
||||
fn bar<T: Sync>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = Foo { a: 5, m: marker::NoShare };
|
||||
let x = Foo { a: 5, m: marker::NoSync };
|
||||
bar(x);
|
||||
//~^ ERROR instantiating a type parameter with an incompatible type `Foo`,
|
||||
// which does not fulfill `Share`
|
||||
// which does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn is_send<T: Send>() {}
|
||||
fn is_freeze<T: Share>() {}
|
||||
fn is_freeze<T: Sync>() {}
|
||||
fn is_static<T: 'static>() {}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -15,7 +15,7 @@ trait Foo {
|
|||
fn a(_x: Box<Foo+Send>) {
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo+Share+Send>) {
|
||||
fn c(x: Box<Foo+Sync+Send>) {
|
||||
a(x);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@ fn a(_x: Box<Foo+Send>) {
|
|||
fn b(_x: &'static Foo) { // should be same as &'static Foo+'static
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo+Share>) {
|
||||
fn c(x: Box<Foo+Sync>) {
|
||||
a(x); //~ ERROR expected bounds `Send`
|
||||
}
|
||||
|
||||
fn d(x: &'static Foo+Share) {
|
||||
fn d(x: &'static Foo+Sync) {
|
||||
b(x); //~ ERROR expected bounds `'static`
|
||||
}
|
||||
|
||||
|
|
|
@ -8,36 +8,36 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Verify that UnsafeCell is *always* share regardles `T` is share.
|
||||
// Verify that UnsafeCell is *always* sync regardles `T` is sync.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::kinds::marker;
|
||||
|
||||
struct MyShare<T> {
|
||||
struct MySync<T> {
|
||||
u: UnsafeCell<T>
|
||||
}
|
||||
|
||||
struct NoShare {
|
||||
m: marker::NoShare
|
||||
struct NoSync {
|
||||
m: marker::NoSync
|
||||
}
|
||||
|
||||
fn test<T: Share>(s: T){
|
||||
fn test<T: Sync>(s: T){
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let us = UnsafeCell::new(MyShare{u: UnsafeCell::new(0i)});
|
||||
let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0i)});
|
||||
test(us);
|
||||
|
||||
let uns = UnsafeCell::new(NoShare{m: marker::NoShare});
|
||||
let uns = UnsafeCell::new(NoSync{m: marker::NoSync});
|
||||
test(uns);
|
||||
|
||||
let ms = MyShare{u: uns};
|
||||
let ms = MySync{u: uns};
|
||||
test(ms);
|
||||
|
||||
let ns = NoShare{m: marker::NoShare};
|
||||
let ns = NoSync{m: marker::NoSync};
|
||||
test(ns);
|
||||
//~^ ERROR instantiating a type parameter with an incompatible type `NoShare`, which does not fulfill `Share`
|
||||
//~^ ERROR instantiating a type parameter with an incompatible type `NoSync`, which does not fulfill `Sync`
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
trait Tr { }
|
||||
impl Tr for int { }
|
||||
|
||||
fn foo(x: Box<Tr+ Share>) -> Box<Tr+ Share> { x }
|
||||
fn foo(x: Box<Tr+ Sync>) -> Box<Tr+ Sync> { x }
|
||||
|
||||
fn main() {
|
||||
let x: Box<Tr+ Share>;
|
||||
let x: Box<Tr+ Sync>;
|
||||
|
||||
box() 1i as Box<Tr+ Share>;
|
||||
box() 1i as Box<Tr+ Sync>;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
|
|||
#[deriving(PartialEq)]
|
||||
struct X<T>(T);
|
||||
|
||||
impl <T: Share> RequiresShare for X<T> { }
|
||||
impl <T: Share+Send> RequiresRequiresShareAndSend for X<T> { }
|
||||
impl <T: Sync> RequiresShare for X<T> { }
|
||||
impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
|
||||
|
||||
fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) {
|
||||
chan.send(val);
|
||||
|
|
|
@ -19,9 +19,9 @@ use trait_superkinds_in_metadata::{RequiresCopy};
|
|||
|
||||
struct X<T>(T);
|
||||
|
||||
impl <T:Share> RequiresShare for X<T> { }
|
||||
impl <T:Sync> RequiresShare for X<T> { }
|
||||
|
||||
impl <T:Share+Send> RequiresRequiresShareAndSend for X<T> { }
|
||||
impl <T:Sync+Send> RequiresRequiresShareAndSend for X<T> { }
|
||||
|
||||
impl <T:Copy> RequiresCopy for X<T> { }
|
||||
|
||||
|
|
|
@ -28,11 +28,11 @@ struct Foo<'a> {
|
|||
a: ||: 'a,
|
||||
b: ||: 'static,
|
||||
c: <'b>||: 'a,
|
||||
d: ||: 'a + Share,
|
||||
e: <'b>|int|: 'a + Share -> &'b f32,
|
||||
d: ||: 'a + Sync,
|
||||
e: <'b>|int|: 'a + Sync -> &'b f32,
|
||||
f: proc(),
|
||||
g: proc(): 'static + Share,
|
||||
h: proc<'b>(int): Share -> &'b f32,
|
||||
g: proc(): 'static + Sync,
|
||||
h: proc<'b>(int): Sync -> &'b f32,
|
||||
}
|
||||
|
||||
fn f<'a>(a: &'a int, f: <'b>|&'b int| -> &'b int) -> &'a int {
|
||||
|
@ -54,14 +54,14 @@ fn bar<'b>() {
|
|||
foo::<|| -> ()>();
|
||||
foo::<||:>();
|
||||
foo::<||:'b>();
|
||||
foo::<||:'b + Share>();
|
||||
foo::<||:Share>();
|
||||
foo::< <'a>|int, f32, &'a int|:'b + Share -> &'a int>();
|
||||
foo::<||:'b + Sync>();
|
||||
foo::<||:Sync>();
|
||||
foo::< <'a>|int, f32, &'a int|:'b + Sync -> &'a int>();
|
||||
foo::<proc()>();
|
||||
foo::<proc() -> ()>();
|
||||
foo::<proc():'static>();
|
||||
foo::<proc():Share>();
|
||||
foo::<proc<'a>(int, f32, &'a int):'static + Share -> &'a int>();
|
||||
foo::<proc():Sync>();
|
||||
foo::<proc<'a>(int, f32, &'a int):'static + Sync -> &'a int>();
|
||||
|
||||
foo::<<'a>||>();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// are const.
|
||||
|
||||
|
||||
fn foo<T: Share>(x: T) -> T { x }
|
||||
fn foo<T: Sync>(x: T) -> T { x }
|
||||
|
||||
struct F { field: int }
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[deriving(Share,Send,Copy)]
|
||||
#[deriving(Sync,Send,Copy)]
|
||||
struct Test;
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// than the traits require.
|
||||
|
||||
trait A {
|
||||
fn b<C:Share,D>(x: C) -> C;
|
||||
fn b<C:Sync,D>(x: C) -> C;
|
||||
}
|
||||
|
||||
struct E {
|
||||
|
|
|
@ -20,7 +20,7 @@ mod foo {
|
|||
}
|
||||
|
||||
fn foo1<T>(_: &A<T> + Send) {}
|
||||
fn foo2<T>(_: Box<A<T> + Send + Share>) {}
|
||||
fn foo2<T>(_: Box<A<T> + Send + Sync>) {}
|
||||
fn foo3<T>(_: Box<B<int, uint> + 'static>) {}
|
||||
fn foo4<'a, T>(_: Box<C<'a, T> + 'static + Send>) {}
|
||||
fn foo5<'a, T>(_: Box<foo::D<'a, T> + 'static + Send>) {}
|
||||
|
|
|
@ -12,18 +12,18 @@ fn foo<T>() {}
|
|||
fn bar<T>(_: T) {}
|
||||
|
||||
fn is_send<T: Send>() {}
|
||||
fn is_freeze<T: Share>() {}
|
||||
fn is_freeze<T: Sync>() {}
|
||||
fn is_static<T: 'static>() {}
|
||||
|
||||
pub fn main() {
|
||||
foo::<proc()>();
|
||||
foo::<proc()>();
|
||||
foo::<proc():Send>();
|
||||
foo::<proc():Send + Share>();
|
||||
foo::<proc():'static + Send + Share>();
|
||||
foo::<proc():Send + Sync>();
|
||||
foo::<proc():'static + Send + Sync>();
|
||||
|
||||
is_send::<proc():Send>();
|
||||
is_freeze::<proc():Share>();
|
||||
is_freeze::<proc():Sync>();
|
||||
is_static::<proc():'static>();
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ trait Foo {
|
|||
fn b(_x: Box<Foo+Send>) {
|
||||
}
|
||||
|
||||
fn c(x: Box<Foo+Share+Send>) {
|
||||
fn c(x: Box<Foo+Sync+Send>) {
|
||||
e(x);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,10 +71,10 @@ pub fn main() {
|
|||
swim_speed: 998,
|
||||
name: "alec_guinness".to_string(),
|
||||
};
|
||||
let arc = Arc::new(vec!(box catte as Box<Pet+Share+Send>,
|
||||
box dogge1 as Box<Pet+Share+Send>,
|
||||
box fishe as Box<Pet+Share+Send>,
|
||||
box dogge2 as Box<Pet+Share+Send>));
|
||||
let arc = Arc::new(vec!(box catte as Box<Pet+Sync+Send>,
|
||||
box dogge1 as Box<Pet+Sync+Send>,
|
||||
box fishe as Box<Pet+Sync+Send>,
|
||||
box dogge2 as Box<Pet+Sync+Send>));
|
||||
let (tx1, rx1) = channel();
|
||||
let arc1 = arc.clone();
|
||||
task::spawn(proc() { check_legs(arc1); tx1.send(()); });
|
||||
|
@ -89,21 +89,21 @@ pub fn main() {
|
|||
rx3.recv();
|
||||
}
|
||||
|
||||
fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
fn check_legs(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
|
||||
let mut legs = 0;
|
||||
for pet in arc.iter() {
|
||||
legs += pet.num_legs();
|
||||
}
|
||||
assert!(legs == 12);
|
||||
}
|
||||
fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
fn check_names(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
|
||||
for pet in arc.iter() {
|
||||
pet.name(|name| {
|
||||
assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
|
||||
})
|
||||
}
|
||||
}
|
||||
fn check_pedigree(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
|
||||
fn check_pedigree(arc: Arc<Vec<Box<Pet+Sync+Send>>>) {
|
||||
for pet in arc.iter() {
|
||||
assert!(pet.of_good_pedigree());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue