Introdução: o enigma dos dois "mut"
\nSe você já escreveu em Rust, certamente já viu a estranha dualidade da palavra-chave mut. Ela pode aparecer tanto antes do nome da variável (let mut x = 5), quanto depois dos dois pontos, junto ao tipo (&mut T). À primeira vista, parece um detalhe, mas no Stack Overflow este tópico acumulou milhares de visualizações. Por quê? Porque por trás deste detalhe esconde-se uma diferença fundamental entre propriedade e referência.
Neste artigo, não vamos apenas responder à pergunta "onde colocar mut?". Vamos olhar sob o capô do Rust, analisar como o compilador lida com a mutabilidade e por que essa diferença é a chave para o trabalho seguro com memória. Se você está aprendendo Rust ou quer entender mais profundamente seu modelo de propriedade, está no lugar certo.
\n\nParte principal: dois mundos — dois mut
\n1. Primeiro mut: "Eu sou o dono e posso mudar"
\nQuando você escreve:
\nlet mut x = 42;\nx = 10; // ok\n\nvocê está dizendo ao compilador: "Estou criando uma variável x que possui o valor 42, e autorizo a alteração deste valor no futuro". Sem o mut, a variável é imutável por padrão. Esta é uma escolha de design consciente do Rust: por padrão, segurança; mutação é uma permissão explícita.
Sob o capô: o compilador aloca espaço na pilha (ou no heap, se for um Box) e marca a célula de memória como "mutável". As verificações de empréstimo (borrow checker) garantirão que você não tenha referências mutáveis e imutáveis simultaneamente para esta memória. Se o mut não estivesse presente, qualquer tentativa de atribuir um novo valor causaria um erro de compilação.
2. Segundo mut: "Eu te dou as chaves, mas não entrego a casa"
\nAgora, um exemplo com referência:
\nlet mut x = 42;\nlet y = &mut x; // referência mutável para x\n*y = 100;\n\nAqui, &mut T não é sobre propriedade, mas sobre empréstimo. Estamos dizendo: "Estou emprestando x para a variável y, e concedendo o direito de alterá-lo". O próprio x continua sendo o dono, mas transfere temporariamente o controle.
Diferença chave: o mut depois dos dois pontos se refere ao tipo da referência, não à variável. Você não pode escrever let &mut x = &y — isso é sintaticamente incorreto. O Rust distingue estritamente:
- \n
let mut x— variável proprietária mutável \n&mut T— referência mutável para algum valor do tipo T \n
É exatamente essa diferença que confunde iniciantes: visualmente, o "mut" aparece em lugares diferentes, mas semanticamente, resolve tarefas diferentes.
\n\n3. Por que isso é importante: borrow checker
\nImagine que você está escrevendo uma função que recebe uma referência:
\nfn increment(n: &mut i32) {\n *n += 1;\n}\n\nfn main() {\n let mut a = 5;\n increment(&mut a);\n println!("{}", a); // 6\n}\n\nSe tivéssemos escrito fn increment(n: &i32) (sem mut), não poderíamos alterar n. E se esquecêssemos o mut em a, não poderíamos passar uma referência mutável. O compilador Rust protege você de alterações acidentais de dados que poderiam levar a condições de corrida ou comportamento indefinido.
Sob o capô: &mut T é uma referência única (exclusiva). A qualquer momento, pode existir apenas uma referência mutável para os dados. Esta regra garante que ninguém mais está lendo os dados enquanto você os altera. Referências imutáveis podem existir em qualquer quantidade — elas apenas leem.
4. Exemplo prático real: estruturas e métodos
\nA confusão geralmente surge ao trabalhar com métodos:
\nstruct Point {\n x: i32,\n y: i32,\n}\n\nimpl Point {\n fn shift(&mut self, dx: i32, dy: i32) {\n self.x += dx;\n self.y += dy;\n }\n}\n\nfn main() {\n let mu