E0046: Items Faltando na Implementação no Rust

Como resolver o erro E0046 do Rust: nem todos os items do trait foram implementados. Veja como identificar métodos faltando e implementar traits corretamente.

E0046: Items Faltando na Implementação

O erro E0046 ocorre quando você começa a implementar um trait para um tipo, mas não fornece implementações para todos os métodos obrigatórios do trait. É como assinar um contrato e não cumprir todas as cláusulas.

A Mensagem de Erro

error[E0046]: not all trait items implemented, missing: `area`
 --> src/main.rs:8:1
  |
2 |     fn area(&self) -> f64;
  |     ---------------------- `area` from trait
...
8 | impl Forma for Circulo {
  | ^^^^^^^^^^^^^^^^^^^^^^ missing `area` in implementation

Com múltiplos métodos faltando:

error[E0046]: not all trait items implemented, missing: `nome`, `descricao`
 --> src/main.rs:12:1
  |
3 |     fn nome(&self) -> &str;
  |     ----------------------- `nome` from trait
4 |     fn descricao(&self) -> String;
  |     ------------------------------ `descricao` from trait
...
12| impl Exibivel for Produto {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `nome`, `descricao` in implementation

O Que Significa

Um trait no Rust define um conjunto de métodos que um tipo deve implementar. Alguns métodos são obrigatórios (não têm corpo padrão) e outros são opcionais (têm implementação default). Quando você escreve impl TraitX for TipoY, o compilador exige que todos os métodos obrigatórios sejam implementados.

O erro lista exatamente quais métodos estão faltando, facilitando a correção.

Situações comuns:

  1. Esqueceu de implementar um ou mais métodos obrigatórios
  2. Errou a assinatura do método (nome, parâmetros ou tipo de retorno)
  3. O trait foi atualizado (nova versão do crate) e adicionou novos métodos
  4. Confundiu o nome de um método

Código com Erro

trait Forma {
    fn area(&self) -> f64;
    fn perimetro(&self) -> f64;
    fn nome(&self) -> &str;
}

struct Circulo {
    raio: f64,
}

// ERRO: faltam `perimetro` e `nome`
impl Forma for Circulo {
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.raio * self.raio
    }
}

Erro sutil com assinatura errada:

trait Repositorio {
    fn buscar(&self, id: u64) -> Option<String>;
}

struct BancoDeDados;

// ERRO: a assinatura não bate — `id: i32` vs `id: u64`
impl Repositorio for BancoDeDados {
    fn buscar(&self, id: i32) -> Option<String> {
        Some(format!("Item {}", id))
    }
}

Como Resolver

Solução 1: Implementar Todos os Métodos Obrigatórios

Adicione os métodos faltando com as assinaturas exatas do trait:

trait Forma {
    fn area(&self) -> f64;
    fn perimetro(&self) -> f64;
    fn nome(&self) -> &str;
}

struct Circulo {
    raio: f64,
}

impl Forma for Circulo {
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.raio * self.raio
    }

    fn perimetro(&self) -> f64 {
        2.0 * std::f64::consts::PI * self.raio
    }

    fn nome(&self) -> &str {
        "Círculo"
    }
}

fn main() {
    let c = Circulo { raio: 5.0 };
    println!("{}: área={:.2}, perímetro={:.2}", c.nome(), c.area(), c.perimetro());
}

Solução 2: Usar Implementações Default no Trait

Se você controla o trait, forneça implementações padrão para métodos opcionais:

trait Forma {
    fn area(&self) -> f64;         // Obrigatório
    fn perimetro(&self) -> f64;    // Obrigatório

    // Opcional — tem implementação default
    fn nome(&self) -> &str {
        "Forma desconhecida"
    }

    // Opcional — usa outros métodos do trait
    fn descricao(&self) -> String {
        format!("{}: área={:.2}", self.nome(), self.area())
    }
}

struct Quadrado {
    lado: f64,
}

impl Forma for Quadrado {
    fn area(&self) -> f64 {
        self.lado * self.lado
    }

    fn perimetro(&self) -> f64 {
        4.0 * self.lado
    }

    // `nome` e `descricao` usam a implementação default
}

Solução 3: Corrigir Assinaturas de Métodos

Verifique se as assinaturas batem exatamente:

trait Repositorio {
    fn buscar(&self, id: u64) -> Option<String>;
    fn salvar(&mut self, id: u64, valor: String) -> Result<(), String>;
}

struct BancoDeDados {
    dados: std::collections::HashMap<u64, String>,
}

impl Repositorio for BancoDeDados {
    // Assinaturas devem ser idênticas às do trait
    fn buscar(&self, id: u64) -> Option<String> {
        self.dados.get(&id).cloned()
    }

    fn salvar(&mut self, id: u64, valor: String) -> Result<(), String> {
        self.dados.insert(id, valor);
        Ok(())
    }
}

Solução 4: Usar rust-analyzer para Gerar Esqueleto

Se você usa rust-analyzer, ele oferece uma ação de código “Implement missing members” que gera automaticamente o esqueleto de todos os métodos faltando:

impl Forma for Triangulo {
    fn area(&self) -> f64 {
        todo!()  // rust-analyzer gera com todo!()
    }

    fn perimetro(&self) -> f64 {
        todo!()
    }

    fn nome(&self) -> &str {
        todo!()
    }
}

A macro todo!() compila mas causa panic em runtime — útil para implementar gradualmente.

Traits Comuns que Exigem Implementação

Alguns traits da biblioteca padrão que frequentemente precisam de implementação manual:

use std::fmt;

// Display — para formatação com {}
impl fmt::Display for MinhaStruct {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "...")
    }
}

// Iterator — para for loops
impl Iterator for MeuIterador {
    type Item = i32;
    fn next(&mut self) -> Option<Self::Item> {
        // ...
        None
    }
}

// From — para conversões
impl From<String> for MinhaStruct {
    fn from(s: String) -> Self {
        // ...
        MinhaStruct { /* ... */ }
    }
}

// Error — para tipos de erro
impl std::error::Error for MeuErro {}

Veja Também