Question

Rust clone() vs to_owned(): What’s the Difference?

Question

In Rust, what is the difference between clone() and to_owned()?

Clone is a trait that provides the clone method (and clone_from). Some types and traits, such as string slices and collection-related abstractions, also provide a to_owned() method. Why would a type need both methods, and how do they differ?

Consider this Rust example:

fn main() {
    test_clone();
    test_to_owned();
}

fn test_clone() {
    let s1: &'static str = "I am static";
    let s2 = "I am boxed and owned".to_string();

    let c1 = s1.clone();
    let c2 = s2.clone();

    println!("{:?}", c1);
    println!("{:?}", c2);

    println!("{:?}", c1 == s1);
    println!("{:?}", c2 == s2);
}

fn test_to_owned() {
    let s1: &'static str = "I am static";
    let s2 = "I am boxed and owned".to_string();

    let c1 = s1.to_owned();
    let c2 = s2.to_owned();

    println!("{:?}", c1);
    println!("{:?}", c2);

    println!("{:?}", c1 == s1); // Why does this fail to compile?
    println!("{:?}", c2 == s2);
}

The key confusion is this: clone() works for both values, but to_owned() changes the behavior for &str. Why does the first example compile while the second produces a type mismatch?

Short Answer

By the end of this page, you will understand that clone() duplicates a value without changing its type, while to_owned() converts borrowed data into its owned version. In Rust, this difference matters most for types like &str, where clone() returns another &str, but to_owned() returns a String.

Concept

clone() and to_owned() are related, but they solve different problems.

clone()

clone() comes from the Clone trait.

Its job is simple:

  • make a duplicate of a value
  • keep the same type

Examples:

  • cloning a String gives another String
  • cloning a Vec<T> gives another Vec<T>
  • cloning a &str gives another &str

That last one is important: a string slice &str is a borrowed reference, not an owned string buffer. Cloning it does not allocate new string storage. It just copies the reference.

to_owned()

to_owned() is about converting data into an owned form.

Its job is:

  • if you have borrowed data, create an owned version of it
  • if you already have owned data, it often behaves like a clone

Examples:

  • &str.to_owned() produces a String
  • &[T].to_owned() produces a Vec<T>
  • String.to_owned() produces a String

So the big idea is:

  • clone() = duplicate this value as the same type
  • to_owned() = give me an owned version of this value

Why both exist

Rust distinguishes very clearly between:

  • borrowed data n- owned data

Many APIs work with borrowed data because borrowing is cheaper and more flexible. But sometimes you need to store data beyond the lifetime of the borrow, return it, or modify it independently. That is when to_owned() is useful.

clone() does not solve that conversion problem. It only duplicates the current type.

Why this matters

This distinction appears everywhere in Rust:

  • &str vs String
  • &[T] vs Vec<T>
  • borrowed config values vs stored application state
  • temporary input vs owned output

Understanding the difference helps you reason about ownership, allocations, performance, and API design.

Mental Model

Think of borrowed and owned data like reading a book.

  • A borrowed value is like borrowing a library book.
  • An owned value is like buying your own copy.

Now compare the methods:

  • clone() means: make another copy of whatever you currently have.

    • If you currently have a library card pointing to a book (&str), cloning just copies the card.
    • You still do not own the book.
  • to_owned() means: get your own personal copy.

    • If you borrowed the book (&str), to_owned() buys a copy (String).
    • If you already owned the book (String), it can make another owned copy.

So for &str:

  • clone() -> another borrowed &str
  • to_owned() -> an owned String

That is why the types differ.

Take Quiz

Syntax and Examples

Core syntax

let a = value.clone();
let b = value.to_owned();

The important question is: what type is value?

Example 1: &str

fn main() {
    let s: &str = "hello";

    let a = s.clone();
    let b = s.to_owned();

    // a: &str
    // b: String

    println!("{}", a);
    println!("{}", b);
}

Explanation:

  • s.clone() returns another &str
  • s.to_owned() returns a String

Example 2: String

fn main() {
    let s = String::from("hello");

    let a = s.clone();
    let b = s.to_owned();

    // a: String
    // b: String

    println!("{}", a);
    println!("{}", b);
}

For String, both methods produce a new owned String.

Example 3: Slice to vector

fn main() {
    let nums: &[i32] = &[1, 2, 3];

    let a = nums.clone();
    let b = nums.to_owned();

    // a: &[i32]
    // b: Vec<i32>

    println!("{:?}", a);
    println!("{:?}", b);
}

Again:

  • clone() keeps the same type: &[i32]
  • to_owned() produces the owned version: Vec<i32>

Your original string comparison issue

fn main() {
    let s1: &str = "I am static";

    let c1 = s1.clone();     // &str
    let c2 = s1.to_owned();  // String

    println!("{}", c1 == s1); // OK: &str == &str
    println!("{}", c2 == s1); // Often works in modern Rust due to trait impls
}

Conceptually, the reason for the old error is that c2 and s1 were different types:

  • c2: owned string
  • s1: borrowed string slice

The important lesson is not the historical compiler behavior, but that to_owned() changes &str into String, while clone() does not.

Step by Step Execution

Consider this small example:

fn main() {
    let s: &str = "rust";

    let a = s.clone();
    let b = s.to_owned();

    println!("{}", a);
    println!("{}", b);
}

Step by step

1. Create s

let s: &str = "rust";
  • s is a string slice
  • it points to string data
  • it does not own that data

2. Clone s

let a = s.clone();
  • clone() preserves the type
  • a is also &str
  • Rust copies the reference, not the string contents

So now:

  • s points to the string data
  • a points to the same string data

3. Convert to owned

let b = s.to_owned();
  • to_owned() creates an owned version
  • b is a String
  • Rust allocates memory for a new string buffer and copies the text into it

So now:

  • s is borrowed &str
  • a is borrowed &str
  • b is owned String

4. Print values

println!("{}", a);
println!("{}", b);

Both print rust, but the ownership is different.

Type trace

VariableValueType
s"rust"&str
a"rust"&str
b"rust"String

That type difference explains the behavior in your original example.

Real World Use Cases

When to use clone()

Use clone() when you want another value of the same type.

Common examples:

  • duplicate a String you already own
  • copy a Vec<T> before modifying one version
  • duplicate configuration data stored in an owned struct
  • copy an Arc<T> or Rc<T> handle
let name = String::from("Alice");
let backup = name.clone();

When to use to_owned()

Use to_owned() when you have borrowed data but need to own it.

Common examples:

  • convert &str input into String for storage
  • convert a slice &[T] into Vec<T>
  • take borrowed request data and keep it after the request ends
  • build structs that own their fields
fn save_username(input: &str) -> String {
    input.to_owned()
}

In APIs and parsing

A function may accept &str because that is flexible:

fn parse_name(input: &str) {
    // use borrowed data
}

But if the function needs to store the value, it often converts it:

struct User {
    name: String,
}

fn build_user(input: &str) -> User {
    User {
        name: input.to_owned(),
    }
}

That is a very common Rust pattern.

Take Quiz

Real Codebase Usage

In real projects, developers often use these methods as part of broader ownership patterns.

Pattern: accept borrowed, store owned

This is one of the most common Rust API designs.

struct Config {
    host: String,
}

impl Config {
    fn new(host: &str) -> Self {
        Self {
            host: host.to_owned(),
        }
    }
}

Why this is good:

  • callers can pass &str or string literals easily
  • the struct owns its data safely

Pattern: clone owned state before mutation

let original = String::from("draft");
let editable = original.clone();

Used when:

  • you need a backup
  • you want to preserve the original value
  • ownership rules prevent moving the original

Pattern: guard clauses with borrowed input

fn normalize_name(input: &str) -> Option<String> {
    if input.trim().is_empty() {
        return None;
    }

    Some(input.trim().to_owned())
}

This combines:

  • validation
  • borrowing for efficiency
  • to_owned() only when needed

Pattern: slices to owned collections

fn copy_chunk(data: &[u8]) -> Vec<u8> {
    data.to_owned()
}

This is common in:

  • networking
  • file processing
  • parsers
  • binary protocols

Performance note

Developers avoid unnecessary allocation when possible:

  • use borrowed types in function parameters
  • call to_owned() only when ownership is required
  • use clone() only when duplicating owned data intentionally

That makes code both ergonomic and efficient.

Common Mistakes

1. Assuming clone() always makes a deep owned copy

Broken assumption:

let s: &str = "hello";
let c = s.clone();

Many beginners expect c to be a String. It is not.

  • s is &str
  • c is also &str

Fix

Use to_owned() or to_string() when you need ownership.

let s: &str = "hello";
let owned = s.to_owned(); // String

2. Forgetting that to_owned() may change the type

Broken example:

let s: &str = "hello";
let x = s.to_owned();

// x is String, not &str

Fix

Check the resulting type mentally:

  • &str -> String
  • &[T] -> Vec<T>

3. Using clone() just to satisfy the borrow checker

Beginners sometimes write too many clones:

let a = some_string.clone();
let b = a.clone();
let c = b.clone();

Fix

Ask:

  • Do I need another owned value?
  • Can I borrow instead?
  • Can I restructure the code?

Cloning is valid, but unnecessary cloning can waste memory and CPU.

4. Confusing equality with identical types

In older Rust versions, comparing String and &str could fail depending on trait implementations.

let s: &str = "hello";
let owned = s.to_owned();

The conceptual issue is that these are different types even if they contain the same text.

Fix

Know the types involved. If needed, compare compatible forms:

let s: &str = "hello";
let owned = s.to_owned();

println!("{}", owned == s);

Or explicitly borrow:

println!("{}", owned.as_str() == s);

5. Using to_owned() where borrowing is enough

fn print_name(name: &str) {
    let owned = name.to_owned(); // unnecessary if only printing
    println!("{}", owned);
}

Fix

Only allocate when you need ownership.

fn print_name(name: &str) {
    println!("{}", name);
}

Comparisons

MethodMain purposeKeeps same type?Can convert borrowed to owned?Example on &strExample on String
clone()Duplicate a valueYesNo&str -> &strString -> String
to_owned()Produce an owned versionNot alwaysYes&str -> StringString -> String
to_string()Convert to StringNoOften yes for displayable types&str -> StringString -> String

clone() vs to_owned()

  • Use clone() when you want the same type again.
  • Use to_owned() when you want ownership.

to_owned() vs to_string()

For strings, these often look similar:

let a = "hello".to_owned();
let b = "hello".to_string();

Both produce a String here.

But conceptually:

  • to_owned() means “make the owned form of this borrowed value”
  • to_string() means “convert this value into a String representation”

to_owned() is more directly about ownership. to_string() is more general string conversion.

Borrowed vs owned forms

BorrowedOwned
&strString
&[T]Vec<T>
&PathPathBuf
&OsStrOsString

to_owned() is especially useful across these pairs.

Take Quiz

Cheat Sheet

Quick rules

  • clone() returns the same type.
  • to_owned() returns an owned version.
  • For borrowed data, to_owned() often allocates.
  • For already owned data, to_owned() often behaves similarly to clone().

Common examples

let s: &str = "abc";
let a = s.clone();    // &str
let b = s.to_owned(); // String
let s = String::from("abc");
let a = s.clone();    // String
let b = s.to_owned(); // String
let slice: &[i32] = &[1, 2, 3];
let a = slice.clone();    // &[i32]
let b = slice.to_owned(); // Vec<i32>

When to choose which

  • Need the same type? Use clone().
  • Need ownership from borrowed data? Use to_owned().
  • Need a String text representation? Consider to_string().

Important edge case

For &str:

  • clone() does not create a String
  • to_owned() does create a String

Memory behavior

  • Cloning a reference like &str is cheap: it copies the pointer and length.
  • to_owned() on &str copies the actual text into new owned memory.

FAQ

Why does clone() on &str not create a String?

Because clone() preserves the original type. A &str cloned value is still a &str.

Is to_owned() the same as clone() for String?

In practice, both produce a new String. The conceptual difference is that to_owned() means “give me an owned version,” while clone() means “duplicate this exact type.”

Should I use to_owned() or to_string() for &str?

Both can produce a String. For borrowed-to-owned conversion, to_owned() communicates intent more clearly.

Does to_owned() always allocate memory?

Not always in every possible type, but for common borrowed types like &str and slices, it creates owned data and therefore allocates.

Why did the comparison fail in the original example?

Because c1 from to_owned() became an owned string type, while s1 was still a borrowed string slice. The values may have the same text, but the types are different.

When should I avoid clone()?

Avoid it when borrowing is enough. Cloning owned data can be unnecessary work if you do not need an independent copy.

Take Quiz

Mini Project

Description

Build a small Rust program that accepts borrowed text and stores it inside an owned struct. This demonstrates why to_owned() exists and how it differs from clone() on borrowed string slices.

Goal

Create a User struct that stores a name as String, and write functions that show the difference between copying a borrowed &str and converting it into owned data.

Requirements

  • Define a User struct with a name: String field.
  • Write one function that uses clone() on a &str and prints the result type behavior.
  • Write another function that uses to_owned() on a &str and stores it in a User.
  • Show that a String can be duplicated with either clone() or to_owned().
  • Print enough output to verify the differences clearly.
Take Quiz

Keep learning

Related questions

View more