Why is Vec<String> moved while using for loop?

use std::io;

fn main() {
    let mut skillset: Vec<String> = Vec::new();
    println!("Please enter your skills, enter STOP when to end:");
        let mut input = String::new();
        io::stdin().read_line(&mut input).expect("Invalid Input");
        input = String::from(input.trim());
        if input == "STOP" {break}

    for mut skill in skillset{ // skillset is moved here
        skill = skill.to_uppercase();

    println!("Here are your skills {:?}", &skillset);


I'm trying to print the content of skillset Vec but it does not work because according to the compiler, skillset is moved. I don't understand why.


For loops always consume the thing they’re looping over; you can reuse it later by looping over a reference instead:

for skill in &mut skillset {
    *skill = skill.to_uppercase();
Technical Details

In particular, for loops call IntoIterator::into_iter on the argument to turn it into an iterator, and then run the loop body once for each item returned by the iterator.

You can use a reference for this because IntoIterator is also defined for slice references.


I see now, but I have another question. I see the asterisk symbol before skill. It is for dereferencing right? By looping over a collection, I get its items as references by default, is it so? I have then to dereference to mutate the actual value.

By looping over a reference to a collection, you get references to the items. Dereferencing is required to change the value that’s being referenced.

The code doesn’t compile without the star because of a type mismatch. If it did compile, you’d be changing which storage location the reference points to instead of the content of the location.

In your original code where the loop destroyed the collection, you weren’t getting references— the collection no longer existed to be referred to.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.