E0107: Argumentos Genéricos Incorretos
O erro E0107 ocorre quando você fornece o número errado de argumentos genéricos (tipo, lifetime ou const) ao usar um tipo ou função genérica. É como chamar uma função com o número errado de argumentos, mas para parâmetros de tipo.
A Mensagem de Erro
error[E0107]: this struct takes 2 generic arguments but 1 generic argument was supplied
--> src/main.rs:3:16
|
3 | let mapa: HashMap<String> = HashMap::new();
| ^^^^^^^ ------- supplied 1 generic argument
| |
| expected 2 generic arguments
|
note: struct defined here, with 2 generic parameters: `K`, `V`
Outra variação — argumentos demais:
error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
--> src/main.rs:3:16
|
3 | let lista: Vec<i32, String> = Vec::new();
| ^^^ ------ help: remove this generic argument
| |
| expected 1 generic argument
O Que Significa
Tipos genéricos no Rust são definidos com um número específico de parâmetros de tipo. Quando você usa o tipo, precisa fornecer exatamente o número correto:
Vec<T>— 1 parâmetro de tipoHashMap<K, V>— 2 parâmetros de tipoResult<T, E>— 2 parâmetros de tipoOption<T>— 1 parâmetro de tipo
Se você fornece menos ou mais parâmetros que o esperado, o compilador rejeita o código. Em alguns casos, o compilador pode inferir os tipos automaticamente (e você não precisa especificá-los), mas quando você começa a anotar, precisa fornecer todos.
Código com Erro
use std::collections::HashMap;
fn main() {
// ERRO: HashMap precisa de 2 argumentos (chave e valor)
let mapa: HashMap<String> = HashMap::new();
// ERRO: Vec precisa de apenas 1 argumento
let lista: Vec<i32, f64> = Vec::new();
// ERRO: Option precisa de 1 argumento
let valor: Option = Some(42);
}
Com funções genéricas:
fn converter<T, U>(valor: T) -> U {
todo!()
}
fn main() {
// ERRO: a função precisa de 2 argumentos genéricos
let resultado = converter::<i32>(42);
}
Com lifetimes:
struct Referencia<'a, 'b> {
primeiro: &'a str,
segundo: &'b str,
}
fn criar(a: &str, b: &str) -> Referencia {
// ERRO: Referencia precisa de 2 lifetimes
Referencia { primeiro: a, segundo: b }
}
Como Resolver
Solução 1: Fornecer o Número Correto de Argumentos
use std::collections::HashMap;
fn main() {
// HashMap<K, V> — 2 argumentos
let mapa: HashMap<String, i32> = HashMap::new();
// Vec<T> — 1 argumento
let lista: Vec<i32> = Vec::new();
// Result<T, E> — 2 argumentos
let resultado: Result<String, std::io::Error> = Ok("sucesso".to_string());
// Option<T> — 1 argumento
let valor: Option<i32> = Some(42);
}
Solução 2: Deixar o Compilador Inferir os Tipos
Em muitos casos, você não precisa especificar os tipos — o compilador infere:
use std::collections::HashMap;
fn main() {
// O compilador infere HashMap<&str, i32> pelo uso
let mut mapa = HashMap::new();
mapa.insert("chave", 42);
// O compilador infere Vec<i32> pelos elementos
let lista = vec![1, 2, 3];
// Inferência parcial com _ (turbofish parcial)
let numeros: Vec<_> = (1..10).collect();
}
Solução 3: Usar Turbofish para Funções Genéricas
A sintaxe ::<> (turbofish) especifica argumentos genéricos em chamadas de função:
fn main() {
// Todos os argumentos genéricos
let resultado = "42".parse::<i32>().unwrap();
// Collect com tipo especificado
let numeros: Vec<i32> = (1..5).collect();
// Ou com turbofish:
let numeros = (1..5).collect::<Vec<i32>>();
}
Solução 4: Corrigir Lifetimes
struct Referencia<'a, 'b> {
primeiro: &'a str,
segundo: &'b str,
}
// Especifique todos os lifetimes necessários
fn criar<'a, 'b>(a: &'a str, b: &'b str) -> Referencia<'a, 'b> {
Referencia { primeiro: a, segundo: b }
}
Ou simplifique usando um único lifetime quando possível:
struct Referencia<'a> {
primeiro: &'a str,
segundo: &'a str,
}
fn criar<'a>(a: &'a str, b: &'a str) -> Referencia<'a> {
Referencia { primeiro: a, segundo: b }
}
Solução 5: Tipos com Default Genéricos
Alguns tipos têm parâmetros genéricos com valores padrão. HashMap, por exemplo, tem um terceiro parâmetro opcional para o hasher:
use std::collections::HashMap;
// HashMap<K, V, S = RandomState>
// Normalmente usamos apenas K e V:
let mapa: HashMap<String, i32> = HashMap::new();
// Mas podemos especificar um hasher customizado:
use std::hash::BuildHasherDefault;
use std::collections::hash_map::DefaultHasher;
let mapa: HashMap<String, i32, BuildHasherDefault<DefaultHasher>> = HashMap::default();
Referência Rápida de Tipos Genéricos Comuns
| Tipo | Parâmetros | Exemplo |
|---|---|---|
Vec<T> | 1 tipo | Vec<String> |
Option<T> | 1 tipo | Option<i32> |
Result<T, E> | 2 tipos | Result<String, Error> |
HashMap<K, V> | 2 tipos | HashMap<String, Vec<i32>> |
BTreeMap<K, V> | 2 tipos | BTreeMap<i32, String> |
Box<T> | 1 tipo | Box<dyn Error> |
Rc<T> | 1 tipo | Rc<String> |
Arc<T> | 1 tipo | Arc<Mutex<Vec<i32>>> |
Cow<'a, B> | 1 lifetime + 1 tipo | Cow<'a, str> |