Question
How can I write an idiomatic generic Rust function that accepts an immutable vector or slice, creates an owned clone, mutates only that new vector (for example, by shuffling it), and returns it?
Given an in-place shuffle function:
pub fn shuffle<T>(values: &mut [T]) {
// Shuffles the slice in place.
}
Why does this attempt fail even though newvec is declared mut?
pub fn shuffle_create_new<T: Clone>(values: &[T]) -> Vec<T> {
let mut newvec = values.clone();
shuffle(&mut newvec);
newvec.to_owned()
}
And, although this version compiles, how can I avoid consuming the caller's Vec<T> and instead return a separately cloned vector?
pub fn shuffle_owned<T: Clone>(mut values: Vec<T>) -> Vec<T> {
shuffle(&mut values);
values
}
Short Answer
You will learn the difference between cloning a reference and cloning its elements, how Vec<T> ownership affects function calls, and how to create, mutate, and return an independent Vec<T> in generic Rust code.
Concept
A Rust slice parameter such as values: &[T] is a shared reference to existing elements. It lets a function read those elements without taking ownership or allowing mutation.
The important detail is that this line does not clone the elements:
let newvec = values.clone();
Here, values has type &[T]. Cloning a shared reference produces another shared reference of the same type, &[T]. Both references point at the same original slice. Since a shared reference cannot be used to mutate the underlying data, shuffle(&mut newvec) fails.
To make an independent owned vector, clone the elements into a Vec<T>:
let mut newvec = values.to_vec();
to_vec() allocates a new vector and clones every element, which is why the type parameter needs the bound T: Clone.
A Vec<T> owns its heap-allocated element buffer. Passing a Vec<T> by value transfers ownership into the function. That can be appropriate when the caller intentionally gives up the vector, but it is not necessary when the function should preserve the caller's original collection. Accepting &[T] is usually more flexible: callers can pass either a Vec<T> or a slice.
Mental Model
Think of &[T] as a library card that lets you look at a row of books.
- Cloning the library card gives you a second card pointing to the same books. This is what
values.clone()does whenvaluesis&[T]. - Creating a
Vec<T>withvalues.to_vec()is like making a photocopy of every book and placing the copies on a new shelf.
You may rearrange the copied shelf without changing the original shelf. mut means you may rearrange the binding or data that the binding owns; it does not turn a shared reference into owned, mutable data.
Syntax and Examples
Use to_vec() to clone a slice into a new vector:
pub fn shuffle<T>(values: &mut [T]) {
// Rearrange values in place.
}
pub fn shuffled_copy<T: Clone>(values: &[T]) -> Vec<T> {
let mut copy = values.to_vec();
shuffle(&mut copy);
copy
}
copy has type Vec<T>, so it owns cloned elements and can be borrowed mutably. Rust automatically coerces &mut Vec<T> to &mut [T] when calling shuffle.
A shorter equivalent uses an iterator:
pub fn copied_values<T: Clone>(values: &[T]) -> Vec<T> {
values.iter().cloned().collect()
}
For cloning an entire slice, to_vec() is clearer. Use iter().cloned().collect() when you are already transforming, filtering, or otherwise processing values in an iterator pipeline.
Call the function with either a vector or a slice:
let original = vec![1, 2, 3, 4];
let result = shuffled_copy(&original);
assert_eq!(original, vec![1, 2, 3, 4]);
assert_eq!(result.len(), original.len());
Step by Step Execution
Consider this function:
pub fn duplicate_and_add<T: Clone>(values: &[T]) -> Vec<T> {
let mut result = values.to_vec();
result.push(values[0].clone());
result
}
For this call:
let original = vec!["red".to_string(), "blue".to_string()];
let expanded = duplicate_and_add(&original);
Execution proceeds as follows:
&originalcreates a shared borrow of the vector's contents. The caller still ownsoriginal.values.to_vec()creates a newVec<String>and callsclone()for eachStringin the slice.resultis a mutable, owned vector. It has its own strings and its own allocation.values[0].clone()creates another ownedString, whichpushappends toresult.- The function returns
result, moving that newly created vector toexpanded. originalis unchanged and remains usable.
Afterward, original contains "red" and "blue", while expanded contains "red", "blue", and "red".
Real World Use Cases
Creating a modified copy is useful whenever the original input represents data that should remain unchanged:
- Display ordering: Copy a list of products, sort the copy for a screen, and retain the source order.
- Random selection: Shuffle a copied list of quiz questions while preserving the canonical question order.
- Request processing: Copy default configuration values, then apply request-specific changes to the copy.
- Data transformations: Start with input records and build a derived collection for export or reporting.
- Simulation: Clone a game state or list of candidates before trying a hypothetical move or algorithm.
In many Rust APIs, accepting &[T] communicates that the function reads input without consuming or modifying it.
Real Codebase Usage
A common API design is to offer separate functions based on ownership needs:
pub fn shuffle_in_place<T>(values: &mut [T]) {
// Mutate an existing collection.
}
pub fn shuffled<T: Clone>(values: &[T]) -> Vec<T> {
let mut result = values.to_vec();
shuffle_in_place(&mut result);
result
}
This gives callers a clear choice:
- Call
shuffle_in_place(&mut values)when mutation is desired and avoiding a clone matters. - Call
shuffled(&values)when the original must stay unchanged.
In real projects, slices are often preferred in read-only APIs because they accept multiple collection forms:
let vector = vec![10, 20, 30];
let from_vec = shuffled(&vector);
let from_slice = shuffled(&vector[1..]);
let from_array = shuffled(&[40, 50, 60]);
For types that are expensive to clone, developers may redesign the operation: work with indices, borrow values, or make ownership transfer explicit. Cloning is correct when an independent result is genuinely required.
Common Mistakes
Cloning the reference instead of the elements
let mut copy = values.clone(); // `copy` is still `&[T]`
This duplicates only the shared reference. Use values.to_vec() to create Vec<T>.
Assuming mut changes ownership
let mut copy = values.clone();
mut allows reassignment or mutable borrowing when the value's type permits it. It does not make &[T] mutable and does not make it owned.
Taking Vec<T> by value unintentionally
fn shuffled<T: Clone>(mut values: Vec<T>) -> Vec<T> {
shuffle(&mut values);
values
}
This is valid, but the caller moves its vector into the function and cannot use the old binding afterward. Use &[T] if the function should preserve caller ownership.
Calling clone() on a Vec<T> when a slice API is intended
let copy = original.clone();
This does create an independent vector, but an API that accepts only Vec<T> is less flexible than one accepting &[T]. At the call site, original.clone() is fine when a vector clone is specifically wanted.
Forgetting the Clone bound
fn make_copy<T>(values: &[T]) -> Vec<T> {
values.to_vec()
}
This fails because Rust cannot copy arbitrary values. Require T: Clone:
fn make_copy<T: Clone>(values: &[T]) -> Vec<T> {
values.to_vec()
}
Confusing copying with cloning
Copy types, such as integers, can be duplicated implicitly. Many useful types, including String and Vec<T>, are not Copy; they need explicit Clone. A generic function that uses to_vec() should usually require T: Clone.
Comparisons
| Approach | Input ownership | Does it change the caller's vector? | Allocates/clones elements? | Best use |
|---|---|---|---|---|
fn f(values: &mut [T]) | Borrowed mutably | Yes | No | In-place operations |
fn f(values: &[T]) -> Vec<T> with to_vec() | Borrowed read-only | No | Yes | Return an independent modified copy |
fn f(values: Vec<T>) -> Vec<T> | Moved into function | The returned vector is the same owned collection, modified | No | Transform a vector when caller gives up ownership |
values.clone() where values: Vec<T> | Caller retains ownership | No | Yes | Make a copy at the call site |
values.clone() where values: &[T] | Still borrowed | No | No; clones only the reference | Usually not useful for creating a vector |
to_vec() and iter().cloned().collect() both produce a cloned vector. Prefer to_vec() for a direct whole-slice clone; prefer the iterator form when it is part of a larger iterator transformation.
Cheat Sheet
// Read-only input, independent owned output
fn copied<T: Clone>(values: &[T]) -> Vec<T> {
values.to_vec()
}
// Copy, then mutate only the copy
fn transformed<T: Clone>(values: &[T]) -> Vec<T> {
let mut result = values.to_vec();
// mutate result
result
}
// Mutate caller-owned data in place
fn mutate<T>(values: &mut [T]) {
// mutate values
}
// Take ownership of a vector
fn consume_and_transform<T>(mut values: Vec<T>) -> Vec<T> {
// mutate values
values
}
&[T]: shared, read-only borrow of contiguous elements.&mut [T]: exclusive, mutable borrow of contiguous elements.Vec<T>: owned, growable vector.values.clone()whenvalues: &[T]: clones the reference, not its elements.values.to_vec(): createsVec<T>by cloning elements; requiresT: Clone.&mut Vec<T>automatically works where&mut [T]is expected.- A
Vec<T>stores its elements on the heap; it is not itself a “boxed vector.”
FAQ
Why does values.clone() not return a Vec<T>?
Because values has type &[T]. The Clone implementation selected is for the reference itself, so the result is another &[T] pointing to the same slice.
Is to_owned() also valid for a slice?
Yes. For a slice, values.to_owned() produces Vec<T> and clones its elements. values.to_vec() is often more explicit when the desired result is a vector.
Does to_vec() make a deep copy?
It calls clone() on each element. Whether that is “deep” depends on T's Clone implementation. For example, cloning a String duplicates its text, while cloning Rc<T> duplicates a reference-counted handle.
Why does to_vec() require T: Clone?
An arbitrary Rust value cannot safely be duplicated. Clone explicitly states that values of T know how to create a duplicate.
Can I pass &Vec<T> instead of &[T]?
You can, but &[T] is more idiomatic for functions that need only slice operations. It accepts vectors, arrays, and sub-slices.
Does passing Vec<T> by value mutate the original vector?
It moves ownership into the function, so the caller's original binding is no longer usable. The function can mutate that same allocation and return it. No separate copy is made unless you explicitly clone it.
How can I avoid cloning expensive values?
If independent ownership is not needed, return references or process the slice directly. For reordering, you can also shuffle a vector of indices instead of cloning large elements.
Mini Project
Description
Build a function that returns a randomized ordering of a list without changing the source list. This mirrors common application needs such as showing quiz questions in a different order for each session while preserving the stored order.
Goal
Create an independent shuffled Vec<T> from an immutable slice and verify that the original data remains unchanged.
Requirements
Accept input as &[T] and require T: Clone.
Create a new owned vector containing cloned input elements.
Shuffle only the newly created vector.
Return the shuffled vector.
Demonstrate that the original vector remains usable and unchanged.
Keep learning
Related questions
Accepting Iterators in Rust Functions with impl Iterator
Learn how to write Rust functions that accept HashMap iterators using generic bounds or impl Iterator, avoiding trait object and lifetime errors.
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Associated Types vs Generic Type Parameters in Rust: When to Use Each
Learn when to use associated types vs generic parameters in Rust traits, with clear rules, examples, and practical API design advice.