-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Shared
pointer and have {Arc, Rc}
use it
#29110
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This interface feels a little off to me, but since this isn't a stable API it can be bikeshedded later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the same interface exposed by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bad interface because it removes the optimizations |
||
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) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Were this and the rwlock changes needed for this PR? I have a feeling this probably isn't too bad, but I just want to make sure that this wasn't something super subtle that came up when fixing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aha I see it was needed to make the tests pass, makes sense to me! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These were necessary to keep the run-pass/dropck_legal_cycles.rs test passing. From what I understand, it was an oversight that the attribute wasn't applied in these locations when the same changes were made to the collection types' destructors in #28861. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah they are needed; otherwise the dropck-legal-cycles test won't pass. @apasel422 mentioned this on the other ticket, but not here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @apasel422 yeah the oversight was that I shouldn't have said "boy that was easy, didn't have to add that attribute in too many places"; I should have said "hmm, why are these tests passing currently without that attribute ... ooh, missing PhantomData" |
||
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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this not affect variance? Or are you saying that it has the same effect owning
*const T
above has, therefore it doesn't have additional consequences for variance?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same note that is in
Unique
above.