---
title: "Modulo std::convert em Rust: From, Into e TryFrom"
url: "https://rustlang.com.br/stdlib/convert-module/"
markdown_url: "https://rustlang.com.br/stdlib/convert-module.MD"
description: "Guia completo do modulo std::convert em Rust: From, Into, TryFrom, TryInto, AsRef, AsMut, Infallible e padroes de conversao idiomaticos."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Modulo std::convert em Rust: From, Into e TryFrom

Guia completo do modulo std::convert em Rust: From, Into, TryFrom, TryInto, AsRef, AsMut, Infallible e padroes de conversao idiomaticos.


## Visao Geral do Modulo std::convert

O modulo `std::convert` define as **traits padrao de conversao** do Rust. Essas traits formam o contrato universal para transformar valores de um tipo em outro, de forma segura e idiomatica.

As quatro traits principais formam dois pares:
- **`From<T>` / `Into<T>`** — conversoes infaliveis (que nunca falham)
- **`TryFrom<T>` / `TryInto<T>`** — conversoes faliveis (que podem retornar erro)

Alem dessas, o modulo inclui:
- **`AsRef<T>` / `AsMut<T>`** — conversoes baratas por referencia
- **`Infallible`** — tipo de erro impossivel (usado com `From`)
- **`identity`** — funcao identidade (retorna o proprio valor)

Essas traits sao tao fundamentais que a maioria esta incluida no [prelude](/stdlib/prelude/), ou seja, voce nao precisa importa-las explicitamente.

---

## Traits e Funcoes Principais

### From e Into

| Trait | Metodo | Descricao |
|---|---|---|
| `From<T>` | `fn from(T) -> Self` | Converte de T para Self |
| `Into<T>` | `fn into(self) -> T` | Converte self para T |

**Regra:** Implemente `From<T>`. A implementacao de `Into<T>` e gerada automaticamente pela blanket implementation. Nunca implemente `Into` diretamente.

### TryFrom e TryInto

| Trait | Metodo | Descricao |
|---|---|---|
| `TryFrom<T>` | `fn try_from(T) -> Result<Self, Error>` | Conversao falivel |
| `TryInto<T>` | `fn try_into(self) -> Result<T, Error>` | Conversao falivel |

### AsRef e AsMut

| Trait | Metodo | Descricao |
|---|---|---|
| `AsRef<T>` | `fn as_ref(&self) -> &T` | Referencia barata |
| `AsMut<T>` | `fn as_mut(&mut self) -> &mut T` | Referencia mutavel barata |

### Outros

| Item | Descricao |
|---|---|
| `Infallible` | Tipo de erro que nunca pode ser construido |
| `identity(x)` | Retorna `x` sem modificacao |

---

## Exemplos Praticos

### 1. Implementando From para Tipos Customizados

```rust
#[derive(Debug)]
struct Email {
    endereco: String,
}

// Conversao de &str para Email
impl From<&str> for Email {
    fn from(s: &str) -> Self {
        Email {
            endereco: s.to_lowercase(),
        }
    }
}

// Conversao de String para Email
impl From<String> for Email {
    fn from(s: String) -> Self {
        Email {
            endereco: s.to_lowercase(),
        }
    }
}

#[derive(Debug)]
struct Celsius(f64);

#[derive(Debug)]
struct Fahrenheit(f64);

impl From<Celsius> for Fahrenheit {
    fn from(c: Celsius) -> Self {
        Fahrenheit(c.0 * 9.0 / 5.0 + 32.0)
    }
}

impl From<Fahrenheit> for Celsius {
    fn from(f: Fahrenheit) -> Self {
        Celsius((f.0 - 32.0) * 5.0 / 9.0)
    }
}

fn main() {
    // From explicito
    let email = Email::from("Usuario@Email.COM");
    println!("{email:?}"); // Email { endereco: "usuario@email.com" }

    // Into implicito (gerado automaticamente pelo From)
    let email2: Email = "outro@teste.com".into();
    println!("{email2:?}");

    // Conversao de temperatura
    let agua_fervendo = Celsius(100.0);
    let em_fahrenheit: Fahrenheit = agua_fervendo.into();
    println!("{em_fahrenheit:?}"); // Fahrenheit(212.0)

    let corpo = Fahrenheit(98.6);
    let em_celsius: Celsius = corpo.into();
    println!("{em_celsius:?}"); // Celsius(37.0)
}
```

### 2. TryFrom para Conversoes Faliveis

```rust
use std::num::TryFromIntError;

#[derive(Debug)]
struct Idade(u8);

#[derive(Debug)]
enum IdadeErro {
    MuitoJovem,
    MuitoVelho,
    NumeroInvalido(TryFromIntError),
}

impl std::fmt::Display for IdadeErro {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            IdadeErro::MuitoJovem => write!(f, "Idade deve ser pelo menos 0"),
            IdadeErro::MuitoVelho => write!(f, "Idade deve ser no maximo 150"),
            IdadeErro::NumeroInvalido(e) => write!(f, "Numero invalido: {e}"),
        }
    }
}

impl TryFrom<i32> for Idade {
    type Error = IdadeErro;

    fn try_from(valor: i32) -> Result<Self, Self::Error> {
        if valor < 0 {
            Err(IdadeErro::MuitoJovem)
        } else if valor > 150 {
            Err(IdadeErro::MuitoVelho)
        } else {
            // u8::try_from(i32) pode falhar se i32 > 255,
            // mas ja validamos que esta entre 0 e 150
            Ok(Idade(valor as u8))
        }
    }
}

fn main() {
    let idades = [25, -5, 200, 0, 100];

    for &valor in &idades {
        match Idade::try_from(valor) {
            Ok(idade) => println!("{valor} -> {idade:?}"),
            Err(e) => println!("{valor} -> Erro: {e}"),
        }
    }

    // TryInto tambem funciona (gerado automaticamente)
    let resultado: Result<Idade, _> = 30i32.try_into();
    println!("\n30.try_into() = {resultado:?}");

    // Conversoes entre inteiros (TryFrom ja implementado na stdlib)
    let grande: i64 = 1_000_000;
    let tentativa: Result<i16, _> = grande.try_into();
    println!("i64({grande}) -> i16: {tentativa:?}"); // Err(TryFromIntError)
}
```

### 3. AsRef para Funcoes Genericas

```rust
use std::path::Path;

// AsRef<str> aceita tanto &str quanto String
fn contar_palavras(texto: impl AsRef<str>) -> usize {
    texto.as_ref().split_whitespace().count()
}

// AsRef<Path> aceita &str, String, PathBuf, &Path...
fn arquivo_existe(caminho: impl AsRef<Path>) -> bool {
    caminho.as_ref().exists()
}

// AsRef<[u8]> aceita &[u8], Vec<u8>, String, &str...
fn calcular_hash(dados: impl AsRef<[u8]>) -> u64 {
    let bytes = dados.as_ref();
    // Hash simples para exemplo
    bytes.iter().fold(0u64, |acc, &b| {
        acc.wrapping_mul(31).wrapping_add(b as u64)
    })
}

fn main() {
    // contar_palavras aceita diferentes tipos de string
    println!("{}", contar_palavras("Rust e incrivel")); // 3
    println!("{}", contar_palavras(String::from("Ola mundo"))); // 2

    // arquivo_existe aceita diferentes tipos de caminho
    println!("{}", arquivo_existe("/tmp"));
    println!("{}", arquivo_existe(String::from("/nao/existe")));

    // calcular_hash aceita bytes de diferentes fontes
    println!("{}", calcular_hash("texto"));
    println!("{}", calcular_hash(vec![1u8, 2, 3]));
    println!("{}", calcular_hash(b"bytes" as &[u8]));
}
```

### 4. From para Conversao de Erros

Um dos usos mais poderosos de `From` e a conversao automatica de erros com o operador `?`:

```rust
use std::io;
use std::num::ParseIntError;

#[derive(Debug)]
enum AppErro {
    Io(io::Error),
    Parse(ParseIntError),
    Validacao(String),
}

// Implementando From para cada tipo de erro
impl From<io::Error> for AppErro {
    fn from(e: io::Error) -> Self {
        AppErro::Io(e)
    }
}

impl From<ParseIntError> for AppErro {
    fn from(e: ParseIntError) -> Self {
        AppErro::Parse(e)
    }
}

impl std::fmt::Display for AppErro {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AppErro::Io(e) => write!(f, "Erro de I/O: {e}"),
            AppErro::Parse(e) => write!(f, "Erro de parse: {e}"),
            AppErro::Validacao(msg) => write!(f, "Validacao: {msg}"),
        }
    }
}

// Agora o operador ? converte automaticamente os erros!
fn processar_arquivo(caminho: &str) -> Result<i32, AppErro> {
    let conteudo = std::fs::read_to_string(caminho)?; // io::Error -> AppErro
    let numero: i32 = conteudo.trim().parse()?;       // ParseIntError -> AppErro

    if numero < 0 {
        return Err(AppErro::Validacao("Numero deve ser positivo".into()));
    }

    Ok(numero * 2)
}

fn main() {
    match processar_arquivo("/tmp/numero.txt") {
        Ok(resultado) => println!("Resultado: {resultado}"),
        Err(e) => println!("Erro: {e}"),
    }
}
```

### 5. Padroes Avancados de Conversao

```rust
// Padrao: construtor generico com Into
struct Configuracao {
    host: String,
    porta: u16,
    nome: String,
}

impl Configuracao {
    // Aceita qualquer tipo que pode ser convertido em String
    fn new(host: impl Into<String>, porta: u16, nome: impl Into<String>) -> Self {
        Configuracao {
            host: host.into(),
            porta,
            nome: nome.into(),
        }
    }
}

// Padrao: colecao de itens convertidos
fn criar_lista_de_strings(itens: &[&str]) -> Vec<String> {
    itens.iter().map(|&s| String::from(s)).collect()
}

// Padrao: identity como funcao de primeira classe
fn processar<F>(dados: Vec<i32>, transformar: F) -> Vec<i32>
where
    F: Fn(i32) -> i32,
{
    dados.into_iter().map(transformar).collect()
}

fn main() {
    // Construtor generico — aceita &str e String
    let cfg = Configuracao::new("localhost", 8080, String::from("meu_app"));
    println!("{}:{} ({})", cfg.host, cfg.porta, cfg.nome);

    // identity — util com APIs que exigem uma funcao
    let dados = vec![1, 2, 3];
    let sem_mudanca = processar(dados.clone(), std::convert::identity);
    let dobrados = processar(dados, |x| x * 2);
    println!("Identidade: {sem_mudanca:?}");
    println!("Dobrados: {dobrados:?}");

    // Conversoes embutidas na stdlib
    let n: i64 = i64::from(42i32);     // i32 -> i64 (sempre seguro)
    let s: String = String::from("ola"); // &str -> String
    let v: Vec<u8> = Vec::from(&[1u8, 2, 3][..]); // &[u8] -> Vec<u8>

    println!("{n}, {s}, {v:?}");
}
```

---

## Padroes Comuns

### Quando Implementar From vs TryFrom

| Situacao | Use |
|---|---|
| Conversao sempre funciona | `From` |
| Conversao pode falhar | `TryFrom` |
| Conversao de subconjunto (ex: u8 -> u32) | `From` |
| Conversao de superconjunto (ex: u32 -> u8) | `TryFrom` |
| Parsing de strings | `TryFrom` ou `FromStr` |
| Conversao de erros | `From` |

### Cadeia de Conversao com Into em Parametros

Prefira `impl Into<T>` em parametros de funcao para flexibilidade:

```rust
fn saudar(nome: impl Into<String>) {
    let nome = nome.into();
    println!("Ola, {nome}!");
}
```

### AsRef vs Borrow

- `AsRef<T>` e para **conversao generica** de referencia
- `Borrow<T>` e para quando o tipo emprestado tem as **mesmas garantias de Eq/Hash/Ord** (importante para chaves de HashMap)

---

## Quando Usar (e Quando Nao Usar)

**Use `std::convert` quando:**
- Precisar converter entre tipos de forma idiomatica
- Quiser que o operador `?` converta erros automaticamente
- Quiser funcoes genericas que aceitem multiplos tipos de entrada
- Precisar de validacao na conversao (`TryFrom`)

**Nao use `std::convert` quando:**
- A conversao envolve efeitos colaterais (I/O, rede) — use metodos explicitos
- A conversao e ambigua ou tem multiplas interpretacoes — use metodos nomeados
- Dois tipos tem From reciproco e isso pode causar confusao
- A conversao e custosa — documente claramente ou use um metodo explicito

**Dica de performance:** `From`/`Into` tem custo zero de abstracao — o compilador inline e otimiza as conversoes. `AsRef` tambem e custo zero, pois retorna apenas uma referencia.

---

## Veja Tambem

- [From e Into em Detalhes](/stdlib/from-into/) — aprofundamento nas traits de conversao
- [Converter String para Numero](/receitas/converter-string-numero/) — receita pratica com `parse` e `TryFrom`
- [Modulo std::any](/stdlib/any-module/) — verificacao de tipos em runtime
- [O Prelude do Rust](/stdlib/prelude/) — quais traits de conversao sao importadas automaticamente
- [String e &str](/stdlib/string/) — conversoes entre tipos de texto
- [Documentacao oficial — std::convert](https://doc.rust-lang.org/std/convert/index.html)
