diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index b33a18ed95d..019cd53be55 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Runtime move semantics +//! Types dealing with dynamic mutability #[missing_doc]; -use cast::transmute_mut; use prelude::*; +use cast; +use util::NonCopyable; + /* A dynamic, mutable location. @@ -36,7 +38,7 @@ impl Cell { /// Yields the value, failing if the cell is empty. pub fn take(&self) -> T { - let this = unsafe { transmute_mut(self) }; + let this = unsafe { cast::transmute_mut(self) }; if this.is_empty() { fail!("attempt to take an empty cell"); } @@ -46,7 +48,7 @@ impl Cell { /// Yields the value if the cell is full, or `None` if it is empty. pub fn take_opt(&self) -> Option { - let this = unsafe { transmute_mut(self) }; + let this = unsafe { cast::transmute_mut(self) }; this.value.take() } @@ -72,3 +74,295 @@ fn test_take_empty() { value_cell.take(); value_cell.take(); } + + +/// A mutable memory location with dynamically checked borrow rules +#[no_freeze] +pub struct RefCell { + priv value: T, + priv borrow: BorrowFlag, + priv nc: NonCopyable +} + +// Values [1, MAX-1] represent the number of `Ref` active +// (will not outgrow its range since `uint` is the size of the address space) +type BorrowFlag = uint; +static UNUSED: BorrowFlag = 0; +static WRITING: BorrowFlag = -1; + +impl RefCell { + /// Create a new `RefCell` containing `value` + pub fn new(value: T) -> RefCell { + RefCell { + value: value, + borrow: UNUSED, + nc: NonCopyable + } + } + + /// Consumes the `RefCell`, returning the wrapped value. + pub fn unwrap(self) -> T { + assert!(self.borrow == UNUSED); + self.value + } + + unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell { + cast::transmute_mut(self) + } + + /// Attempts to immutably borrow the wrapped value. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// Returns `None` if the value is currently mutably borrowed. + pub fn try_borrow<'a>(&'a self) -> Option> { + match self.borrow { + WRITING => None, + _ => { + unsafe { self.as_mut().borrow += 1; } + Some(Ref { parent: self }) + } + } + } + + /// Immutably borrows the wrapped value. + /// + /// The borrow lasts until the returned `Ref` exits scope. Multiple + /// immutable borrows can be taken out at the same time. + /// + /// # Failure + /// + /// Fails if the value is currently mutably borrowed. + pub fn borrow<'a>(&'a self) -> Ref<'a, T> { + match self.try_borrow() { + Some(ptr) => ptr, + None => fail!("RefCell already mutably borrowed") + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts untile the returned `RefMut` exits scope. The value + /// cannot be borrowed while this borrow is active. + /// + /// Returns `None` if the value is currently borrowed. + pub fn try_borrow_mut<'a>(&'a self) -> Option> { + match self.borrow { + UNUSED => unsafe { + let mut_self = self.as_mut(); + mut_self.borrow = WRITING; + Some(RefMut { parent: mut_self }) + }, + _ => None + } + } + + /// Mutably borrows the wrapped value. + /// + /// The borrow lasts untile the returned `RefMut` exits scope. The value + /// cannot be borrowed while this borrow is active. + /// + /// # Failure + /// + /// Fails if the value is currently borrowed. + pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { + match self.try_borrow_mut() { + Some(ptr) => ptr, + None => fail!("RefCell already borrowed") + } + } + + /// Immutably borrows the wrapped value and applies `blk` to it. + /// + /// # Failure + /// + /// Fails if the value is currently mutably borrowed. + #[inline] + pub fn with(&self, blk: |&T| -> U) -> U { + let ptr = self.borrow(); + blk(ptr.get()) + } + + /// Mutably borrows the wrapped value and applies `blk` to it. + /// + /// # Failure + /// + /// Fails if the value is currently borrowed. + #[inline] + pub fn with_mut(&self, blk: |&mut T| -> U) -> U { + let mut ptr = self.borrow_mut(); + blk(ptr.get()) + } +} + +impl Clone for RefCell { + fn clone(&self) -> RefCell { + let x = self.borrow(); + RefCell::new(x.get().clone()) + } +} + +impl DeepClone for RefCell { + fn deep_clone(&self) -> RefCell { + let x = self.borrow(); + RefCell::new(x.get().deep_clone()) + } +} + +impl Eq for RefCell { + fn eq(&self, other: &RefCell) -> bool { + let a = self.borrow(); + let b = other.borrow(); + a.get() == b.get() + } +} + +/// Wraps a borrowed reference to a value in a `RefCell` box. +pub struct Ref<'box, T> { + priv parent: &'box RefCell +} + +#[unsafe_destructor] +impl<'box, T> Drop for Ref<'box, T> { + fn drop(&mut self) { + assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED); + unsafe { self.parent.as_mut().borrow -= 1; } + } +} + +impl<'box, T> Ref<'box, T> { + /// Retrieve an immutable reference to the stored value. + #[inline] + pub fn get<'a>(&'a self) -> &'a T { + &self.parent.value + } +} + +/// Wraps a mutable borrowed reference to a value in a `RefCell` box. +pub struct RefMut<'box, T> { + priv parent: &'box mut RefCell +} + +#[unsafe_destructor] +impl<'box, T> Drop for RefMut<'box, T> { + fn drop(&mut self) { + assert!(self.parent.borrow == WRITING); + self.parent.borrow = UNUSED; + } +} + +impl<'box, T> RefMut<'box, T> { + /// Retrieve a mutable reference to the stored value. + #[inline] + pub fn get<'a>(&'a mut self) -> &'a mut T { + &mut self.parent.value + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn double_imm_borrow() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + x.borrow(); + } + + #[test] + fn no_mut_then_imm_borrow() { + let x = RefCell::new(0); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow().is_none()); + } + + #[test] + fn no_imm_then_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + fn no_double_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow_mut(); + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + fn imm_release_borrow_mut() { + let x = RefCell::new(0); + { + let _b1 = x.borrow(); + } + x.borrow_mut(); + } + + #[test] + fn mut_release_borrow_mut() { + let x = RefCell::new(0); + { + let _b1 = x.borrow_mut(); + } + x.borrow(); + } + + #[test] + fn double_borrow_single_release_no_borrow_mut() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + { + let _b2 = x.borrow(); + } + assert!(x.try_borrow_mut().is_none()); + } + + #[test] + fn with_ok() { + let x = RefCell::new(0); + assert_eq!(1, x.with(|x| *x+1)); + } + + #[test] + #[should_fail] + fn mut_borrow_with() { + let x = RefCell::new(0); + let _b1 = x.borrow_mut(); + x.with(|x| *x+1); + } + + #[test] + fn borrow_with() { + let x = RefCell::new(0); + let _b1 = x.borrow(); + assert_eq!(1, x.with(|x| *x+1)); + } + + #[test] + fn with_mut_ok() { + let x = RefCell::new(0); + x.with_mut(|x| *x += 1); + let b = x.borrow(); + assert_eq!(1, *b.get()); + } + + #[test] + #[should_fail] + fn borrow_with_mut() { + let x = RefCell::new(0); + let _b = x.borrow(); + x.with_mut(|x| *x += 1); + } + + #[test] + #[should_fail] + fn discard_doesnt_unborrow() { + let x = RefCell::new(0); + let _b = x.borrow(); + let _ = _b; + let _b = x.borrow_mut(); + } +} diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs index 5e2ba808d31..5fe11d310d4 100644 --- a/src/libstd/gc.rs +++ b/src/libstd/gc.rs @@ -55,26 +55,26 @@ impl DeepClone for Gc { #[cfg(test)] mod tests { use super::*; - use cell::Cell; + use cell::RefCell; #[test] fn test_clone() { - let x = Gc::new(Cell::new(5)); + let x = Gc::new(RefCell::new(5)); let y = x.clone(); - do x.borrow().with_mut_ref |inner| { + do x.borrow().with_mut |inner| { *inner = 20; } - assert_eq!(y.borrow().take(), 20); + assert_eq!(y.borrow().with(|x| *x), 20); } #[test] fn test_deep_clone() { - let x = Gc::new(Cell::new(5)); + let x = Gc::new(RefCell::new(5)); let y = x.deep_clone(); - do x.borrow().with_mut_ref |inner| { + do x.borrow().with_mut |inner| { *inner = 20; } - assert_eq!(y.borrow().take(), 5); + assert_eq!(y.borrow().with(|x| *x), 5); } #[test] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 10887369b15..ffa91df4e8a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -164,7 +164,6 @@ pub mod result; pub mod either; pub mod hashmap; pub mod cell; -pub mod mutable; pub mod trie; diff --git a/src/libstd/mutable.rs b/src/libstd/mutable.rs deleted file mode 100644 index 44efbc149c1..00000000000 --- a/src/libstd/mutable.rs +++ /dev/null @@ -1,307 +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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A mutable memory location with dynamically checked borrow rules - -use prelude::*; - -use cast; -use util::NonCopyable; - -/// A mutable memory location with dynamically checked borrow rules -#[no_freeze] -pub struct Mut { - priv value: T, - priv borrow: BorrowFlag, - priv nc: NonCopyable -} - -// Values [1, MAX-1] represent the number of `Ref` active -// (will not outgrow its range since `uint` is the size of the address space) -type BorrowFlag = uint; -static UNUSED: BorrowFlag = 0; -static WRITING: BorrowFlag = -1; - -impl Mut { - /// Create a new `Mut` containing `value` - pub fn new(value: T) -> Mut { - Mut { - value: value, - borrow: UNUSED, - nc: NonCopyable - } - } - - /// Consumes the `Mut`, returning the wrapped value. - pub fn unwrap(self) -> T { - assert!(self.borrow == UNUSED); - self.value - } - - unsafe fn as_mut<'a>(&'a self) -> &'a mut Mut { - cast::transmute_mut(self) - } - - /// Attempts to immutably borrow the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// Returns `None` if the value is currently mutably borrowed. - pub fn try_borrow<'a>(&'a self) -> Option> { - match self.borrow { - WRITING => None, - _ => { - unsafe { self.as_mut().borrow += 1; } - Some(Ref { parent: self }) - } - } - } - - /// Immutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// # Failure - /// - /// Fails if the value is currently mutably borrowed. - pub fn borrow<'a>(&'a self) -> Ref<'a, T> { - match self.try_borrow() { - Some(ptr) => ptr, - None => fail!("Mut already mutably borrowed") - } - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts untile the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// Returns `None` if the value is currently borrowed. - pub fn try_borrow_mut<'a>(&'a self) -> Option> { - match self.borrow { - UNUSED => unsafe { - let mut_self = self.as_mut(); - mut_self.borrow = WRITING; - Some(RefMut { parent: mut_self }) - }, - _ => None - } - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts untile the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// # Failure - /// - /// Fails if the value is currently borrowed. - pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> { - match self.try_borrow_mut() { - Some(ptr) => ptr, - None => fail!("Mut already borrowed") - } - } - - /// Immutably borrows the wrapped value and applies `blk` to it. - /// - /// # Failure - /// - /// Fails if the value is currently mutably borrowed. - #[inline] - pub fn with(&self, blk: |&T| -> U) -> U { - let ptr = self.borrow(); - blk(ptr.get()) - } - - /// Mutably borrows the wrapped value and applies `blk` to it. - /// - /// # Failure - /// - /// Fails if the value is currently borrowed. - #[inline] - pub fn with_mut(&self, blk: |&mut T| -> U) -> U { - let mut ptr = self.borrow_mut(); - blk(ptr.get()) - } -} - -impl Clone for Mut { - fn clone(&self) -> Mut { - let x = self.borrow(); - Mut::new(x.get().clone()) - } -} - -impl DeepClone for Mut { - fn deep_clone(&self) -> Mut { - let x = self.borrow(); - Mut::new(x.get().deep_clone()) - } -} - -impl Eq for Mut { - fn eq(&self, other: &Mut) -> bool { - let a = self.borrow(); - let b = other.borrow(); - a.get() == b.get() - } -} - -/// Wraps a borrowed reference to a value in a `Mut` box. -pub struct Ref<'box, T> { - priv parent: &'box Mut -} - -#[unsafe_destructor] -impl<'box, T> Drop for Ref<'box, T> { - fn drop(&mut self) { - assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED); - unsafe { self.parent.as_mut().borrow -= 1; } - } -} - -impl<'box, T> Ref<'box, T> { - /// Retrieve an immutable reference to the stored value. - #[inline] - pub fn get<'a>(&'a self) -> &'a T { - &self.parent.value - } -} - -/// Wraps a mutable borrowed reference to a value in a `Mut` box. -pub struct RefMut<'box, T> { - priv parent: &'box mut Mut -} - -#[unsafe_destructor] -impl<'box, T> Drop for RefMut<'box, T> { - fn drop(&mut self) { - assert!(self.parent.borrow == WRITING); - self.parent.borrow = UNUSED; - } -} - -impl<'box, T> RefMut<'box, T> { - /// Retrieve a mutable reference to the stored value. - #[inline] - pub fn get<'a>(&'a mut self) -> &'a mut T { - &mut self.parent.value - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn double_imm_borrow() { - let x = Mut::new(0); - let _b1 = x.borrow(); - x.borrow(); - } - - #[test] - fn no_mut_then_imm_borrow() { - let x = Mut::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow().is_none()); - } - - #[test] - fn no_imm_then_borrow_mut() { - let x = Mut::new(0); - let _b1 = x.borrow(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn no_double_borrow_mut() { - let x = Mut::new(0); - let _b1 = x.borrow_mut(); - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn imm_release_borrow_mut() { - let x = Mut::new(0); - { - let _b1 = x.borrow(); - } - x.borrow_mut(); - } - - #[test] - fn mut_release_borrow_mut() { - let x = Mut::new(0); - { - let _b1 = x.borrow_mut(); - } - x.borrow(); - } - - #[test] - fn double_borrow_single_release_no_borrow_mut() { - let x = Mut::new(0); - let _b1 = x.borrow(); - { - let _b2 = x.borrow(); - } - assert!(x.try_borrow_mut().is_none()); - } - - #[test] - fn with_ok() { - let x = Mut::new(0); - assert_eq!(1, x.with(|x| *x+1)); - } - - #[test] - #[should_fail] - fn mut_borrow_with() { - let x = Mut::new(0); - let _b1 = x.borrow_mut(); - x.with(|x| *x+1); - } - - #[test] - fn borrow_with() { - let x = Mut::new(0); - let _b1 = x.borrow(); - assert_eq!(1, x.with(|x| *x+1)); - } - - #[test] - fn with_mut_ok() { - let x = Mut::new(0); - x.with_mut(|x| *x += 1); - let b = x.borrow(); - assert_eq!(1, *b.get()); - } - - #[test] - #[should_fail] - fn borrow_with_mut() { - let x = Mut::new(0); - let _b = x.borrow(); - x.with_mut(|x| *x += 1); - } - - #[test] - #[should_fail] - fn discard_doesnt_unborrow() { - let x = Mut::new(0); - let _b = x.borrow(); - let _ = _b; - let _b = x.borrow_mut(); - } -} diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index 24e7decfb82..242533773d7 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -21,7 +21,7 @@ use unstable::intrinsics::transmute; use ops::Drop; use kinds::{Freeze, Send}; use clone::{Clone, DeepClone}; -use mutable::Mut; +use cell::RefCell; struct RcBox { value: T, @@ -55,10 +55,10 @@ impl Rc { } } -impl Rc> { - /// Construct a new reference-counted box from a `Mut`-wrapped `Freeze` value +impl Rc> { + /// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value #[inline] - pub fn from_mut(value: Mut) -> Rc> { + pub fn from_mut(value: RefCell) -> Rc> { unsafe { Rc::new_unchecked(value) } @@ -116,11 +116,11 @@ impl Drop for Rc { #[cfg(test)] mod test_rc { use super::*; - use mutable::Mut; + use cell::RefCell; #[test] fn test_clone() { - let x = Rc::from_send(Mut::new(5)); + let x = Rc::from_send(RefCell::new(5)); let y = x.clone(); do x.borrow().with_mut |inner| { *inner = 20; @@ -130,7 +130,7 @@ mod test_rc { #[test] fn test_deep_clone() { - let x = Rc::from_send(Mut::new(5)); + let x = Rc::from_send(RefCell::new(5)); let y = x.deep_clone(); do x.borrow().with_mut |inner| { *inner = 20; @@ -161,6 +161,6 @@ mod test_rc { #[test] fn test_from_mut() { let a = 10; - let _x = Rc::from_mut(Mut::new(&a)); + let _x = Rc::from_mut(RefCell::new(&a)); } } diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 7441d0d3edc..8635f9372c4 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -25,10 +25,9 @@ use unstable::sync::UnsafeArc; use util; use util::Void; use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable, SendDeferred}; -use cell::Cell; +use cell::{Cell, RefCell}; use clone::Clone; use tuple::ImmutableTuple; -use mutable::Mut; /// A combined refcount / BlockedTask-as-uint pointer. /// @@ -433,20 +432,20 @@ type StreamPortOne = PortOne>; /// A channel with unbounded size. pub struct Chan { - // FIXME #5372. Using Mut because we don't take &mut self - next: Mut> + // FIXME #5372. Using RefCell because we don't take &mut self + next: RefCell> } /// An port with unbounded size. pub struct Port { - // FIXME #5372. Using Mut because we don't take &mut self - next: Mut>> + // FIXME #5372. Using RefCell because we don't take &mut self + next: RefCell>> } pub fn stream() -> (Port, Chan) { let (pone, cone) = oneshot(); - let port = Port { next: Mut::new(Some(pone)) }; - let chan = Chan { next: Mut::new(cone) }; + let port = Port { next: RefCell::new(Some(pone)) }; + let chan = Chan { next: RefCell::new(cone) }; return (port, chan); } diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs index feea0765ec2..9276a2f0d41 100644 --- a/src/test/compile-fail/issue-7013.rs +++ b/src/test/compile-fail/issue-7013.rs @@ -9,21 +9,21 @@ // except according to those terms. use std::rc::Rc; -use std::mutable::Mut; +use std::cell::RefCell; trait Foo { - fn set(&mut self, v: Rc>); + fn set(&mut self, v: Rc>); } struct B { - v: Option>> + v: Option>> } impl Foo for B { - fn set(&mut self, v: Rc>) + fn set(&mut self, v: Rc>) { self.v = Some(v); } @@ -37,7 +37,7 @@ struct A fn main() { let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send` - let v = Rc::from_send(Mut::new(a)); + let v = Rc::from_send(RefCell::new(a)); let w = v.clone(); let b = v.borrow(); let mut b = b.borrow_mut(); diff --git a/src/test/compile-fail/mut-cant-alias.rs b/src/test/compile-fail/mut-cant-alias.rs index 8e37f88af82..f031467328f 100644 --- a/src/test/compile-fail/mut-cant-alias.rs +++ b/src/test/compile-fail/mut-cant-alias.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mutable::Mut; +use std::cell::RefCell; fn main() { - let m = Mut::new(0); + let m = RefCell::new(0); let mut b = m.borrow_mut(); let b1 = b.get(); let b2 = b.get(); //~ ERROR cannot borrow `b` as mutable more than once at a time diff --git a/src/test/compile-fail/mut-not-freeze.rs b/src/test/compile-fail/mut-not-freeze.rs index 9a9669cbb3b..97fe49ca087 100644 --- a/src/test/compile-fail/mut-not-freeze.rs +++ b/src/test/compile-fail/mut-not-freeze.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mutable::Mut; +use std::cell::RefCell; fn f(_: T) {} fn main() { - let x = Mut::new(0); + let x = RefCell::new(0); f(x); //~ ERROR: which does not fulfill `Freeze` } diff --git a/src/test/compile-fail/mut-ptr-cant-outlive-ref.rs b/src/test/compile-fail/mut-ptr-cant-outlive-ref.rs index 0dbba87019a..ca276700e8b 100644 --- a/src/test/compile-fail/mut-ptr-cant-outlive-ref.rs +++ b/src/test/compile-fail/mut-ptr-cant-outlive-ref.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mutable::Mut; +use std::cell::RefCell; fn main() { - let m = Mut::new(0); + let m = RefCell::new(0); let p; { let b = m.borrow(); diff --git a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs index 981cec6f0ba..7e0c8319356 100644 --- a/src/test/compile-fail/rcmut-not-const-and-not-owned.rs +++ b/src/test/compile-fail/rcmut-not-const-and-not-owned.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::mutable::Mut; +use std::cell::RefCell; use std::rc::Rc; fn o(_: &T) {} fn c(_: &T) {} fn main() { - let x = Rc::from_send(Mut::new(0)); - o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc>`, which does not fulfill `Send` - c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc>`, which does not fulfill `Freeze` + let x = Rc::from_send(RefCell::new(0)); + o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc>`, which does not fulfill `Send` + c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc>`, which does not fulfill `Freeze` }