Skip to content

Commit ba9224f

Browse files
committed
Auto merge of #26934 - reem:boxed-slice-clone, r=Gankro
Closes #25097
2 parents aa6efd9 + e244230 commit ba9224f

File tree

4 files changed

+109
-10
lines changed

4 files changed

+109
-10
lines changed

src/liballoc/boxed.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
use core::prelude::*;
5757

5858
use heap;
59+
use raw_vec::RawVec;
5960

6061
use core::any::Any;
6162
use core::cmp::Ordering;
@@ -65,7 +66,7 @@ use core::marker::{self, Unsize};
6566
use core::mem;
6667
use core::ops::{CoerceUnsized, Deref, DerefMut};
6768
use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
68-
use core::ptr::Unique;
69+
use core::ptr::{self, Unique};
6970
use core::raw::{TraitObject};
7071

7172
/// A value that represents the heap. This is the default place that the `box`
@@ -514,3 +515,55 @@ impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
514515
}
515516

516517
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
518+
519+
#[stable(feature = "box_slice_clone", since = "1.3.0")]
520+
impl<T: Clone> Clone for Box<[T]> {
521+
fn clone(&self) -> Self {
522+
let mut new = BoxBuilder {
523+
data: RawVec::with_capacity(self.len()),
524+
len: 0
525+
};
526+
527+
let mut target = new.data.ptr();
528+
529+
for item in self.iter() {
530+
unsafe {
531+
ptr::write(target, item.clone());
532+
target = target.offset(1);
533+
};
534+
535+
new.len += 1;
536+
}
537+
538+
return unsafe { new.into_box() };
539+
540+
// Helper type for responding to panics correctly.
541+
struct BoxBuilder<T> {
542+
data: RawVec<T>,
543+
len: usize,
544+
}
545+
546+
impl<T> BoxBuilder<T> {
547+
unsafe fn into_box(self) -> Box<[T]> {
548+
let raw = ptr::read(&self.data);
549+
mem::forget(self);
550+
raw.into_box()
551+
}
552+
}
553+
554+
impl<T> Drop for BoxBuilder<T> {
555+
fn drop(&mut self) {
556+
let mut data = self.data.ptr();
557+
let max = unsafe { data.offset(self.len as isize) };
558+
559+
while data != max {
560+
unsafe {
561+
ptr::read(data);
562+
data = data.offset(1);
563+
}
564+
}
565+
}
566+
}
567+
}
568+
}
569+

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
#![feature(core)]
7777
#![feature(core_intrinsics)]
7878
#![feature(core_prelude)]
79+
#![feature(core_slice_ext)]
7980
#![feature(custom_attribute)]
8081
#![feature(fundamental)]
8182
#![feature(lang_items)]

src/libcollectionstest/slice.rs

+53
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,59 @@ fn test_to_vec() {
12701270
assert_eq!(ys, [1, 2, 3]);
12711271
}
12721272

1273+
#[test]
1274+
fn test_box_slice_clone() {
1275+
let data = vec![vec![0, 1], vec![0], vec![1]];
1276+
let data2 = data.clone().into_boxed_slice().clone().to_vec();
1277+
1278+
assert_eq!(data, data2);
1279+
}
1280+
1281+
#[test]
1282+
fn test_box_slice_clone_panics() {
1283+
use std::sync::Arc;
1284+
use std::sync::atomic::{AtomicUsize, Ordering};
1285+
use std::thread::spawn;
1286+
1287+
struct Canary {
1288+
count: Arc<AtomicUsize>,
1289+
panics: bool
1290+
}
1291+
1292+
impl Drop for Canary {
1293+
fn drop(&mut self) {
1294+
self.count.fetch_add(1, Ordering::SeqCst);
1295+
}
1296+
}
1297+
1298+
impl Clone for Canary {
1299+
fn clone(&self) -> Self {
1300+
if self.panics { panic!() }
1301+
1302+
Canary {
1303+
count: self.count.clone(),
1304+
panics: self.panics
1305+
}
1306+
}
1307+
}
1308+
1309+
let drop_count = Arc::new(AtomicUsize::new(0));
1310+
let canary = Canary { count: drop_count.clone(), panics: false };
1311+
let panic = Canary { count: drop_count.clone(), panics: true };
1312+
1313+
spawn(move || {
1314+
// When xs is dropped, +5.
1315+
let xs = vec![canary.clone(), canary.clone(), canary.clone(),
1316+
panic, canary].into_boxed_slice();
1317+
1318+
// When panic is cloned, +3.
1319+
xs.clone();
1320+
}).join().unwrap_err();
1321+
1322+
// Total = 8
1323+
assert_eq!(drop_count.load(Ordering::SeqCst), 8);
1324+
}
1325+
12731326
mod bench {
12741327
use std::iter::repeat;
12751328
use std::{mem, ptr};

src/libstd/ffi/c_str.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use ascii;
1212
use borrow::{Cow, ToOwned, Borrow};
1313
use boxed::Box;
14-
use clone::Clone;
1514
use convert::{Into, From};
1615
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
1716
use error::Error;
@@ -62,7 +61,7 @@ use vec::Vec;
6261
/// }
6362
/// # }
6463
/// ```
65-
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
64+
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
6665
#[stable(feature = "rust1", since = "1.0.0")]
6766
pub struct CString {
6867
inner: Box<[u8]>,
@@ -250,13 +249,6 @@ impl CString {
250249
}
251250
}
252251

253-
#[stable(feature = "rust1", since = "1.0.0")]
254-
impl Clone for CString {
255-
fn clone(&self) -> Self {
256-
CString { inner: self.inner.to_owned().into_boxed_slice() }
257-
}
258-
}
259-
260252
#[stable(feature = "rust1", since = "1.0.0")]
261253
impl Deref for CString {
262254
type Target = CStr;

0 commit comments

Comments
 (0)