---
title: "Rust 1.86 e 1.87: Trait Upcasting, Pipes e Novidades — 2026"
url: "https://rustlang.com.br/blog/rust-1-86-1-87-trait-upcasting-novidades-2026/"
markdown_url: "https://rustlang.com.br/blog/rust-1-86-1-87-trait-upcasting-novidades-2026.MD"
description: "Conheça as novidades do Rust 1.86 e 1.87: trait upcasting, get_disjoint_mut, io::pipe, intrínsecos seguros e muito mais com exemplos práticos."
date: "2026-04-21"
author: "Equipe Rust Brasil"
---

# Rust 1.86 e 1.87: Trait Upcasting, Pipes e Novidades — 2026

Conheça as novidades do Rust 1.86 e 1.87: trait upcasting, get_disjoint_mut, io::pipe, intrínsecos seguros e muito mais com exemplos práticos.


## Introdução

As versões 1.86 e 1.87 do Rust trouxeram recursos que mudam a forma como escrevemos código no dia a dia. Desde o esperado **trait upcasting** — que simplifica drasticamente o trabalho com trait objects — até **pipes anônimos** na stdlib e a possibilidade de chamar intrínsecos de arquitetura em código seguro, essas releases consolidam a missão do Rust: oferecer poder sem sacrificar segurança.

Neste artigo, vamos explorar cada recurso com exemplos de código prontos para você testar. Se você ainda não atualizou, basta rodar:

```bash
rustup update stable
```

Se quiser entender como instalar o Rust do zero, confira nosso [guia de instalação](/instalacao/rustup/).

---

## Rust 1.86: Os Destaques

### Trait Upcasting

O recurso mais aguardado do Rust 1.86 é, sem dúvida, o **trait upcasting**. Antes desta versão, converter uma referência `&dyn Trait` para `&dyn Supertrait` exigia gambiarras manuais — métodos auxiliares como `fn as_supertrait(&self) -> &dyn Supertrait`. Agora, a conversão é automática:

```rust
trait Animal {
    fn nome(&self) -> &str;
}

trait Cachorro: Animal {
    fn latir(&self) -> String;
}

struct Labrador {
    nome: String,
}

impl Animal for Labrador {
    fn nome(&self) -> &str {
        &self.nome
    }
}

impl Cachorro for Labrador {
    fn latir(&self) -> String {
        format!("{} diz: Au au!", self.nome())
    }
}

fn imprimir_animal(animal: &dyn Animal) {
    println!("Animal: {}", animal.nome());
}

fn main() {
    let rex: Box<dyn Cachorro> = Box::new(Labrador {
        nome: "Rex".to_string(),
    });

    // Antes do 1.86: erro de compilação!
    // Agora: conversão automática de &dyn Cachorro → &dyn Animal
    imprimir_animal(&*rex);

    // Também funciona com Arc e Rc
    let rex_arc: std::sync::Arc<dyn Cachorro> = std::sync::Arc::new(Labrador {
        nome: "Rex".to_string(),
    });
    let animal_arc: std::sync::Arc<dyn Animal> = rex_arc;
    println!("Via Arc: {}", animal_arc.nome());
}
```

Se você trabalha com [trait objects e generics](/artigos/trait-objects-vs-generics/), esse recurso elimina uma enorme fonte de boilerplate. Combinado com [smart pointers](/artigos/smart-pointers/) como `Arc` e `Rc`, o trait upcasting torna padrões de polimorfismo dinâmico muito mais ergonômicos.

Para um guia completo sobre traits, confira nosso [artigo sobre traits em Rust](/blog/traits-rust-guia-completo-exemplos/).

### get_disjoint_mut: Múltiplas Referências Mutáveis Seguras

Um dos problemas clássicos do Rust é acessar dois elementos mutáveis de um slice ou [HashMap](/stdlib/hashmap/) ao mesmo tempo. O compilador impede porque não consegue provar em tempo de compilação que os índices são diferentes. O novo método `get_disjoint_mut` resolve isso:

```rust
fn main() {
    let mut valores = vec![10, 20, 30, 40, 50];

    // Antes: split_at_mut ou unsafe
    // Agora: get_disjoint_mut!
    if let Ok([a, c]) = valores.get_disjoint_mut([0, 2]) {
        *a += 100;
        *c += 200;
        println!("a={}, c={}", a, c); // a=110, c=230
    }

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

Isso funciona também com `HashMap`:

```rust
use std::collections::HashMap;

fn main() {
    let mut mapa = HashMap::new();
    mapa.insert("x", 1);
    mapa.insert("y", 2);
    mapa.insert("z", 3);

    if let Ok([vx, vz]) = mapa.get_disjoint_mut(["x", "z"]) {
        *vx *= 10;
        *vz *= 10;
    }

    println!("{:?}", mapa); // {"x": 10, "y": 2, "z": 30}
}
```

Se você usa [Vec](/stdlib/vec/) ou [HashMap](/stdlib/hashmap/) no dia a dia, esse método elimina a necessidade de `unsafe` ou `split_at_mut` para o caso mais comum de acesso simultâneo.

### #[target_feature] em Funções Seguras

Antes do 1.86, usar `#[target_feature]` exigia que a função fosse `unsafe`. Agora, funções seguras podem ser marcadas com features de CPU específicas:

```rust
#[target_feature(enable = "avx2")]
fn soma_vetorial_avx2(a: &[f32; 8], b: &[f32; 8]) -> [f32; 8] {
    let mut resultado = [0.0f32; 8];
    for i in 0..8 {
        resultado[i] = a[i] + b[i];
    }
    resultado
}

fn main() {
    if std::is_x86_feature_detected!("avx2") {
        let a = [1.0; 8];
        let b = [2.0; 8];
        let resultado = soma_vetorial_avx2(&a, &b);
        println!("Resultado: {:?}", resultado);
    } else {
        println!("AVX2 não disponível neste processador");
    }
}
```

Para quem trabalha com [otimização de performance](/artigos/otimizacao-performance/), isso reduz a quantidade de `unsafe` no código sem perder controle sobre instruções SIMD.

### Asserções de Ponteiro Nulo em Debug

O compilador agora insere verificações automáticas em modo debug para detectar desreferência de ponteiros nulos antes de qualquer leitura ou escrita de tamanho diferente de zero. Se você usa [ponteiros e unsafe](/artigos/unsafe-rust/), isso ajuda a pegar bugs mais cedo durante o desenvolvimento.

---

## Rust 1.87: Os Destaques

### io::pipe — Pipes Anônimos na Stdlib

Finalmente temos pipes nativos na biblioteca padrão! O `std::io::pipe()` cria um par leitor/escritor que funciona tanto no Unix quanto no Windows:

```rust
use std::io::{self, Read, Write};
use std::thread;

fn main() -> io::Result<()> {
    let (mut reader, mut writer) = io::pipe()?;

    let handle = thread::spawn(move || {
        writer.write_all(b"Olá do Rust 1.87!").unwrap();
        writer.write_all(b" Pipes nativos!").unwrap();
        // writer é dropado aqui, sinalizando EOF
    });

    let mut buffer = String::new();
    reader.read_to_string(&mut buffer)?;
    println!("Recebido: {}", buffer);

    handle.join().unwrap();
    Ok(())
}
```

Para quem trabalha com [threads](/stdlib/thread/) e [canais de comunicação](/stdlib/channels/), `io::pipe` oferece uma alternativa baseada em I/O que se integra bem com processos filhos e redirects de stdin/stdout.

### Intrínsecos de Arquitetura Seguros

A maioria dos intrínsecos em `std::arch` agora pode ser chamada sem `unsafe` quando as features de CPU apropriadas estão habilitadas. Isso é uma revolução para código SIMD:

```rust
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse4.1")]
fn soma_inteiros_sse(a: &[i32; 4], b: &[i32; 4]) -> [i32; 4] {
    use std::arch::x86_64::*;

    // Antes: unsafe { _mm_add_epi32(...) }
    // Agora: chamada segura!
    let va = unsafe { _mm_loadu_si128(a.as_ptr() as *const _) };
    let vb = unsafe { _mm_loadu_si128(b.as_ptr() as *const _) };
    let resultado = unsafe { _mm_add_epi32(va, vb) };

    let mut out = [0i32; 4];
    unsafe { _mm_storeu_si128(out.as_mut_ptr() as *mut _, resultado) };
    out
}
```

### Vec::extract_if — Filtrar e Remover Elementos

O método `extract_if` permite filtrar e remover elementos de um [Vec](/stdlib/vec/) em uma única passagem, retornando os elementos removidos como iterador:

```rust
fn main() {
    let mut numeros = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // Extrai todos os pares (remove do vec e retorna como iterador)
    let pares: Vec<i32> = numeros.extract_if(.., |x| *x % 2 == 0).collect();

    println!("Pares removidos: {:?}", pares);    // [2, 4, 6, 8, 10]
    println!("Ímpares restantes: {:?}", numeros); // [1, 3, 5, 7, 9]
}
```

Antes, você precisava de `retain` (que descarta os removidos) ou loops manuais. Agora, com `extract_if`, você mantém ambos os conjuntos. Muito útil para [filtrar coleções](/receitas/filtrar-vetor/) em processamento de dados.

### String::extend_from_within

Novo método para duplicar partes de uma [String](/stdlib/string/) sem alocar strings intermediárias:

```rust
fn main() {
    let mut texto = String::from("Rust");
    texto.extend_from_within(..);
    println!("{}", texto); // "RustRust"

    let mut saudacao = String::from("Olá, mundo!");
    saudacao.extend_from_within(0..4);
    println!("{}", saudacao); // "Olá, mundo!Olá,"
}
```

---

## Qual Versão Usar?

Se você está começando agora, use sempre a versão estável mais recente. Nosso guia [Como Aprender Rust em 2026](/blog/como-aprender-rust-2026/) tem o caminho completo. Para atualizar:

```bash
rustup update stable
rustc --version
```

## Resumo das Novidades

| Recurso | Versão | Impacto |
|---------|--------|---------|
| Trait upcasting | 1.86 | Polimorfismo dinâmico mais ergonômico |
| `get_disjoint_mut` | 1.86 | Acesso mutável simultâneo seguro |
| `#[target_feature]` safe | 1.86 | Menos `unsafe` em código SIMD |
| Null pointer assertions | 1.86 | Debug mais seguro |
| `io::pipe` | 1.87 | Pipes nativos na stdlib |
| Safe arch intrinsics | 1.87 | SIMD sem `unsafe` desnecessário |
| `Vec::extract_if` | 1.87 | Filtrar + remover em uma passagem |
| `String::extend_from_within` | 1.87 | Duplicação eficiente de substrings |

## Leia Também

- [Rust 1.94: Novidades e Recursos Estabilizados](/blog/rust-1-94-novidades-array-windows-2026/) — mais novidades recentes
- [Traits em Rust: Guia Completo](/blog/traits-rust-guia-completo-exemplos/) — fundamentos de traits
- [Tratamento de Erros com thiserror e anyhow](/blog/tratamento-erros-rust-thiserror-anyhow/) — boas práticas de error handling
- [Testes em Rust: Estratégias e Boas Práticas](/blog/testes-rust-estrategias-boas-praticas-2026/) — como testar seu código
- [Cargo Workspaces: Organizando Projetos Grandes em Rust](/blog/cargo-workspaces-monorepos-rust-2026/) — gerenciando monorepos

Se você vem de outra linguagem, confira também como Rust se compara: <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go</a>, <a href="https://python.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">Python</a>, <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin</a> e <a href="https://ziglang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'ziglang.com.br' })">Zig</a> são linguagens que frequentemente aparecem em comparações com Rust.
