Auto merge of #29110 - apasel422:shared, r=alexcrichton

Fixes #29037.
Fixes #29106.

r? @pnkfelix 
CC @Gankro
This commit is contained in:
bors 2015-10-17 09:51:30 +00:00
commit e1944b6b0b
8 changed files with 148 additions and 12 deletions

View file

@ -79,9 +79,8 @@ use core::cmp::Ordering;
use core::mem::{align_of_val, size_of_val};
use core::intrinsics::{drop_in_place, abort};
use core::mem;
use core::nonzero::NonZero;
use core::ops::{Deref, CoerceUnsized};
use core::ptr;
use core::ptr::{self, Shared};
use core::marker::Unsize;
use core::hash::{Hash, Hasher};
use core::{usize, isize};
@ -124,12 +123,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
pub struct Arc<T: ?Sized> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_ptr: NonZero<*mut ArcInner<T>>,
_ptr: Shared<ArcInner<T>>,
}
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> { }
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> { }
#[cfg(not(stage0))] // remove cfg after new snapshot
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
/// A weak pointer to an `Arc`.
@ -141,12 +141,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
pub struct Weak<T: ?Sized> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_ptr: NonZero<*mut ArcInner<T>>,
_ptr: Shared<ArcInner<T>>,
}
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
#[cfg(not(stage0))] // remove cfg after new snapshot
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -190,7 +191,7 @@ impl<T> Arc<T> {
weak: atomic::AtomicUsize::new(1),
data: data,
};
Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
Arc { _ptr: unsafe { Shared::new(Box::into_raw(x)) } }
}
/// Unwraps the contained value if the `Arc<T>` has only one strong reference.

View file

@ -90,6 +90,7 @@
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(raw)]
#![feature(shared)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]

View file

@ -163,9 +163,8 @@ use core::hash::{Hasher, Hash};
use core::intrinsics::{assume, drop_in_place, abort};
use core::marker::{self, Unsize};
use core::mem::{self, align_of_val, size_of_val, forget};
use core::nonzero::NonZero;
use core::ops::{CoerceUnsized, Deref};
use core::ptr;
use core::ptr::{self, Shared};
use heap::deallocate;
@ -184,12 +183,13 @@ struct RcBox<T: ?Sized> {
pub struct Rc<T: ?Sized> {
// FIXME #12808: strange names to try to avoid interfering with field
// accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
_ptr: Shared<RcBox<T>>,
}
impl<T: ?Sized> !marker::Send for Rc<T> {}
impl<T: ?Sized> !marker::Sync for Rc<T> {}
#[cfg(not(stage0))] // remove cfg after new snapshot
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
impl<T> Rc<T> {
@ -210,7 +210,7 @@ impl<T> Rc<T> {
// 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(Box::into_raw(box RcBox {
_ptr: Shared::new(Box::into_raw(box RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
value: value,
@ -712,12 +712,13 @@ impl<T> fmt::Pointer for Rc<T> {
pub struct Weak<T: ?Sized> {
// FIXME #12808: strange names to try to avoid interfering with
// field accesses of the contained type via Deref
_ptr: NonZero<*mut RcBox<T>>,
_ptr: Shared<RcBox<T>>,
}
impl<T: ?Sized> !marker::Send for Weak<T> {}
impl<T: ?Sized> !marker::Sync for Weak<T> {}
#[cfg(not(stage0))] // remove cfg after new snapshot
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
impl<T: ?Sized> Weak<T> {

View file

@ -18,11 +18,11 @@
use clone::Clone;
use intrinsics;
use ops::Deref;
use ops::{CoerceUnsized, Deref};
use fmt;
use hash;
use option::Option::{self, Some, None};
use marker::{PhantomData, Send, Sized, Sync};
use marker::{Copy, PhantomData, Send, Sized, Sync, Unsize};
use mem;
use nonzero::NonZero;
@ -532,3 +532,68 @@ impl<T> fmt::Pointer for Unique<T> {
fmt::Pointer::fmt(&*self.pointer, f)
}
}
/// A wrapper around a raw `*mut T` that indicates that the possessor
/// of this wrapper has shared ownership of the referent. Useful for
/// building abstractions like `Rc<T>` or `Arc<T>`, which internally
/// use raw pointers to manage the memory that they own.
#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
issue = "0")]
pub struct Shared<T: ?Sized> {
pointer: NonZero<*const T>,
// NOTE: this marker has no consequences for variance, but is necessary
// for dropck to understand that we logically own a `T`.
//
// For details, see:
// https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
_marker: PhantomData<T>,
}
/// `Shared` pointers are not `Send` because the data they reference may be aliased.
// NB: This impl is unnecessary, but should provide better error messages.
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> !Send for Shared<T> { }
/// `Shared` pointers are not `Sync` because the data they reference may be aliased.
// NB: This impl is unnecessary, but should provide better error messages.
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> !Sync for Shared<T> { }
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> Shared<T> {
/// Creates a new `Shared`.
pub unsafe fn new(ptr: *mut T) -> Self {
Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
}
}
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> Clone for Shared<T> {
fn clone(&self) -> Self {
*self
}
}
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> Copy for Shared<T> { }
#[cfg(not(stage0))] // remove cfg after new snapshot
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
#[unstable(feature = "shared", issue = "0")]
impl<T: ?Sized> Deref for Shared<T> {
type Target = *mut T;
#[inline]
fn deref(&self) -> &*mut T {
unsafe { mem::transmute(&*self.pointer) }
}
}
#[unstable(feature = "shared", issue = "0")]
impl<T> fmt::Pointer for Shared<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&*self.pointer, f)
}
}

View file

@ -293,6 +293,7 @@ impl<T: ?Sized> Mutex<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for Mutex<T> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
// This is actually safe b/c we know that there is no further usage of
// this mutex (it's up to the user to arrange for a mutex to get

View file

@ -314,6 +314,7 @@ impl<T: ?Sized> RwLock<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Drop for RwLock<T> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
// IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`.
unsafe { self.inner.lock.destroy() }

View file

@ -0,0 +1,34 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::rc::Rc;
use std::sync::Arc;
struct Foo<'a>(&'a String);
impl<'a> Drop for Foo<'a> {
fn drop(&mut self) {
println!("{:?}", self.0);
}
}
fn main() {
{
let (y, x);
x = "alive".to_string();
y = Arc::new(Foo(&x)); //~ ERROR `x` does not live long enough
}
{
let (y, x);
x = "alive".to_string();
y = Rc::new(Foo(&x)); //~ ERROR `x` does not live long enough
}
}

View file

@ -0,0 +1,32 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This test ensures that each pointer type `P<X>` is covariant in `X`.
use std::rc::Rc;
use std::sync::Arc;
fn a<'r>(x: Box<&'static str>) -> Box<&'r str> {
x
}
fn b<'r, 'w>(x: &'w &'static str) -> &'w &'r str {
x
}
fn c<'r>(x: Arc<&'static str>) -> Arc<&'r str> {
x
}
fn d<'r>(x: Rc<&'static str>) -> Rc<&'r str> {
x
}
fn main() {}