Skip to content

Commit 4a4c89c

Browse files
committed
auto merge of #20119 : FlaPer87/rust/oibit-send-and-friends, r=nikomatsakis
More work on opt-in built in traits. `Send` and `Sync` are not opt-in, `OwnedPtr` renamed to `UniquePtr` and the `Send` and `Sync` traits are now unsafe. NOTE: This likely needs to be rebased on top of the yet-to-land snapshot. r? @nikomatsakis cc #13231
2 parents 9be54be + 1a73ccc commit 4a4c89c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+975
-533
lines changed

src/liballoc/arc.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ pub struct Arc<T> {
117117
_ptr: *mut ArcInner<T>,
118118
}
119119

120+
unsafe impl<T: Sync + Send> Send for Arc<T> { }
121+
unsafe impl<T: Sync + Send> Sync for Arc<T> { }
122+
123+
120124
/// A weak pointer to an `Arc`.
121125
///
122126
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be used to break cycles
@@ -129,13 +133,19 @@ pub struct Weak<T> {
129133
_ptr: *mut ArcInner<T>,
130134
}
131135

136+
unsafe impl<T: Sync + Send> Send for Weak<T> { }
137+
unsafe impl<T: Sync + Send> Sync for Weak<T> { }
138+
132139
struct ArcInner<T> {
133140
strong: atomic::AtomicUint,
134141
weak: atomic::AtomicUint,
135142
data: T,
136143
}
137144

138-
impl<T: Sync + Send> Arc<T> {
145+
unsafe impl<T: Sync + Send> Send for ArcInner<T> {}
146+
unsafe impl<T: Sync + Send> Sync for ArcInner<T> {}
147+
148+
impl<T> Arc<T> {
139149
/// Constructs a new `Arc<T>`.
140150
///
141151
/// # Examples
@@ -587,6 +597,7 @@ mod tests {
587597
use std::str::Str;
588598
use std::sync::atomic;
589599
use std::task;
600+
use std::kinds::Send;
590601
use std::vec::Vec;
591602
use super::{Arc, Weak, weak_count, strong_count};
592603
use std::sync::Mutex;

src/liballoc/boxed.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use core::hash::{mod, Hash};
1919
use core::kinds::Sized;
2020
use core::mem;
2121
use core::option::Option;
22+
use core::ptr::Unique;
2223
use core::raw::TraitObject;
2324
use core::result::Result;
2425
use core::result::Result::{Ok, Err};
@@ -44,7 +45,7 @@ pub static HEAP: () = ();
4445
/// A type that represents a uniquely-owned value.
4546
#[lang = "owned_box"]
4647
#[unstable = "custom allocators will add an additional type parameter (with default)"]
47-
pub struct Box<T>(*mut T);
48+
pub struct Box<T>(Unique<T>);
4849

4950
#[stable]
5051
impl<T: Default> Default for Box<T> {

src/libcollections/dlist.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct Rawlink<T> {
4343
}
4444

4545
impl<T> Copy for Rawlink<T> {}
46+
unsafe impl<T:'static+Send> Send for Rawlink<T> {}
47+
unsafe impl<T:Send+Sync> Sync for Rawlink<T> {}
4648

4749
struct Node<T> {
4850
next: Link<T>,

src/libcollections/vec.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use core::kinds::marker::{ContravariantLifetime, InvariantType};
5858
use core::mem;
5959
use core::num::{Int, UnsignedInt};
6060
use core::ops;
61-
use core::ptr;
61+
use core::ptr::{mod, Unique};
6262
use core::raw::Slice as RawSlice;
6363
use core::uint;
6464

@@ -133,7 +133,7 @@ use slice::CloneSliceExt;
133133
#[unsafe_no_drop_flag]
134134
#[stable]
135135
pub struct Vec<T> {
136-
ptr: *mut T,
136+
ptr: Unique<T>,
137137
len: uint,
138138
cap: uint,
139139
}
@@ -176,7 +176,7 @@ impl<T> Vec<T> {
176176
// non-null value which is fine since we never call deallocate on the ptr
177177
// if cap is 0. The reason for this is because the pointer of a slice
178178
// being NULL would break the null pointer optimization for enums.
179-
Vec { ptr: EMPTY as *mut T, len: 0, cap: 0 }
179+
Vec { ptr: Unique(EMPTY as *mut T), len: 0, cap: 0 }
180180
}
181181

182182
/// Constructs a new, empty `Vec<T>` with the specified capacity.
@@ -209,15 +209,15 @@ impl<T> Vec<T> {
209209
#[stable]
210210
pub fn with_capacity(capacity: uint) -> Vec<T> {
211211
if mem::size_of::<T>() == 0 {
212-
Vec { ptr: EMPTY as *mut T, len: 0, cap: uint::MAX }
212+
Vec { ptr: Unique(EMPTY as *mut T), len: 0, cap: uint::MAX }
213213
} else if capacity == 0 {
214214
Vec::new()
215215
} else {
216216
let size = capacity.checked_mul(mem::size_of::<T>())
217217
.expect("capacity overflow");
218218
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
219219
if ptr.is_null() { ::alloc::oom() }
220-
Vec { ptr: ptr as *mut T, len: 0, cap: capacity }
220+
Vec { ptr: Unique(ptr as *mut T), len: 0, cap: capacity }
221221
}
222222
}
223223

@@ -284,7 +284,7 @@ impl<T> Vec<T> {
284284
#[unstable = "needs finalization"]
285285
pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
286286
capacity: uint) -> Vec<T> {
287-
Vec { ptr: ptr, len: length, cap: capacity }
287+
Vec { ptr: Unique(ptr), len: length, cap: capacity }
288288
}
289289

290290
/// Creates a vector by copying the elements from a raw pointer.
@@ -795,19 +795,19 @@ impl<T> Vec<T> {
795795
if self.len == 0 {
796796
if self.cap != 0 {
797797
unsafe {
798-
dealloc(self.ptr, self.cap)
798+
dealloc(self.ptr.0, self.cap)
799799
}
800800
self.cap = 0;
801801
}
802802
} else {
803803
unsafe {
804804
// Overflow check is unnecessary as the vector is already at
805805
// least this large.
806-
self.ptr = reallocate(self.ptr as *mut u8,
807-
self.cap * mem::size_of::<T>(),
808-
self.len * mem::size_of::<T>(),
809-
mem::min_align_of::<T>()) as *mut T;
810-
if self.ptr.is_null() { ::alloc::oom() }
806+
self.ptr = Unique(reallocate(self.ptr.0 as *mut u8,
807+
self.cap * mem::size_of::<T>(),
808+
self.len * mem::size_of::<T>(),
809+
mem::min_align_of::<T>()) as *mut T);
810+
if self.ptr.0.is_null() { ::alloc::oom() }
811811
}
812812
self.cap = self.len;
813813
}
@@ -867,7 +867,7 @@ impl<T> Vec<T> {
867867
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
868868
unsafe {
869869
mem::transmute(RawSlice {
870-
data: self.ptr as *const T,
870+
data: self.ptr.0 as *const T,
871871
len: self.len,
872872
})
873873
}
@@ -890,9 +890,9 @@ impl<T> Vec<T> {
890890
#[unstable = "matches collection reform specification, waiting for dust to settle"]
891891
pub fn into_iter(self) -> IntoIter<T> {
892892
unsafe {
893-
let ptr = self.ptr;
893+
let ptr = self.ptr.0;
894894
let cap = self.cap;
895-
let begin = self.ptr as *const T;
895+
let begin = self.ptr.0 as *const T;
896896
let end = if mem::size_of::<T>() == 0 {
897897
(ptr as uint + self.len()) as *const T
898898
} else {
@@ -1110,14 +1110,14 @@ impl<T> Vec<T> {
11101110
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
11111111
if old_size > size { panic!("capacity overflow") }
11121112
unsafe {
1113-
self.ptr = alloc_or_realloc(self.ptr, old_size, size);
1114-
if self.ptr.is_null() { ::alloc::oom() }
1113+
self.ptr = Unique(alloc_or_realloc(self.ptr.0, old_size, size));
1114+
if self.ptr.0.is_null() { ::alloc::oom() }
11151115
}
11161116
self.cap = max(self.cap, 2) * 2;
11171117
}
11181118

11191119
unsafe {
1120-
let end = (self.ptr as *const T).offset(self.len as int) as *mut T;
1120+
let end = self.ptr.0.offset(self.len as int);
11211121
ptr::write(&mut *end, value);
11221122
self.len += 1;
11231123
}
@@ -1162,11 +1162,11 @@ impl<T> Vec<T> {
11621162
#[unstable = "matches collection reform specification, waiting for dust to settle"]
11631163
pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
11641164
unsafe {
1165-
let begin = self.ptr as *const T;
1165+
let begin = self.ptr.0 as *const T;
11661166
let end = if mem::size_of::<T>() == 0 {
1167-
(self.ptr as uint + self.len()) as *const T
1167+
(self.ptr.0 as uint + self.len()) as *const T
11681168
} else {
1169-
self.ptr.offset(self.len() as int) as *const T
1169+
self.ptr.0.offset(self.len() as int) as *const T
11701170
};
11711171
self.set_len(0);
11721172
Drain {
@@ -1231,8 +1231,10 @@ impl<T> Vec<T> {
12311231
let size = capacity.checked_mul(mem::size_of::<T>())
12321232
.expect("capacity overflow");
12331233
unsafe {
1234-
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);
1235-
if self.ptr.is_null() { ::alloc::oom() }
1234+
self.ptr = Unique(alloc_or_realloc(self.ptr.0,
1235+
self.cap * mem::size_of::<T>(),
1236+
size));
1237+
if self.ptr.0.is_null() { ::alloc::oom() }
12361238
}
12371239
self.cap = capacity;
12381240
}
@@ -1355,7 +1357,7 @@ impl<T> AsSlice<T> for Vec<T> {
13551357
fn as_slice<'a>(&'a self) -> &'a [T] {
13561358
unsafe {
13571359
mem::transmute(RawSlice {
1358-
data: self.ptr as *const T,
1360+
data: self.ptr.0 as *const T,
13591361
len: self.len
13601362
})
13611363
}
@@ -1380,7 +1382,7 @@ impl<T> Drop for Vec<T> {
13801382
for x in self.iter() {
13811383
ptr::read(x);
13821384
}
1383-
dealloc(self.ptr, self.cap)
1385+
dealloc(self.ptr.0, self.cap)
13841386
}
13851387
}
13861388
}
@@ -1418,7 +1420,7 @@ impl<T> IntoIter<T> {
14181420
for _x in self { }
14191421
let IntoIter { allocation, cap, ptr: _ptr, end: _end } = self;
14201422
mem::forget(self);
1421-
Vec { ptr: allocation, cap: cap, len: 0 }
1423+
Vec { ptr: Unique(allocation), cap: cap, len: 0 }
14221424
}
14231425
}
14241426

src/libcore/atomic.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
pub use self::Ordering::*;
1616

17+
use kinds::Sync;
18+
1719
use intrinsics;
1820
use cell::UnsafeCell;
1921

@@ -23,24 +25,32 @@ pub struct AtomicBool {
2325
v: UnsafeCell<uint>,
2426
}
2527

28+
unsafe impl Sync for AtomicBool {}
29+
2630
/// A signed integer type which can be safely shared between threads.
2731
#[stable]
2832
pub struct AtomicInt {
2933
v: UnsafeCell<int>,
3034
}
3135

36+
unsafe impl Sync for AtomicInt {}
37+
3238
/// An unsigned integer type which can be safely shared between threads.
3339
#[stable]
3440
pub struct AtomicUint {
3541
v: UnsafeCell<uint>,
3642
}
3743

44+
unsafe impl Sync for AtomicUint {}
45+
3846
/// A raw pointer type which can be safely shared between threads.
3947
#[stable]
4048
pub struct AtomicPtr<T> {
4149
p: UnsafeCell<uint>,
4250
}
4351

52+
unsafe impl<T> Sync for AtomicPtr<T> {}
53+
4454
/// Atomic memory orderings
4555
///
4656
/// Memory orderings limit the ways that both the compiler and CPU may reorder

src/libcore/kinds.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
2020
/// Types able to be transferred across task boundaries.
2121
#[lang="send"]
22-
pub trait Send for Sized? : 'static {
22+
pub unsafe trait Send for Sized? : 'static {
2323
// empty.
2424
}
2525

@@ -81,7 +81,7 @@ pub trait Copy for Sized? {
8181
/// reference; not doing this is undefined behaviour (for example,
8282
/// `transmute`-ing from `&T` to `&mut T` is illegal).
8383
#[lang="sync"]
84-
pub trait Sync for Sized? {
84+
pub unsafe trait Sync for Sized? {
8585
// Empty
8686
}
8787

src/libcore/ptr.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ use clone::Clone;
9292
use intrinsics;
9393
use option::Option;
9494
use option::Option::{Some, None};
95+
use kinds::{Send, Sync};
9596

9697
use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
9798
use cmp::Ordering;
@@ -501,3 +502,35 @@ impl<T> PartialOrd for *mut T {
501502
#[inline]
502503
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
503504
}
505+
506+
/// A wrapper around a raw `*mut T` that indicates that the possessor
507+
/// of this wrapper owns the referent. This in turn implies that the
508+
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a
509+
/// raw `*mut T` (which conveys no particular ownership semantics).
510+
/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
511+
/// internally use raw pointers to manage the memory that they own.
512+
pub struct Unique<T>(pub *mut T);
513+
514+
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
515+
/// reference is unaliased. Note that this aliasing invariant is
516+
/// unenforced by the type system; the abstraction using the
517+
/// `Unique` must enforce it.
518+
unsafe impl<T:Send> Send for Unique<T> { }
519+
520+
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
521+
/// reference is unaliased. Note that this aliasing invariant is
522+
/// unenforced by the type system; the abstraction using the
523+
/// `Unique` must enforce it.
524+
unsafe impl<T:Sync> Sync for Unique<T> { }
525+
526+
impl<T> Unique<T> {
527+
/// Returns a null Unique.
528+
pub fn null() -> Unique<T> {
529+
Unique(RawPtr::null())
530+
}
531+
532+
/// Return an (unsafe) pointer into the memory owned by `self`.
533+
pub unsafe fn offset(self, offset: int) -> *mut T {
534+
(self.0 as *const T).offset(offset) as *mut T
535+
}
536+
}

src/libflate/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727

2828
extern crate libc;
2929

30-
use std::c_vec::CVec;
3130
use libc::{c_void, size_t, c_int};
31+
use std::c_vec::CVec;
32+
use std::ptr::Unique;
3233

3334
#[link(name = "miniz", kind = "static")]
3435
extern {
@@ -59,7 +60,8 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
5960
&mut outsz,
6061
flags);
6162
if !res.is_null() {
62-
Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, move|:| libc::free(res)))
63+
let res = Unique(res);
64+
Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
6365
} else {
6466
None
6567
}
@@ -84,7 +86,8 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
8486
&mut outsz,
8587
flags);
8688
if !res.is_null() {
87-
Some(CVec::new_with_dtor(res as *mut u8, outsz as uint, move|:| libc::free(res)))
89+
let res = Unique(res);
90+
Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
8891
} else {
8992
None
9093
}

src/librustc/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,6 @@ register_diagnostics! {
6767
E0173,
6868
E0174,
6969
E0177,
70-
E0178
70+
E0178,
71+
E0179
7172
}

0 commit comments

Comments
 (0)