Question

Clone a Vector in a Generic Rust Function

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 when values is &[T].
  • Creating a Vec<T> with values.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.

Take Quiz

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:

  1. &original creates a shared borrow of the vector's contents. The caller still owns original.
  2. values.to_vec() creates a new Vec<String> and calls clone() for each String in the slice.
  3. result is a mutable, owned vector. It has its own strings and its own allocation.
  4. values[0].clone() creates another owned String, which push appends to result.
  5. The function returns result, moving that newly created vector to expanded.
  6. original is 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.

Take Quiz

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

ApproachInput ownershipDoes it change the caller's vector?Allocates/clones elements?Best use
fn f(values: &mut [T])Borrowed mutablyYesNoIn-place operations
fn f(values: &[T]) -> Vec<T> with to_vec()Borrowed read-onlyNoYesReturn an independent modified copy
fn f(values: Vec<T>) -> Vec<T>Moved into functionThe returned vector is the same owned collection, modifiedNoTransform a vector when caller gives up ownership
values.clone() where values: Vec<T>Caller retains ownershipNoYesMake a copy at the call site
values.clone() where values: &[T]Still borrowedNoNo; clones only the referenceUsually 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.

Take Quiz

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() when values: &[T]: clones the reference, not its elements.
  • values.to_vec(): creates Vec<T> by cloning elements; requires T: 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.

Take Quiz

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.

Take Quiz

Keep learning

Related questions

View more