No description
Find a file
2026-09-01 13:34:23 +02:00
.woodpecker chore: migrate CI to .woodpecker/{push,branch}.yml 2026-09-01 13:34:23 +02:00
src fix(026): pedagogical MINOR fixes 2026-09-01 13:34:23 +02:00
tests initial content 2026-09-01 13:34:21 +02:00
.gitignore Initial commit 2026-09-01 11:33:58 +00:00
Cargo.lock initial content 2026-09-01 13:34:21 +02:00
Cargo.toml chore: declare MSRV 1.85 (edition 2024) 2026-09-01 13:34:23 +02:00
LICENSE chore: add AGPL-3.0 license and standard .gitignore 2026-09-01 13:34:23 +02:00
README.md fix(026): pedagogical MINOR fixes 2026-09-01 13:34:23 +02:00

Lição 26: Tempo de Vida (Lifetimes)

1. Narrativa

No sistema do mecha Æther, cada referência de dados tem um tempo de validade — um período durante o qual o dado pode ser acessado com segurança. Lifetimes garantem que nenhuma referência aponte para dados que já foram desativados, prevenindo falhas críticas no sistema de controle.

2. Conceito

Lifetimes ('a) são anotações que o compilador usa para verificar validade de referências:

  • Anotação explícita: <'a> — quando o compilador precisa de ajuda
  • Elision: Regras automáticas — uma entrada/uma saída, &self, etc.
  • Structs com lifetimes: struct Registro<'a> — a struct não pode viver mais que os dados que referencia
  • 'static: Tempo de vida de todo o programa — literais de string e constantes
  • Bounds genéricos: where T: Trait + 'a — combinar lifetimes com traits

3. Requisitos

  • Anotar lifetimes explícitos em funções com múltiplas referências
  • Entender quando elision é suficiente
  • Criar structs que armazenam referências com lifetimes
  • Usar 'static para dados permanentes e bounds em funções genéricas

4. Design de Dados

graph LR
    A[&'a str sensor_a] --> C[fn sensor_mais_duravel]
    B[&'a str sensor_b] --> C
    C --> D[&'a str resultado]
    E[RegistroDiagnostico 'a] --> F[nome: &'a str]
    E --> G[laudo: &'a str]
    H["'static"] --> I[id_sistema_central]

5. Diagrama de Fluxo

flowchart TD
    A[Início] --> B{Múltiplas refs de entrada?}
    B -->|Sim| C[Anotação explícita 'a]
    B -->|Não| D[Elision automática]
    C --> E[Struct com lifetime?]
    D --> E
    E -->|Sim| F["struct Registro<'a>"]
    E -->|Não| G[Lifetime estático?]
    F --> H[Verificar compilador]
    G -->|Sim| I["'static"]
    G -->|Não| H
    I --> H

6. Funções

Função Descrição
sensor_mais_duravel Retorna ref com lifetime explícito 'a
primeiro_alerta Lifetime explícito — &[&str] tem 2 lifetimes, elisão falha (E0106)
nome_do_modelo Elision: uma entrada, saída automática
codigo_status Elision: entrada e saída compartilham lifetime
RegistroDiagnostico::novo Cria struct com referências
RegistroDiagnostico::resumo Resumo do diagnóstico
RegistroDiagnostico::eh_critico Verifica criticidade ≥ 8
ResultadoScan::novo Cria resultado de scan
ResultadoScan::registrar_anomalia Adiciona anomalia detectada
ResultadoScan::total_anomalias Conta anomalias
id_sistema_central Retorna &'static str
protocolo_seguranca Retorna &'static str
componente_maior_prioridade Bound genérico com lifetime + trait
filtrar_por_prioridade Filtra componentes por prioridade

7. Exemplo

fn sensor_mais_duravel<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.len() >= b.len() { a } else { b }
}
let resultado = sensor_mais_duravel("Sensor-Alpha", "Sensor-Beta");
let registro = RegistroDiagnostico::novo("Reator", "Operacional", 3);

8. Missão

  1. Implementar sensor_mais_duravel com lifetime 'a explícito
  2. Implementar primeiro_alerta buscando na slice
  3. Implementar funções com elision: nome_do_modelo, codigo_status
  4. Implementar RegistroDiagnostico: novo, resumo, eh_critico
  5. Implementar ResultadoScan: novo, registrar_anomalia, total_anomalias
  6. Implementar funções 'static: id_sistema_central, protocolo_seguranca
  7. Implementar componente_maior_prioridade e filtrar_por_prioridade com bounds genéricos

9. Como Executar

cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check

10. Dicas

  • Lifetimes não mudam o tempo de vida dos dados — apenas verificam segurança
  • Elision aplica 3 regras: cada referência de entrada ganha um lifetime, se uma entrada então saída = entrada, se &self então saída = &self
  • Structs que guardam referências PRECISAM de anotação de lifetime
  • 'static não significa "vive para sempre no heap" — significa "vive por toda a execução do programa"
  • Avançado (Lição 28): componente_maior_prioridade<T> e filtrar_por_prioridade<T> usam parâmetros genéricos <T> — você os estudará na Lição 28. Por ora, trate T como "qualquer tipo" que implemente o trait PrioridadeComponente
  • Avançado (Lição 29): o trait PrioridadeComponente (com where T: PrioridadeComponente) é um trait bound — você estudará traits em detalhe na Lição 29. O trait já é fornecido; você só precisa implementar as funções que o usam
  • Exceção ao "prefira elisão": fn f(alertas: &[&str]) -> Option<&str> rejeita elisão com E0106. A slice &[&str] esconde dois lifetimes de entrada (o da referência externa e o dos elementos &str internos), e a regra que propaga o lifetime de entrada para a saída só dispara quando há exatamente um. A anotação <'a> amarra explicitamente a saída ao lifetime da slice. É exatamente o caso de primeiro_alerta — ver a explicação na sua doc comment.