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:
- Esqueceu de implementar um ou mais métodos obrigatórios
- Errou a assinatura do método (nome, parâmetros ou tipo de retorno)
- O trait foi atualizado (nova versão do crate) e adicionou novos métodos
- 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 {}