Skip to content

Commit

Permalink
Rollup merge of rust-lang#64975 - crgl:clone-from-linked-list, r=bluss
Browse files Browse the repository at this point in the history
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!
  • Loading branch information
Manishearth authored Oct 2, 2019
2 parents 0ec37c4 + 864e6fe commit cd104d3
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/liballoc/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,19 @@ impl<T: Clone> Clone for LinkedList<T> {
fn clone(&self) -> Self {
self.iter().cloned().collect()
}

fn clone_from(&mut self, other: &Self) {
let mut iter_other = other.iter();
if self.len() > other.len() {
self.split_off(other.len());
}
for (elem, elem_other) in self.iter_mut().zip(&mut iter_other) {
elem.clone_from(elem_other);
}
if !iter_other.is_empty() {
self.extend(iter_other.cloned());
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
43 changes: 43 additions & 0 deletions src/liballoc/collections/linked_list/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,49 @@ fn test_append() {
check_links(&n);
}

#[test]
fn test_clone_from() {
// Short cloned from long
{
let v = vec![1, 2, 3, 4, 5];
let u = vec![8, 7, 6, 2, 3, 4, 5];
let mut m = list_from(&v);
let n = list_from(&u);
m.clone_from(&n);
check_links(&m);
assert_eq!(m, n);
for elt in u {
assert_eq!(m.pop_front(), Some(elt))
}
}
// Long cloned from short
{
let v = vec![1, 2, 3, 4, 5];
let u = vec![6, 7, 8];
let mut m = list_from(&v);
let n = list_from(&u);
m.clone_from(&n);
check_links(&m);
assert_eq!(m, n);
for elt in u {
assert_eq!(m.pop_front(), Some(elt))
}
}
// Two equal length lists
{
let v = vec![1, 2, 3, 4, 5];
let u = vec![9, 8, 1, 2, 3];
let mut m = list_from(&v);
let n = list_from(&u);
m.clone_from(&n);
check_links(&m);
assert_eq!(m, n);
for elt in u {
assert_eq!(m.pop_front(), Some(elt))
}
}
}

#[test]
fn test_insert_prev() {
let mut m = list_from(&[0, 2, 4, 6, 8]);
Expand Down

0 comments on commit cd104d3

Please sign in to comment.