stop treating Rc
cycles as unsafe
This commit is contained in:
parent
63ba93f91d
commit
b36a948831
5 changed files with 13 additions and 70 deletions
|
@ -406,14 +406,14 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S:Encoder,T:Encodable<S> + Freeze> Encodable<S> for Rc<T> {
|
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn encode(&self, s: &mut S) {
|
fn encode(&self, s: &mut S) {
|
||||||
self.borrow().encode(s)
|
self.borrow().encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D:Decoder,T:Decodable<D> + Freeze> Decodable<D> for Rc<T> {
|
impl<D:Decoder,T:Decodable<D> + NonManaged> Decodable<D> for Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn decode(d: &mut D) -> Rc<T> {
|
fn decode(d: &mut D) -> Rc<T> {
|
||||||
Rc::new(Decodable::decode(d))
|
Rc::new(Decodable::decode(d))
|
||||||
|
|
|
@ -19,9 +19,8 @@ overhead of atomic reference counting.
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
use unstable::intrinsics::transmute;
|
use unstable::intrinsics::transmute;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use kinds::{Freeze, Send};
|
use kinds::NonManaged;
|
||||||
use clone::{Clone, DeepClone};
|
use clone::{Clone, DeepClone};
|
||||||
use cell::RefCell;
|
|
||||||
use cmp::{Eq, TotalEq, Ord, TotalOrd, Ordering};
|
use cmp::{Eq, TotalEq, Ord, TotalOrd, Ordering};
|
||||||
|
|
||||||
struct RcBox<T> {
|
struct RcBox<T> {
|
||||||
|
@ -36,46 +35,17 @@ pub struct Rc<T> {
|
||||||
priv ptr: *mut RcBox<T>
|
priv ptr: *mut RcBox<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Freeze> Rc<T> {
|
impl<T: NonManaged> Rc<T> {
|
||||||
/// Construct a new reference-counted box from a `Freeze` value
|
/// Construct a new reference-counted box
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(value: T) -> Rc<T> {
|
pub fn new(value: T) -> Rc<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
Rc::new_unchecked(value)
|
Rc { ptr: transmute(~RcBox { value: value, count: 1 }) }
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Send> Rc<T> {
|
|
||||||
/// Construct a new reference-counted box from a `Send` value
|
|
||||||
#[inline]
|
|
||||||
pub fn from_send(value: T) -> Rc<T> {
|
|
||||||
unsafe {
|
|
||||||
Rc::new_unchecked(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Freeze> Rc<RefCell<T>> {
|
|
||||||
/// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value
|
|
||||||
#[inline]
|
|
||||||
pub fn from_mut(value: RefCell<T>) -> Rc<RefCell<T>> {
|
|
||||||
unsafe {
|
|
||||||
Rc::new_unchecked(value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Rc<T> {
|
impl<T> Rc<T> {
|
||||||
/// Unsafety construct a new reference-counted box from any value.
|
|
||||||
///
|
|
||||||
/// It is possible to create cycles, which will leak, and may interact
|
|
||||||
/// poorly with managed pointers.
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn new_unchecked(value: T) -> Rc<T> {
|
|
||||||
Rc{ptr: transmute(~RcBox{value: value, count: 1})}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Borrow the value contained in the reference-counted box
|
/// Borrow the value contained in the reference-counted box
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn borrow<'r>(&'r self) -> &'r T {
|
pub fn borrow<'r>(&'r self) -> &'r T {
|
||||||
|
@ -147,10 +117,10 @@ impl<T> Clone for Rc<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DeepClone> DeepClone for Rc<T> {
|
impl<T: NonManaged + DeepClone> DeepClone for Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deep_clone(&self) -> Rc<T> {
|
fn deep_clone(&self) -> Rc<T> {
|
||||||
unsafe { Rc::new_unchecked(self.borrow().deep_clone()) }
|
Rc::new(self.borrow().deep_clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +146,7 @@ mod test_rc {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
let x = Rc::from_send(RefCell::new(5));
|
let x = Rc::new(RefCell::new(5));
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
x.borrow().with_mut(|inner| {
|
x.borrow().with_mut(|inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
|
@ -186,7 +156,7 @@ mod test_rc {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deep_clone() {
|
fn test_deep_clone() {
|
||||||
let x = Rc::from_send(RefCell::new(5));
|
let x = Rc::new(RefCell::new(5));
|
||||||
let y = x.deep_clone();
|
let y = x.deep_clone();
|
||||||
x.borrow().with_mut(|inner| {
|
x.borrow().with_mut(|inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
|
@ -210,13 +180,7 @@ mod test_rc {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_destructor() {
|
fn test_destructor() {
|
||||||
let x = Rc::from_send(~5);
|
let x = Rc::new(~5);
|
||||||
assert_eq!(**x.borrow(), 5);
|
assert_eq!(**x.borrow(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_from_mut() {
|
|
||||||
let a = 10;
|
|
||||||
let _x = Rc::from_mut(RefCell::new(&a));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct A
|
||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send`
|
let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send`
|
||||||
let v = Rc::from_send(RefCell::new(a));
|
let v = Rc::new(RefCell::new(a));
|
||||||
let w = v.clone();
|
let w = v.clone();
|
||||||
let b = v.borrow();
|
let b = v.borrow();
|
||||||
let mut b = b.borrow_mut();
|
let mut b = b.borrow_mut();
|
||||||
|
|
|
@ -14,6 +14,6 @@ use std::cell::RefCell;
|
||||||
fn bar<T: Freeze>(_: T) {}
|
fn bar<T: Freeze>(_: T) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Rc::from_send(RefCell::new(5));
|
let x = Rc::new(RefCell::new(5));
|
||||||
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
|
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
// Copyright 2013 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::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
fn o<T: Send>(_: &T) {}
|
|
||||||
fn c<T: Freeze>(_: &T) {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let x = Rc::from_send(RefCell::new(0));
|
|
||||||
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Send`
|
|
||||||
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue