We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ownership II: Borrowing and the Borrow Checker step 19 of 24
What a &mut parameter actually promises
Repair self_merge while keeping the provided merge_into unchanged:
pub fn merge_into(dst: &mut Vec<i64>, src: &[i64])
pub fn self_merge(xs: &mut Vec<i64>) -> usize
merge_into appends all source elements to the destination, preserving
duplicates, then sorts the destination in ascending order. It does not
change the source.
self_merge duplicates every element currently in its vector, sorts the
result in ascending order and returns the new length. It works on the
vector it receives, whether or not that vector is already sorted. Empty
input stays empty and returns zero.
The harness first merges src into dst, records that intermediate result,
and then calls self_merge on it:
| Destination | Source | After merge_into | After self_merge | Length |
|---|---|---|---|---|
[3, 1] |
[2] |
[1, 2, 3] |
[1, 1, 2, 2, 3, 3] |
6 |
[5] |
[] |
[5] |
[5, 5] |
2 |
[] |
[] |
[] |
[] |
0 |
Values may be any i64; neither function performs arithmetic on them.
Preserve all occurrences rather than deduplicating.
Why the starter call conflicts
The starter tries to use one vector as both arguments:
merge_into(xs, xs);
The first argument needs a mutable borrow of the vector. The second needs a shared slice of its elements for the same call. Rust rejects these overlapping borrows with E0502.
merge_into may grow the destination's allocation while reading the source.
Its signature requires those accesses to be compatible; it cannot accept a
source slice borrowed from that same destination. Reserving spare capacity
would not make the conflicting call legal.
This restriction does not forbid all reborrowing. A function can derive a shorter borrow from a mutable reference and use it while the original access is suspended. What fails here is asking this API to use overlapping source and destination through separate arguments.
Use the vector's self-extension operation
Vec::extend_from_within(..) appends clones of the vector's original
elements to its own end. For i64, cloning copies the value. The method
manages any capacity growth without requiring the caller to supply an
overlapping source slice.
After extending, sort the vector and return its length. There is no separate snapshot vector, but the destination may still need to allocate more capacity. This avoids a temporary collection, not every possible allocation.
Copying the original elements into a temporary vector and merging from that
snapshot can also be correct. It is unnecessary for this task. Likewise,
split_at_mut is useful for distinct regions of a slice, but it does not
by itself duplicate a whole vector or grow its length.
Returned references can prolong an input borrow
A method returning a shared reference can still keep its receiver mutably borrowed. This signature:
fn get(&mut self) -> &Thing
has the same elided lifetime relationship as:
fn get<'a>(&'a mut self) -> &'a Thing
The caller must respect that exclusive input borrow while it continues to use the returned reference. The borrow can end at the reference's last use; it does not necessarily last until the binding's scope ends. For example:
struct Counter(i32);
impl Counter {
fn get(&mut self) -> &i32 { &self.0 }
}
let mut counter = Counter(1);
let observed = counter.get();
assert_eq!(*observed, 1); // Last use of observed.
counter.0 = 2;
assert_eq!(counter.0, 2);
If observed were used again after the assignment, the overlapping access
would be rejected. Choose &self when an API only needs shared access;
choose &mut self when it needs exclusivity. Interior mutability and unsafe
abstractions require their own access rules, so a lint alone is not a
complete description of an API's guarantees.
What the intermediate output checks
Both helpers must sort independently. Checking the intermediate vector
catches a missing sort in merge_into that the later sort in self_merge
could hide. It does not check the original append order, because that
intermediate result is already sorted.
Submissions must compile, pass the cases and pass the Rust Clippy gate.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.