Skip to content

Commit c4f8fd2

Browse files
authored
Rollup merge of rust-lang#64975 - crgl:clone-from-linked-list, r=bluss
Implement Clone::clone_from for LinkedList See rust-lang#28481. This represents a substantial speedup when the list sizes are comparable, and shouldn't ever be significantly worse. Technically split_off is doing an unnecessary search, but the code is hopefully cleaner as a result. I'm happy to rework anything that needs to be changed as well!
2 parents faf2e80 + 864e6fe commit c4f8fd2

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

src/liballoc/collections/linked_list.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,19 @@ impl<T: Clone> Clone for LinkedList<T> {
11971197
fn clone(&self) -> Self {
11981198
self.iter().cloned().collect()
11991199
}
1200+
1201+
fn clone_from(&mut self, other: &Self) {
1202+
let mut iter_other = other.iter();
1203+
if self.len() > other.len() {
1204+
self.split_off(other.len());
1205+
}
1206+
for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) {
1207+
elem.clone_from(elem_other);
1208+
}
1209+
if !iter_other.is_empty() {
1210+
self.extend(iter_other.cloned());
1211+
}
1212+
}
12001213
}
12011214

12021215
#[stable(feature = "rust1", since = "1.0.0")]

src/liballoc/collections/linked_list/tests.rs

+43
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,49 @@ fn test_append() {
110110
check_links(&n);
111111
}
112112

113+
#[test]
114+
fn test_clone_from() {
115+
// Short cloned from long
116+
{
117+
let v = vec![1, 2, 3, 4, 5];
118+
let u = vec![8, 7, 6, 2, 3, 4, 5];
119+
let mut m = list_from(&v);
120+
let n = list_from(&u);
121+
m.clone_from(&n);
122+
check_links(&m);
123+
assert_eq!(m, n);
124+
for elt in u {
125+
assert_eq!(m.pop_front(), Some(elt))
126+
}
127+
}
128+
// Long cloned from short
129+
{
130+
let v = vec![1, 2, 3, 4, 5];
131+
let u = vec![6, 7, 8];
132+
let mut m = list_from(&v);
133+
let n = list_from(&u);
134+
m.clone_from(&n);
135+
check_links(&m);
136+
assert_eq!(m, n);
137+
for elt in u {
138+
assert_eq!(m.pop_front(), Some(elt))
139+
}
140+
}
141+
// Two equal length lists
142+
{
143+
let v = vec![1, 2, 3, 4, 5];
144+
let u = vec![9, 8, 1, 2, 3];
145+
let mut m = list_from(&v);
146+
let n = list_from(&u);
147+
m.clone_from(&n);
148+
check_links(&m);
149+
assert_eq!(m, n);
150+
for elt in u {
151+
assert_eq!(m.pop_front(), Some(elt))
152+
}
153+
}
154+
}
155+
113156
#[test]
114157
fn test_insert_prev() {
115158
let mut m = list_from(&[0, 2, 4, 6, 8]);

0 commit comments

Comments
 (0)