|
use std::rc::Rc; |
|
use std::cell::{RefCell,Ref, RefMut}; |
|
use std::ops::Deref; |
|
use std::fmt; |
|
|
|
#[derive(Clone)] |
|
struct Shared<T> { |
|
v: Rc<RefCell<T>> |
|
} |
|
|
|
impl <T> Shared<T> { |
|
fn new(t: T)-> Shared<T> { |
|
Shared{v: Rc::new(RefCell::new(t))} |
|
} |
|
} |
|
|
|
impl <T> Shared<T> { |
|
fn borrow(&self) -> Ref<T> { |
|
self.v.borrow() |
|
} |
|
|
|
fn borrow_mut(&self) -> RefMut<T> { |
|
self.v.borrow_mut() |
|
} |
|
|
|
fn as_ptr(&self) -> *mut T { |
|
self.v.as_ptr() |
|
} |
|
} |
|
|
|
|
|
impl <T: fmt::Display> fmt::Display for Shared<T> { |
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
write!(f, "{}", self.deref()) |
|
} |
|
} |
|
|
|
impl <T: fmt::Debug> fmt::Debug for Shared<T> { |
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
write!(f, "{:?}", self.deref()) |
|
} |
|
} |
|
|
|
impl <'a,T> Deref for Shared<T>{ |
|
type Target = T; |
|
|
|
#[inline] |
|
fn deref(&self) -> &T { |
|
unsafe {self.as_ptr().as_ref().unwrap()} |
|
} |
|
|
|
} |
|
|
|
/* |
|
// Cute, but useless, since it needs to be mutable |
|
// and so can't be shared anyway |
|
impl <'a, T> DerefMut for Shared<T> |
|
{ #[inline] |
|
fn deref_mut(&mut self) -> &mut T { |
|
unsafe {self.as_ptr().as_mut().unwrap()} |
|
} |
|
} |
|
*/ |
|
|
|
|
|
fn split (s: Shared<String>) -> Vec<String> { |
|
s.split_whitespace().map(|s| s.to_string()).collect() |
|
} |
|
|
|
fn main() { |
|
let s = Shared::new("hello".to_string()); |
|
let s2 = s.clone(); |
|
s2.borrow_mut().push('!'); |
|
println!("{:?}",s2); |
|
|
|
// Deref kicking in... |
|
let n = s2.len(); |
|
|
|
println!("{:?}", n); |
|
|
|
// mutation has to be explicit |
|
s2.borrow_mut().push_str(" dolly"); |
|
|
|
println!("{:?} {}",s2.borrow(), s); |
|
|
|
println!("{:?}", split(s2.clone())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
It cannot be fixed currently. Deref has associated type
Target
which cannot be polymorphic (forall t'
), because of a few reasons, including lack of HKT. I don't think it will be possible even if GATs land, asforall t'
is not what we want to tell there, really. What we want to express is that this't
inTarget
is the same ast
on&'t self
. In order to express that, we would either need to change the definition ofDeref
(not going to happen), or we would need to have some special type checking rules. I do feel that the type system around lifetimes is not flexible as it should be, so hopefully, it could be expressible in the future.