diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 85aefbfffb1..25ff1f1a82a 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1068,6 +1068,18 @@ fn merge_sort(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order let mut out = buf_tmp.offset(start as isize); let out_end = buf_tmp.offset(right_end_idx as isize); + // If left[last] <= right[0], they are already in order: + // fast-forward the left side (the right side is handled + // in the loop). + // If `right` is not empty then left is not empty, and + // the offsets are in bounds. + if right != right_end && compare(&*right.offset(-1), &*right) != Greater { + let elems = (right_start as usize - left as usize) / mem::size_of::(); + ptr::copy_nonoverlapping(&*left, out, elems); + out = out.offset(elems as isize); + left = right_start; + } + while out < out_end { // Either the left or the right run are exhausted, // so just copy the remainder from the other run