Nirmalya
Nirmalya

Reputation: 727

Rust String::to_bytes | What does the Rust compiler mean here, exactly?

I am newbie in the Rust world.

As an exercise, this is the problem I am trying to solve:

fn main() {
    let s = give_ownership();
    println!("{}", s);
}

// Only modify the code below!
fn give_ownership() -> String {
    let s = String::from("hello, world");
    // Convert String to Vec
    let _s = s.into_bytes();
    s
}

I have gotten through. My solution works.

However, when I compile the exercise code-snippet above unchanged, I don't quite get what the compiler is telling me here, as a note below:

Compiling playground v0.0.1 (/playground)
error[E0382]: use of moved value: `s`
  --> src/main.rs:12:5
   |
9  |     let s = String::from("hello, world");
   |         - move occurs because `s` has type `String`, which does not implement the `Copy` trait
10 |     // Convert String to Vec
11 |     let _s = s.into_bytes();
   |                ------------ `s` moved due to this method call
12 |     s
   |     ^ value used here after move
   |
note: this function takes ownership of the receiver `self`, which moves `s`

My guess is that the note is about the function into_bytes(). The RustDoc says this about the function:

This consumes the String, so we do not need to copy its contents.

Could someone please elaborate on this?

Upvotes: 1

Views: 813

Answers (1)

cameron1024
cameron1024

Reputation: 10156

into_bytes() takes self (i.e. an owned self, not a reference).

This means that it takes ownership of the string it's called on. It's conceptually the same as this:

fn main() {
  let s = String::from("hello");
  take_string(s);
  println!("{s}");  // ERROR
}

fn take_string(s: String) {}

This is useful because it allows you to turn a String into a Vec<u8>, while reusing the allocation. A String is really just a Vec<u8> with the guarantee that the bytes are valid UTF-8.

So once you write let _s = s.into_bytes(), the data that was in s has now moved to _s, so you can't return s from your function. There's nothing there.

If you just want to return the string, you can just return String::from("stuff")

Upvotes: 2

Related Questions