diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index b8703f6e7d935..4a80d75575e6d 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -1085,7 +1085,7 @@ impl Node { vals: RawItems::from_slice(self.vals()), edges: RawItems::from_slice(self.edges()), - ptr: *self.keys as *mut u8, + ptr: Unique::new(*self.keys as *mut u8), capacity: self.capacity(), is_leaf: self.is_leaf() }, @@ -1354,11 +1354,14 @@ struct MoveTraversalImpl { edges: RawItems>, // For deallocation when we are done iterating. - ptr: *mut u8, + ptr: Unique, capacity: usize, is_leaf: bool } +unsafe impl Sync for MoveTraversalImpl {} +unsafe impl Send for MoveTraversalImpl {} + impl TraversalImpl for MoveTraversalImpl { type Item = (K, V); type Edge = Node; @@ -1401,7 +1404,7 @@ impl Drop for MoveTraversalImpl { let (alignment, size) = calculate_allocation_generic::(self.capacity, self.is_leaf); - unsafe { heap::deallocate(self.ptr, size, alignment) }; + unsafe { heap::deallocate(*self.ptr, size, alignment) }; } } @@ -1425,12 +1428,12 @@ pub enum TraversalItem { /// A traversal over a node's entries and edges pub type Traversal<'a, K, V> = AbsTraversal, slice::Iter<'a, V>>, - slice::Iter<'a, Node>>>; + slice::Iter<'a, Node>>>; /// A mutable traversal over a node's entries and edges pub type MutTraversal<'a, K, V> = AbsTraversal, slice::IterMut<'a, V>>, - slice::IterMut<'a, Node>>>; + slice::IterMut<'a, Node>>>; /// An owning traversal over a node's entries and edges pub type MoveTraversal = AbsTraversal>; diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 3d68bb13db8e9..9b5fbfc25114c 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -51,8 +51,8 @@ struct Rawlink { } impl Copy for Rawlink {} -unsafe impl Send for Rawlink {} -unsafe impl Sync for Rawlink {} +unsafe impl Send for Rawlink {} +unsafe impl Sync for Rawlink {} struct Node { next: Link, diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 6d4541b5bde16..e18fa8c3082d1 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1755,6 +1755,9 @@ pub struct Drain<'a, T:'a> { marker: PhantomData<&'a T>, } +unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {} +unsafe impl<'a, T: Send> Send for Drain<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Drain<'a, T> { type Item = T; diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index e99d44551d536..abcc0cef9f1fe 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -24,7 +24,6 @@ use core::cmp::Ordering; use core::default::Default; use core::fmt; use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; -use core::marker; use core::mem; use core::num::{Int, UnsignedInt}; use core::ops::{Index, IndexMut}; @@ -59,12 +58,6 @@ pub struct VecDeque { ptr: Unique, } -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for VecDeque {} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for VecDeque {} - #[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecDeque { fn clone(&self) -> VecDeque { @@ -545,9 +538,7 @@ impl VecDeque { IterMut { tail: self.tail, head: self.head, - cap: self.cap, - ptr: *self.ptr, - marker: marker::PhantomData, + ring: unsafe { self.buffer_as_mut_slice() }, } } @@ -1515,17 +1506,12 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> { } } -// FIXME This was implemented differently from Iter because of a problem -// with returning the mutable reference. I couldn't find a way to -// make the lifetime checker happy so, but there should be a way. /// `VecDeque` mutable iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T:'a> { - ptr: *mut T, + ring: &'a mut [T], tail: usize, head: usize, - cap: usize, - marker: marker::PhantomData<&'a mut T>, } #[stable(feature = "rust1", since = "1.0.0")] @@ -1538,16 +1524,17 @@ impl<'a, T> Iterator for IterMut<'a, T> { return None; } let tail = self.tail; - self.tail = wrap_index(self.tail + 1, self.cap); + self.tail = wrap_index(self.tail + 1, self.ring.len()); unsafe { - Some(&mut *self.ptr.offset(tail as isize)) + let elem = self.ring.get_unchecked_mut(tail); + Some(&mut *(elem as *mut _)) } } #[inline] fn size_hint(&self) -> (usize, Option) { - let len = count(self.tail, self.head, self.cap); + let len = count(self.tail, self.head, self.ring.len()); (len, Some(len)) } } @@ -1559,10 +1546,11 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { if self.tail == self.head { return None; } - self.head = wrap_index(self.head - 1, self.cap); + self.head = wrap_index(self.head - 1, self.ring.len()); unsafe { - Some(&mut *self.ptr.offset(self.head as isize)) + let elem = self.ring.get_unchecked_mut(self.head); + Some(&mut *(elem as *mut _)) } } } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index b4ccf93043729..8f767e62678e6 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -68,7 +68,7 @@ use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; use option::Option; use option::Option::{Some, None}; -use marker::Sized; +use marker::{Send, Sized, Sync}; use usize; /// An interface for dealing with "external iterators". These types of iterators @@ -1786,6 +1786,10 @@ pub struct Peekable { peeked: Option, } +// FIXME: after #22828 being fixed, the following unsafe impl should be removed +unsafe impl Sync for Peekable where I: Sync, I::Item: Sync {} +unsafe impl Send for Peekable where I: Send, I::Item: Send {} + impl Clone for Peekable where I::Item: Clone { fn clone(&self) -> Peekable { Peekable { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index ae64a57a390f8..91cad4330f204 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -51,7 +51,7 @@ use ptr; use ptr::PtrExt; use mem; use mem::size_of; -use marker::{Sized, self}; +use marker::{Send, Sized, Sync, self}; use raw::Repr; // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. use raw::Slice as RawSlice; @@ -740,6 +740,9 @@ pub struct Iter<'a, T: 'a> { _marker: marker::PhantomData<&'a T>, } +unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {} +unsafe impl<'a, T: Sync> Send for Iter<'a, T> {} + #[unstable(feature = "core")] impl<'a, T> ops::Index> for Iter<'a, T> { type Output = [T]; @@ -830,6 +833,8 @@ pub struct IterMut<'a, T: 'a> { _marker: marker::PhantomData<&'a mut T>, } +unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {} +unsafe impl<'a, T: Send> Send for IterMut<'a, T> {} #[unstable(feature = "core")] impl<'a, T> ops::Index> for IterMut<'a, T> { diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs new file mode 100644 index 0000000000000..6d29d5f2b3e91 --- /dev/null +++ b/src/test/run-pass/sync-send-iterators-in-libcollections.rs @@ -0,0 +1,98 @@ +// 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. + +#![allow(unused_mut)] +#![feature(collections)] + +extern crate collections; + +use collections::BinaryHeap; +use collections::{BitSet, BitVec}; +use collections::{BTreeMap, BTreeSet}; +use collections::EnumSet; +use collections::LinkedList; +use collections::Vec; +use collections::VecDeque; +use collections::VecMap; + +use collections::Bound::Included; +use collections::enum_set::CLike; +use std::mem; + +fn is_sync(_: T) where T: Sync {} +fn is_send(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }) +} + +fn main() { + // The iterator "generator" list should exhaust what corresponding + // implementations have where `Sync` and `Send` semantics apply. + all_sync_send!(BinaryHeap::::new(), iter, drain, into_iter); + + all_sync_send!(BitVec::new(), iter); + + all_sync_send!(BitSet::new(), iter); + is_sync_send!(BitSet::new(), union(&BitSet::new())); + is_sync_send!(BitSet::new(), intersection(&BitSet::new())); + is_sync_send!(BitSet::new(), difference(&BitSet::new())); + is_sync_send!(BitSet::new(), symmetric_difference(&BitSet::new())); + + all_sync_send!(BTreeMap::::new(), iter, iter_mut, into_iter, keys, values); + is_sync_send!(BTreeMap::::new(), range(Included(&0), Included(&9))); + is_sync_send!(BTreeMap::::new(), range_mut(Included(&0), Included(&9))); + + all_sync_send!(BTreeSet::::new(), iter, into_iter); + is_sync_send!(BTreeSet::::new(), range(Included(&0), Included(&9))); + is_sync_send!(BTreeSet::::new(), difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), symmetric_difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), intersection(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), union(&BTreeSet::::new())); + + all_sync_send!(LinkedList::::new(), iter, iter_mut, into_iter); + + #[derive(Copy)] + #[repr(usize)] + #[allow(dead_code)] + enum Foo { A, B, C } + impl CLike for Foo { + fn to_usize(&self) -> usize { + *self as usize + } + + fn from_usize(v: usize) -> Foo { + unsafe { mem::transmute(v) } + } + } + all_sync_send!(EnumSet::::new(), iter); + + all_sync_send!(VecDeque::::new(), iter, iter_mut, drain, into_iter); + + all_sync_send!(VecMap::::new(), iter, iter_mut, drain, into_iter, keys, values); + + all_sync_send!(Vec::::new(), into_iter, drain); +}