Skip to content

Commit

Permalink
Auto merge of #29580 - alexbool:smart-pointer-conversion, r=alexcrichton
Browse files Browse the repository at this point in the history
Sometimes when writing generic code you want to abstract over
owning/pointer type so that calling code isn't restricted by one
concrete owning/pointer type. This commit makes possible such code:
```rust
fn i_will_work_with_arc<T: Into<Arc<MyTy>>>(t: T) {
    let the_arc = t.into();
    // Do something
}

i_will_work_with_arc(MyTy::new());

i_will_work_with_arc(Box::new(MyTy::new()));

let arc_that_i_already_have = Arc::new(MyTy::new());
i_will_work_with_arc(arc_that_i_already_have);
```

Please note that this patch doesn't work with DSTs.
Also to mention, I made those impls stable, and I don't know whether they should be actually stable from the beginning. Please tell me if this should be feature-gated.
  • Loading branch information
bors committed Nov 16, 2015
2 parents 3042fed + 67c07d4 commit 99093b7
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/liballoc/arc.rs
Expand Up @@ -87,6 +87,7 @@ use core::ptr::{self, Shared};
use core::marker::Unsize;
use core::hash::{Hash, Hasher};
use core::{usize, isize};
use core::convert::From;
use heap::deallocate;

const MAX_REFCOUNT: usize = (isize::MAX) as usize;
Expand Down Expand Up @@ -896,6 +897,13 @@ impl<T: ?Sized + Hash> Hash for Arc<T> {
}
}

#[stable(feature = "from_for_ptrs", since = "1.6.0")]
impl<T> From<T> for Arc<T> {
fn from(t: T) -> Self {
Arc::new(t)
}
}

#[cfg(test)]
mod tests {
use std::clone::Clone;
Expand All @@ -910,6 +918,7 @@ mod tests {
use std::vec::Vec;
use super::{Arc, Weak};
use std::sync::Mutex;
use std::convert::From;

struct Canary(*mut atomic::AtomicUsize);

Expand Down Expand Up @@ -1139,6 +1148,13 @@ mod tests {
drop(x);
assert!(y.upgrade().is_none());
}

#[test]
fn test_from_owned() {
let foo = 123;
let foo_arc = Arc::from(foo);
assert!(123 == *foo_arc);
}
}

impl<T: ?Sized> borrow::Borrow<T> for Arc<T> {
Expand Down
8 changes: 8 additions & 0 deletions src/liballoc/boxed.rs
Expand Up @@ -67,6 +67,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
use core::ptr::{self, Unique};
use core::raw::TraitObject;
use core::convert::From;

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
Expand Down Expand Up @@ -373,6 +374,13 @@ impl<T: ?Sized + Hash> Hash for Box<T> {
}
}

#[stable(feature = "from_for_ptrs", since = "1.6.0")]
impl<T> From<T> for Box<T> {
fn from(t: T) -> Self {
Box::new(t)
}
}

impl Box<Any> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
16 changes: 16 additions & 0 deletions src/liballoc/rc.rs
Expand Up @@ -169,6 +169,7 @@ use core::ops::Deref;
#[cfg(not(stage0))]
use core::ops::CoerceUnsized;
use core::ptr::{self, Shared};
use core::convert::From;

use heap::deallocate;

Expand Down Expand Up @@ -701,6 +702,13 @@ impl<T> fmt::Pointer for Rc<T> {
}
}

#[stable(feature = "from_for_ptrs", since = "1.6.0")]
impl<T> From<T> for Rc<T> {
fn from(t: T) -> Self {
Rc::new(t)
}
}

/// A weak version of `Rc<T>`.
///
/// Weak references do not count when determining if the inner value should be
Expand Down Expand Up @@ -906,6 +914,7 @@ mod tests {
use std::result::Result::{Err, Ok};
use std::mem::drop;
use std::clone::Clone;
use std::convert::From;

#[test]
fn test_clone() {
Expand Down Expand Up @@ -1108,6 +1117,13 @@ mod tests {
let foo: Rc<[i32]> = Rc::new([1, 2, 3]);
assert_eq!(foo, foo.clone());
}

#[test]
fn test_from_owned() {
let foo = 123;
let foo_rc = Rc::from(foo);
assert!(123 == *foo_rc);
}
}

impl<T: ?Sized> borrow::Borrow<T> for Rc<T> {
Expand Down

0 comments on commit 99093b7

Please sign in to comment.