Elisão de Lifetimes
A elisão de lifetimes permite que você omita anotações explícitas de 'a em padrões comuns. O compilador aplica três regras para inferir relações entre referências em assinaturas de função.
Receita
fn first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
fn main() {
let line = String::from("hello world");
println!("{}", first_word(&line));
}Quando usar isso: Escrever APIs limpas sem 'a redundante quando as regras de elisão cobrem sua assinatura.
Exemplo de Trabalho
struct Buffer<'a> { data: &'a [u8] }
impl<'a> Buffer<'a> {
fn get(&self, i: usize) -> Option<&u8> {
self.data.get(i)
}
fn slice(&self, range: std::ops::Range<usize>) -> Option<&[u8]> {
self.data.get(range)
}
}
fn main() {
let bytes = [1u8, 2, 3];
let buf = Buffer { data: &bytes };
println!("{:?}", buf.slice(0..2));
}O que isso demonstra:
- A elisão de métodos liga referências retornadas ao lifetime de
&self - Nenhuma anotação explícita de
'anas assinaturas degetouslice - Empréstimos retornados não podem sobreviver a
buf impl<'a>ainda é necessário na struct com parâmetro de lifetime
Mergulho Profundo
As Três Regras de Elisão
- Cada referência de entrada elidida recebe um parâmetro de lifetime distinto.
- Se houver exatamente um lifetime de entrada (ou
&self), ele é atribuído a todas as saídas. - Se houver múltiplos lifetimes de entrada, mas
&self, a saída empresta deself.
Exemplos
// Elidido: fn foo(s: &str) -> &str
// Desugared: fn foo<'a>(s: &'a str) -> &'a str
// Método elidido: fn bar(&self, x: &str) -> &str
// A saída empresta de self, não de x (regra 3)Quando a Elisão Falha
- Múltiplas referências de entrada e referência de retorno sem
&self- deve ser anotado. - Definições de struct com referências - geralmente lifetimes explícitos.
- Limites de trait de ordem superior complexos (higher-ranked trait bounds).
Armadilhas
- Assumir que o retorno empresta de qualquer parâmetro - Apenas as regras de elisão decidem. Correção: Anote quando múltiplos inputs competem.
- Método retornando referência de um argumento que não é
self- Precisa de lifetimes explícitos. Correção:fn merge<'a>(&self, other: &'a str) -> &'a stretc. - Confundir elisão com inferência dentro do corpo - A elisão é apenas para a assinatura. Correção: A inferência do corpo é separada.
- Alterar
&selfpara&mut selfsutilmente - A elisão ainda se aplica, mas as regras de empréstimo diferem. Correção: Verifique novamente os conflitos. - Métodos de trait sem garantia de elisão entre edições - Leia a documentação do trait. Correção: Lifetimes explícitos em traits públicos para clareza.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
'a explícito em tudo | Clareza da API pública | Métodos simples onde a elisão funciona |
Retornar String possuída | Evitar acoplamento de lifetime | Caminho crítico precisa de empréstimo |
| Tipo associado de saída | APIs de trait complexas | fn simples é suficiente |
| GATs (avançado) | Empréstimos semelhantes a iteradores | Assinaturas simples estáveis |
FAQs
As regras de elisão se aplicam a closures?
Closures inferem lifetimes de forma diferente; as regras de elisão são para itens fn/impl.
Posso elidir campos de struct?
Não. Campos de struct com referências precisam de parâmetros de lifetime explícitos.
E sobre `fn(&str, &str) -> &str`?
Falha na elisão - múltiplos inputs, saída ambígua. Anote: <'a>.
O `-> &str` em um método sempre significa `self`?
Com &self e outra referência, a saída é de self de acordo com a regra 3.
As assinaturas `async fn` são elididas?
O desugaring assíncrono adiciona um lifetime oculto no Future de retorno; prefira capturas 'static quando possível.
Mudanças na Edição 2024?
As regras centrais de elisão são estáveis; sempre verifique com o compilador em novas assinaturas.
A elisão pode confundir os leitores?
Às vezes. Traits públicos podem documentar lifetimes explícitos para legibilidade.
Elisão e retornos `impl Trait`?
Tipos de retorno opacos têm regras separadas; empréstimos internos ainda devem ser válidos.
Como ver a assinatura desugared?
rustc -Zunpretty=expanded ou confie no hover do rust-analyzer em erros.
Quando devo aprender anotações explícitas?
Sempre que o compilador rejeitar uma assinatura elidida - a próxima página são as anotações.
Relacionados
- Anotações de Lifetimes -
'aexplícito - Lifetimes Explicados - conceitos
- Non-Lexical Lifetimes & Reborrows - pontos finais de empréstimo
- O Verificador de Empréstimos - aplicação
Versões da Pilha: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4 e Polars 0.46+.