---
title: "From e Into Traits em Rust"
url: "https://rustlang.com.br/stdlib/from-into/"
markdown_url: "https://rustlang.com.br/stdlib/from-into.MD"
description: "Guia completo sobre os traits From e Into em Rust: conversão de tipos, implementação blanket, tratamento de erros e exemplos práticos."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# From e Into Traits em Rust

Guia completo sobre os traits From e Into em Rust: conversão de tipos, implementação blanket, tratamento de erros e exemplos práticos.


## O que são From e Into?

Os traits `From` e `Into` formam o sistema de **conversão de tipos** do Rust. Eles permitem transformar um valor de um tipo em outro de forma segura, explícita e idiomática.

- **`From<T>`**: define como criar um tipo **a partir de** outro tipo `T`.
- **`Into<U>`**: define como converter um tipo **para** outro tipo `U`.

A beleza desse sistema é que **implementar `From` dá `Into` de graça**. Graças a uma implementação blanket na biblioteca padrão, se você implementa `From<A> for B`, automaticamente `A` ganha `Into<B>`. Por isso, a convenção é **sempre implementar `From`**, nunca `Into` diretamente.

---

## Definição dos Traits

```rust
// Definido em std::convert
pub trait From<T>: Sized {
    fn from(value: T) -> Self;
}

pub trait Into<T>: Sized {
    fn into(self) -> T;
}
```

A implementação blanket que conecta os dois:

```rust
// Na biblioteca padrão (simplificado)
impl<T, U> Into<U> for T
where
    U: From<T>,
{
    fn into(self) -> U {
        U::from(self)
    }
}
```

Isso significa: para qualquer tipo `T`, se `U` implementa `From<T>`, então `T` automaticamente implementa `Into<U>`.

---

## Como Implementar

### Implementação de From

`From` não pode ser derivado — você sempre implementa manualmente:

```rust
struct Celsius(f64);
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() {
    // Usando From::from explicitamente
    let fahr = Fahrenheit::from(Celsius(100.0));
    println!("100°C = {}°F", fahr.0); // 212°F

    // Usando .into() (funciona por causa da blanket impl)
    let celsius: Celsius = Fahrenheit(32.0).into();
    println!("32°F = {}°C", celsius.0); // 0°C
}
```

### From na biblioteca padrão

Rust já fornece dezenas de implementações de `From`:

```rust
fn main() {
    // String::from(&str)
    let s = String::from("olá mundo");

    // Vec<u8> from String
    let bytes: Vec<u8> = Vec::from(s.clone());

    // String from Vec<u8> (pode falhar — use String::from_utf8)
    // Mas &str from &[u8] que é válido UTF-8 usa from_utf8_unchecked

    // i64 from i32 (conversão sem perda)
    let grande: i64 = i64::from(42i32);

    // Box<str> from String
    let boxed: Box<str> = Box::from(s);

    println!("{}", boxed);
}
```

---

## Exemplos Práticos

### Exemplo 1: Conversão de tipos de domínio

```rust
#[derive(Debug)]
struct Email(String);

#[derive(Debug)]
struct Usuario {
    nome: String,
    email: Email,
}

impl From<String> for Email {
    fn from(s: String) -> Self {
        Email(s)
    }
}

impl From<&str> for Email {
    fn from(s: &str) -> Self {
        Email(s.to_string())
    }
}

fn main() {
    // From::from
    let email1 = Email::from("ana@exemplo.com");

    // .into() — o compilador infere o tipo alvo
    let email2: Email = String::from("bruno@exemplo.com").into();

    let usuario = Usuario {
        nome: String::from("Ana"),
        email: email1,
    };

    println!("{:?}", usuario);
}
```

### Exemplo 2: From para conversão de erros

Um dos usos mais poderosos de `From` é na conversão de erros com o operador `?`:

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

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

impl fmt::Display for AppErro {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> 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, "Validação: {}", msg),
        }
    }
}

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)
    }
}

// Agora o operador ? converte automaticamente!
fn ler_numero_do_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("Número negativo".into()));
    }
    Ok(numero)
}

fn main() {
    match ler_numero_do_arquivo("numero.txt") {
        Ok(n) => println!("Número: {}", n),
        Err(e) => eprintln!("Erro: {}", e),
    }
}
```

### Exemplo 3: Into em parâmetros de função genérica

Usar `Into<T>` como bound em parâmetros torna a API mais flexível:

```rust
#[derive(Debug)]
struct Mensagem {
    texto: String,
}

impl Mensagem {
    // Aceita qualquer coisa que possa virar String
    fn nova(texto: impl Into<String>) -> Self {
        Mensagem {
            texto: texto.into(),
        }
    }
}

fn saudacao(nome: impl Into<String>) -> String {
    format!("Olá, {}!", nome.into())
}

fn main() {
    // Funciona com &str
    let msg1 = Mensagem::nova("olá");

    // Funciona com String
    let msg2 = Mensagem::nova(String::from("mundo"));

    println!("{:?}", msg1);
    println!("{:?}", msg2);

    // A função aceita ambos os tipos
    println!("{}", saudacao("Ana"));
    println!("{}", saudacao(String::from("Bruno")));
}
```

### Exemplo 4: Construindo tipos a partir de tuplas

```rust
#[derive(Debug)]
struct Ponto {
    x: f64,
    y: f64,
}

impl From<(f64, f64)> for Ponto {
    fn from((x, y): (f64, f64)) -> Self {
        Ponto { x, y }
    }
}

impl From<[f64; 2]> for Ponto {
    fn from(arr: [f64; 2]) -> Self {
        Ponto { x: arr[0], y: arr[1] }
    }
}

impl From<Ponto> for (f64, f64) {
    fn from(p: Ponto) -> Self {
        (p.x, p.y)
    }
}

fn main() {
    let p1 = Ponto::from((3.0, 4.0));
    let p2: Ponto = [1.0, 2.0].into();

    println!("{:?}", p1); // Ponto { x: 3.0, y: 4.0 }
    println!("{:?}", p2); // Ponto { x: 1.0, y: 2.0 }

    let tupla: (f64, f64) = p1.into();
    println!("{:?}", tupla); // (3.0, 4.0)
}
```

### Exemplo 5: TryFrom para conversões que podem falhar

Quando a conversão pode falhar, use `TryFrom` em vez de `From`:

```rust
use std::convert::TryFrom;

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

impl TryFrom<i32> for Porcentagem {
    type Error = String;

    fn try_from(valor: i32) -> Result<Self, Self::Error> {
        if valor < 0 || valor > 100 {
            Err(format!("Valor {} fora do intervalo 0-100", valor))
        } else {
            Ok(Porcentagem(valor as u8))
        }
    }
}

fn main() {
    let p1 = Porcentagem::try_from(85);
    let p2 = Porcentagem::try_from(150);

    println!("{:?}", p1); // Ok(Porcentagem(85))
    println!("{:?}", p2); // Err("Valor 150 fora do intervalo 0-100")

    // Também funciona com .try_into()
    let p3: Result<Porcentagem, _> = 50i32.try_into();
    println!("{:?}", p3); // Ok(Porcentagem(50))
}
```

---

## Padrões e Boas Práticas

1. **Implemente `From`, não `Into`**: Sempre implemente `From<T> for U`. Você ganha `Into<U> for T` automaticamente via blanket impl.

2. **Use `Into<T>` em parâmetros**: Quando uma função aceita um tipo, use `impl Into<String>` ou `impl Into<T>` para tornar a API mais ergonômica.

3. **Conversões de erro com `From`**: Implemente `From<SubErro> for MeuErro` para que o operador `?` converta erros automaticamente.

4. **`From` deve ser infalível**: Se a conversão pode falhar, use `TryFrom` em vez de `From`. `From` é um contrato de que a conversão sempre terá sucesso.

5. **Não implemente `From` para si mesmo**: `From<T> for T` (identidade) já é implementado na biblioteca padrão.

6. **`String::from` vs `.to_string()`**: Ambos convertem `&str` para `String`. `String::from("texto")` usa `From`, enquanto `"texto".to_string()` usa `Display`. Ambos são idiomáticos.

7. **Conversões numéricas**: Para conversões entre tipos numéricos sem perda (como `i32` para `i64`), `From` já está implementado. Para conversões com possível perda, use `as` ou `TryFrom`.

---

## Veja Também

- [Display e Debug](/stdlib/display-debug/) — Display é necessário para formatar a saída de erros convertidos
- [Error Trait](/stdlib/error-trait/) — usa `From` extensivamente para conversão de erros
- [Clone e Copy](/stdlib/clone-copy/) — outro par de traits de conversão/cópia
- [Converter String para Número](/receitas/converter-string-numero/) — exemplo prático de conversão
- [Converter Erros](/receitas/converter-erros/) — padrões de conversão de erros com From
