Por que o Rust precisa de tempos de vida explícitos? Explicamos com exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que o Rust obriga a especificar tempos de vida? E como isso simplifica a vida?

\n\n

Se você está estudando Rust, mais cedo ou mais tarde encontrará essa sintaxe misteriosa: 'a, 'b... E surge uma pergunta natural: «Por que eu preciso especificar explicitamente os tempos de vida? Outras linguagens conseguem se virar!»

\n\n

Essa pergunta é uma das mais populares no Stack Overflow (milhares de visualizações). E não é surpresa: o conceito de lifetimes no Rust parece complicado até que você entenda sua essência. Vamos analisar sem teoria entediante, com exemplos práticos.

\n\n

Resposta curta: segurança sem coletor de lixo

\n\n

O Rust garante segurança de memória em tempo de compilação. Ele precisa saber exatamente quanto tempo as referências vivem para evitar referências pendentes (dangling references). Em Java ou Go, o coletor de lixo cuida disso. Em C++, você é responsável pela memória (e frequentemente erra). O Rust escolheu um terceiro caminho: o compilador verifica tudo estaticamente.

\n\n

Mas por que o compilador não consegue adivinhar sozinho? Ele consegue — em 80% dos casos. Isso é chamado de lifetime elision (regras de inferência implícita). No entanto, em situações complexas, ele precisa da sua ajuda.

\n\n

Regra nº 1: O compilador não é vidente

\n\n

Veja esta função:

\n\n
fn longest(x: &str, y: &str) -> &str {\n    if x.len() > y.len() { x } else { y }\n}
\n\n

À primeira vista, tudo parece lógico. Mas o Rust emitirá um erro: «missing lifetime specifier». Por quê?

\n\n

Imagine que você passou x — uma referência a uma string que vive 5 segundos, e y — uma referência a uma string que vive 1 segundo. A função pode retornar qualquer uma delas. Qual será o tempo de vida da referência retornada? O compilador não sabe!

\n\n

A solução é dizer explicitamente: «a referência retornada viverá tanto quanto ambas as referências de entrada»:

\n\n
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n    if x.len() > y.len() { x } else { y }\n}
\n\n

O símbolo 'a é uma anotação de tempo de vida. Estamos dizendo: «todas as três referências devem ter o mesmo tempo de vida mínimo». Agora o compilador pode verificar se o código chamador não destruirá os dados antes do tempo.

\n\n

Regra nº 2: Referências diferentes — vidas diferentes

\n\n

Um erro comum de iniciantes é pensar que todos os 'a devem ser iguais. Na verdade, você pode especificar tempos de vida diferentes:

\n\n
fn example<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {\n    x // Ok, retornamos uma referência com tempo de vida 'a\n    // y // Erro! y vive 'b, mas prometemos 'a\n}
\n\n

Aqui, dizemos explicitamente: x e y podem ter tempos de vida diferentes. Mas só podemos retornar a referência cujo tempo de vida corresponde ao prometido no tipo de retorno.

\n\n

Regra nº 3: Estruturas também podem armazenar referências

\n\n

Ao criar uma estrutura que contém referências, os tempos de vida no Rust devem ser especificados obrigatoriamente:

\n\n
struct Book<'a> {\n    title: &'a str,\n    author: &'a str,\n}\n\nfn main() {\n    let title = String::from("Rust Book");\n    let book;\n    {\n        let author = String::from("John Doe");\n        book = Book { title: &title, author: &author };\n    } // author é destruído aqui!\n    println!("{}", book.title); // Erro! book.author está pendente\n}
\n\n

O compilador não permitirá compilar este código, porque book.author referencia uma string já removida. Os lifetimes explícitos no Rust permitem capturar esses erros em tempo de compilação, e não em tempo de execução.

\n\n

Regra nº 4: Lifetime Elision — quando não é necessário escrever

\n\n

O Rust é inteligente o suficiente para inferir tempos de vida em casos simples. Aqui estão os casos em que você não precisa especificar:

\n\n
    \n
  • Uma referência de entrada — o tempo de vida da saída é igual ao tempo de

Blogs

Book Recommendations