about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/heap.rs6
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs35
3 files changed, 36 insertions, 6 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 08a0b2a6d00..056af13016c 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -16,7 +16,6 @@
             issue = "27700")]
 
 use core::{isize, usize};
-#[cfg(not(test))]
 use core::intrinsics::{min_align_of_val, size_of_val};
 
 #[allow(improper_ctypes)]
@@ -158,10 +157,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     }
 }
 
-#[cfg(not(test))]
-#[lang = "box_free"]
+#[cfg_attr(not(test), lang = "box_free")]
 #[inline]
-unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
     let size = size_of_val(&*ptr);
     let align = min_align_of_val(&*ptr);
     // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 0c01eabd593..c70d82392f9 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -87,6 +87,7 @@
 #![feature(needs_allocator)]
 #![feature(optin_builtin_traits)]
 #![feature(placement_in_syntax)]
+#![cfg_attr(stage0, feature(pub_restricted))]
 #![feature(shared)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index fed718e9be4..69e5351cad5 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -239,7 +239,7 @@ use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
 use core::convert::From;
 
-use heap::deallocate;
+use heap::{allocate, deallocate, box_free};
 use raw_vec::RawVec;
 
 struct RcBox<T: ?Sized> {
@@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> {
     value: T,
 }
 
-
 /// A single-threaded reference-counting pointer.
 ///
 /// See the [module-level documentation](./index.html) for more details.
@@ -438,6 +437,38 @@ impl Rc<str> {
     }
 }
 
+impl<T> Rc<[T]> {
+    /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
+    #[doc(hidden)]
+    #[unstable(feature = "rustc_private",
+               reason = "for internal use in rustc",
+               issue = "0")]
+    pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
+        unsafe {
+            let ptr: *mut RcBox<[T]> =
+                mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
+            // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
+            // we should have a better way of getting the size/align
+            // of a DST from its unsized part.
+            let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr));
+            let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
+
+            // Initialize the new RcBox.
+            ptr::write(&mut (*ptr).strong, Cell::new(1));
+            ptr::write(&mut (*ptr).weak, Cell::new(1));
+            ptr::copy_nonoverlapping(
+                value.as_ptr(),
+                &mut (*ptr).value as *mut [T] as *mut T,
+                value.len());
+
+            // Free the original allocation without freeing its (moved) contents.
+            box_free(Box::into_raw(value));
+
+            Rc { ptr: Shared::new(ptr as *const _) }
+        }
+    }
+}
+
 impl<T: ?Sized> Rc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///