Trait Bounds
Bounds restringem parâmetros genéricos para que o código possa chamar métodos de trait com segurança: T: Display, cláusulas where e múltiplos bounds com +.
Receita
use std::fmt::Display;
fn print_all<T: Display>(items: &[T]) {
for item in items {
println!("{item}");
}
}
fn compare<T>(a: T, b: T) -> T
where
T: PartialOrd,
{
if a > b { a } else { b }
}Quando usar isso: Qualquer função genérica que use métodos de trait; prefira where para bounds complexos e legíveis.
Exemplo de Trabalho
use std::fmt::{Debug, Display};
fn report<T>(value: T) -> String
where
T: Debug + Display,
{
format!("o usuário vê {value}, debug {value:?}")
}
fn main() {
println!("{}", report(42));
}O que isso demonstra:
- Múltiplos bounds
Debug + Display - A cláusula
wheresepara os bounds da assinatura - Bounds verificados em tempo de compilação por
Tmonomorfizado - Violação falha no local da chamada com erro claro
Mergulho Profundo
Açúcar sintático impl Trait
fn f(x: impl Display) == fn f<T: Display>(x: T) para um parâmetro.
Bounds de alta ordem (Higher-ranked bounds)
for<'a> para funções que precisam de qualquer lifetime - avançado com traits Fn.
Bounds de lifetime
T: 'a - valores em T não podem emprestar por menos tempo que 'a.
Armadilhas
- Bound muito fraco - Método ausente em
T. Correção: Adicionar trait à lista de bounds. - Bound muito forte - Limita os tipos utilizáveis. Correção: Dividir funções ou usar trait objects.
- Impls blanket conflitantes - Duas auto impls sobrepostas. Correção: Evitar padrões blanket impossíveis.
- Explosão da cláusula
where- Ilegível. Correção: Aliases de tipotype SerializeMap = .... impl Traitem retorno não é object-safe (mistura) - Não pode retornar tiposimpl Traitdiferentes. Correção: Enum ouBox<dyn Trait>.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
Parâmetro dyn Trait | Entradas heterogêneas | Genéricos são mais rápidos |
| Tipos concretos | Uso único | Reutilização de biblioteca |
| Enum de capacidades | Opções fechadas | Conjunto aberto de traits |
| Macros | Gerar funções com bounds | Bounds expressáveis |
FAQs
`where` vs bounds inline?
Estilo - `where` é mais limpo para listas longas.Bound em tipo associado?
`where T::Item: Clone`.Impl Trait múltiplos?
`impl A + B` em parâmetros.Bounds negativos?
Não suportado - usar traits selados ou tipos separados.Auto traits?
`Send`, `Sync` implementados automaticamente quando seguros.Alias de trait?
`trait MyBound = A + B + C;` recurso estável.Bounds em structs?
`struct S<T: Display>(T)`.Relaxar bounds?
Dividir API: helper com menos bounds + wrapper fino.Bounds GAT?
Tipos associados genéricos carregam seus próprios bounds.Bounds async?
`T: Future` ou `T: AsyncRead` etc.Relacionados
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+.