E0382: Uso de Valor Após Move no Rust

Aprenda a resolver o erro E0382 do Rust: uso de valor após move. Entenda o sistema de ownership e veja 3 formas de corrigir este erro comum do compilador.

E0382: Uso de Valor Após Move

O erro E0382 é provavelmente o erro mais comum que todo desenvolvedor Rust encontra, especialmente no início da jornada com a linguagem. Ele está diretamente ligado ao conceito fundamental de ownership (posse) do Rust.

A Mensagem de Erro

Quando o compilador detecta esse problema, você verá algo como:

error[E0382]: borrow of moved value: `nome`
 --> src/main.rs:4:20
  |
2 |     let nome = String::from("Rust Brasil");
  |         ---- move occurs because `nome` has type `String`, which does not implement the `Copy` trait
3 |     let outro = nome;
  |                 ---- value moved here
4 |     println!("{}", nome);
  |                    ^^^^ value borrowed here after move

O Que Significa

No Rust, cada valor tem exatamente um dono (owner). Quando você atribui um valor a outra variável, o ownership é transferido (move). A variável original deixa de ser válida e não pode mais ser usada.

Isso acontece com tipos que estão alocados no heap e não implementam o trait Copy, como String, Vec<T>, Box<T>, HashMap e outros. Tipos simples como i32, f64, bool e char implementam Copy e são copiados automaticamente, sem causar move.

O sistema de ownership existe para garantir segurança de memória sem precisar de garbage collector. Quando o dono sai de escopo, a memória é liberada automaticamente. Se houvesse dois donos, teríamos um double free — e o Rust impede isso em tempo de compilação.

Código com Erro

fn main() {
    let mensagem = String::from("Olá, Rust!");

    // Aqui o ownership de `mensagem` é transferido para `copia`
    let copia = mensagem;

    // ERRO: `mensagem` não é mais válida após o move
    println!("{}", mensagem);
}

Outro cenário comum é ao passar um valor para uma função:

fn exibir(texto: String) {
    println!("{}", texto);
}

fn main() {
    let nome = String::from("Brasil");
    exibir(nome);

    // ERRO: `nome` foi movido para a função `exibir`
    println!("Nome: {}", nome);
}

Como Resolver

Solução 1: Usar .clone() para Copiar o Valor

Se você precisa usar o valor em dois lugares, pode criar uma cópia explícita:

fn main() {
    let mensagem = String::from("Olá, Rust!");
    let copia = mensagem.clone();

    // Ambas são válidas agora
    println!("Original: {}", mensagem);
    println!("Cópia: {}", copia);
}

Nota: .clone() cria uma cópia completa dos dados no heap, o que tem custo de performance. Use quando realmente precisar de duas cópias independentes do valor.

Solução 2: Usar Referências (Borrowing)

Na maioria dos casos, você não precisa de uma cópia — apenas precisa ler o valor. Use uma referência com &:

fn exibir(texto: &String) {
    println!("{}", texto);
}

fn main() {
    let nome = String::from("Brasil");
    exibir(&nome);  // Emprestamos uma referência

    // `nome` continua válido!
    println!("Nome: {}", nome);
}

Melhor ainda, use &str em vez de &String para maior flexibilidade:

fn exibir(texto: &str) {
    println!("{}", texto);
}

fn main() {
    let nome = String::from("Brasil");
    exibir(&nome);
    println!("Nome: {}", nome);
}

Solução 3: Reestruturar o Código

Às vezes a melhor solução é repensar a lógica para evitar usar o valor após movê-lo:

fn main() {
    let nome = String::from("Brasil");

    // Use o valor ANTES de movê-lo
    println!("Nome: {}", nome);

    // Agora pode mover sem problemas
    let outro = nome;
    println!("Outro: {}", outro);
}

Ou retorne o valor da função para recuperar o ownership:

fn processar(texto: String) -> String {
    println!("Processando: {}", texto);
    texto  // Retorna o ownership
}

fn main() {
    let nome = String::from("Brasil");
    let nome = processar(nome);  // Recupera o ownership
    println!("Nome: {}", nome);
}

Dica Rápida

Se você está vindo de linguagens com garbage collector (Java, Python, JavaScript), lembre-se: no Rust, a atribuição let b = a com tipos do heap move o valor, não copia. Para copiar, use .clone() explicitamente ou passe por referência com &.

Veja Também