---
title: "Pin\u003cP\u003e em Rust em 2026: Async, Unpin e Ergonomia"
url: "https://rustlang.com.br/stdlib/pin-module/"
markdown_url: "https://rustlang.com.br/stdlib/pin-module.MD"
description: "Guia pratico de Pin em Rust em 2026: por que Pin existe, Pin\u003cBox\u003cT\u003e\u003e, Pin\u003c\u0026mut T\u003e, Unpin, async/await, field projections e quando se preocupar com ergonomia."
date: "2026-05-22"
author: "Equipe Rust Brasil"
---

# Pin<P> em Rust em 2026: Async, Unpin e Ergonomia

Guia pratico de Pin em Rust em 2026: por que Pin existe, Pin<Box<T>>, Pin<&mut T>, Unpin, async/await, field projections e quando se preocupar com ergonomia.


## Visao Geral de Pin

`Pin<P>` e um wrapper que **impede que um valor seja movido na memoria**. Em Rust, valores podem ser movidos livremente — quando voce faz `let b = a;`, os bytes de `a` sao copiados para `b` e `a` e invalidado. Para a maioria dos tipos isso e inofensivo, mas para **structs auto-referenciais** (que contem ponteiros para si mesmas) um move invalidaria esses ponteiros internos.

O principal motivador para a existencia de `Pin` e o suporte a **async/await**. Futures geradas pelo compilador frequentemente contem referencias internas que apontam para outros campos da propria struct. Se essa struct fosse movida, os ponteiros internos apontariam para memoria invalida.

`Pin<P>` nao e magia — e um tipo que:
1. Envolve um ponteiro `P` (como `&mut T` ou `Box<T>`)
2. Restringe o acesso ao `&mut T` interno (para impedir `mem::swap` ou `mem::replace`)
3. Garante ao tipo `T` que ele nao sera movido

A trait `Unpin` marca tipos que **nao se importam em ser movidos**, mesmo quando "pinados". A grande maioria dos tipos e `Unpin`, e para eles `Pin` nao tem efeito pratico.

## O que mudou no radar de Pin em 2026

Pin continua sendo uma API de baixo nivel, mas voltou a aparecer em conversas de linguagem porque o projeto Rust esta trabalhando em ergonomia para tipos que precisam de enderecos estaveis. O ponto pratico para dev brasileiro nao e decorar todos os detalhes de RFC: e entender quando `Pin` faz parte da fronteira de uma biblioteca e quando ele deve ficar escondido atras de uma API simples.

Tres temas importam hoje:

1. **Ergonomia de Pin:** bibliotecas async e de sistemas querem reduzir a quantidade de `unsafe` e boilerplate quando um tipo pinned precisa expor campos internos.
2. **Field projections:** projetar um campo de uma struct pinned e dificil porque mover o campo errado quebra a garantia de endereco estavel. O desenho de linguagem busca tornar esse padrao menos manual.
3. **Rust de alto nivel:** `async fn` em traits, macros como `pin!` e runtimes maduros fazem com que a maioria dos devs use Pin indiretamente, sem escrever `unsafe`.

Em trabalho cotidiano, trate `Pin` como sinal de fronteira: se voce esta usando [Tokio](/ecossistema/tokio/), [Axum](/ecossistema/axum/), streams ou futures boxed, provavelmente so precisa entender o erro do compilador. Se esta escrevendo runtime, biblioteca async, wrapper FFI ou estrutura auto-referencial, precisa revisar as invariantes com muito mais cuidado.

### Resumo rapido para entrevistas e codigo real

| Pergunta | Resposta curta |
|---|---|
| `Pin` move o valor para outro lugar? | Nao. Ele restringe como voce acessa o valor para impedir moves futuros. |
| Todo `Pin<T>` impede move? | So quando o tipo interno nao implementa `Unpin`. Para tipos `Unpin`, `Pin` e praticamente transparente. |
| `Box::pin` sempre aloca? | Sim, porque coloca o valor no heap. Use quando precisa de ownership transferivel. |
| `pin!` aloca? | Nao. Ele pina um valor local na stack, util para escopos curtos. |
| Posso projetar campos pinned manualmente? | Pode, mas normalmente isso envolve API especializada ou `unsafe`. Prefira crates e padroes estabelecidos. |
| Quando aparece em vaga Rust? | Em async avancado, sistemas, networking, runtimes, FFI e bibliotecas de infraestrutura. |

---

## Tipos e Traits Principais

| Tipo/Trait | Descricao |
|---|---|
| `Pin<P>` | Wrapper que garante que o valor apontado nao sera movido |
| `Unpin` | Trait auto: tipo pode ser movido mesmo dentro de `Pin` |
| `pin!` macro | Cria um `Pin<&mut T>` na stack (estabilizada em Rust 1.68) |

### Metodos de Pin

| Metodo | Descricao |
|---|---|
| `Pin::new(ptr)` | Cria Pin (so para tipos Unpin) |
| `Pin::into_inner(pin)` | Extrai o ponteiro interno (so para Unpin) |
| `unsafe Pin::new_unchecked(ptr)` | Cria Pin para tipos !Unpin (unsafe) |
| `.as_ref()` | Converte `Pin<&mut T>` para `Pin<&T>` |
| `.as_mut()` | Reborrow de `Pin<&mut T>` |
| `.get_mut()` | Acessa `&mut T` (so para Unpin) |
| `unsafe .get_unchecked_mut()` | Acessa `&mut T` para !Unpin (unsafe) |

---

## Exemplos Praticos

### 1. Pin Basico com Tipos Unpin

Para tipos `Unpin` (a maioria), `Pin` e transparente — voce pode criar e usar livremente:

```rust
use std::pin::Pin;

fn main() {
    // i32 e Unpin, entao Pin nao restringe nada
    let mut valor = 42;
    let pin = Pin::new(&mut valor);

    // Podemos acessar o &mut normalmente via get_mut()
    *pin.get_mut() = 100;
    println!("Valor: {valor}"); // 100

    // Pin<Box<T>> para tipos Unpin
    let mut caixa = Box::pin(String::from("Ola"));
    println!("Pinned string: {}", caixa.as_ref().get_ref());

    // Podemos obter &mut String porque String e Unpin
    caixa.as_mut().get_mut().push_str(", mundo!");
    println!("Modificada: {}", caixa);

    // Vec, HashMap, i32, String... todos sao Unpin
    println!("i32 e Unpin? {}", std::mem::size_of::<i32>() >= 0); // sempre true
}
```

### 2. Por Que Pin Existe — O Problema de Structs Auto-Referenciais

```rust
use std::pin::Pin;
use std::marker::PhantomPinned;

// Struct auto-referencial: campo 'ptr' aponta para 'dados'
struct AutoRef {
    dados: String,
    ptr: *const String,
    _pin: PhantomPinned, // Torna o tipo !Unpin
}

impl AutoRef {
    fn new(texto: &str) -> Pin<Box<Self>> {
        let mut this = Box::new(AutoRef {
            dados: String::from(texto),
            ptr: std::ptr::null(),
            _pin: PhantomPinned,
        });

        // Agora apontamos ptr para dados
        let ptr_dados: *const String = &this.dados;
        // SAFETY: estamos inicializando o campo antes de pinar.
        // Apos Pin::from(box), o valor nao sera movido.
        unsafe {
            let mut_ref = Pin::get_unchecked_mut(Pin::as_mut(&mut Pin::from(
                // Precisamos usar um truque aqui
                Box::from_raw(Box::into_raw(this))
            )));
            mut_ref.ptr = ptr_dados;
            Pin::new_unchecked(Box::from_raw(
                mut_ref as *mut AutoRef
            ))
        }
    }

    fn dados_via_ptr(&self) -> &str {
        // SAFETY: ptr sempre aponta para dados, que e valido
        // enquanto AutoRef existir e nao for movido
        unsafe { &*self.ptr }
    }
}

fn main() {
    let pinned = AutoRef::new("dados importantes");
    println!("Direto: {}", pinned.dados);
    println!("Via ptr: {}", pinned.dados_via_ptr());

    // Nao podemos mover o valor para fora do Pin!
    // let movido = *pinned; // ERRO: nao implementa Unpin
}
```

### 3. Pin e Async/Await — O Caso de Uso Principal

```rust
use std::pin::Pin;
use std::future::Future;
use std::task::{Context, Poll};

// Uma Future simples que conta ate um numero
struct Contador {
    atual: u32,
    alvo: u32,
}

impl Contador {
    fn new(alvo: u32) -> Self {
        Contador { atual: 0, alvo }
    }
}

impl Future for Contador {
    type Output = u32;

    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32> {
        // Para tipos Unpin, podemos acessar &mut self normalmente
        self.atual += 1;

        if self.atual >= self.alvo {
            Poll::Ready(self.atual)
        } else {
            // Em um executor real, registrariamos um waker
            Poll::Pending
        }
    }
}

// Funcao que aceita qualquer Future pinado
fn tipo_da_future(_f: Pin<&dyn Future<Output = u32>>) {
    println!("Recebi uma future pinada");
}

fn main() {
    // Box::pin e a forma mais comum de pinar uma Future
    let future = Box::pin(Contador::new(5));
    tipo_da_future(future.as_ref());

    // Na pratica, voce usa async/await e o runtime faz o pinning
    // tokio::runtime::Runtime::new().unwrap().block_on(async {
    //     let resultado = minha_funcao_async().await;
    // });

    println!("Futures precisam ser pinadas para serem polled");
}
```

### 4. O Macro pin! para Pinning na Stack

```rust
use std::pin::pin;
use std::future::Future;
use std::task::{Context, Poll};

struct FutureSimples;

impl Future for FutureSimples {
    type Output = &'static str;

    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
        Poll::Ready("concluido!")
    }
}

// pin! permite pinar na stack sem Box (zero alocacao)
fn demonstrar_pin_macro() {
    // Sem o macro: precisaria de Box::pin (aloca no heap)
    let _heap_pinned = Box::pin(FutureSimples);

    // Com o macro: pinado na stack (zero custo)
    let stack_pinned = pin!(FutureSimples);

    // stack_pinned e do tipo Pin<&mut FutureSimples>
    let _ref_pin: Pin<&FutureSimples> = stack_pinned.as_ref();

    println!("pin! macro evita alocacao heap");
}

// pin! e especialmente util com futures em funcoes sync
fn executar_future_simples() {
    let mut future = pin!(async {
        let a = 1;
        let b = 2;
        a + b
    });

    // Para demonstracao: em codigo real, use um executor async
    let _pinned_ref: Pin<&mut _> = future.as_mut();
    println!("Future pinada na stack com sucesso");
}

fn main() {
    demonstrar_pin_macro();
    executar_future_simples();
}
```

### 5. Padroes com Pin em APIs Async

```rust
use std::pin::Pin;
use std::future::Future;

// Tipo alias comum para futures boxed (trait objects)
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

// Funcao que retorna uma future boxed (util para trait methods)
fn buscar_dados(url: String) -> BoxFuture<'static, Result<String, String>> {
    Box::pin(async move {
        // Simula uma operacao assincrona
        if url.starts_with("http") {
            Ok(format!("Dados de {url}"))
        } else {
            Err(format!("URL invalida: {url}"))
        }
    })
}

// Trait com metodo async (padrao pre-async-in-traits)
trait Servico {
    fn processar(&self, entrada: String) -> BoxFuture<'_, String>;
}

struct MeuServico;

impl Servico for MeuServico {
    fn processar(&self, entrada: String) -> BoxFuture<'_, String> {
        Box::pin(async move {
            format!("Processado: {entrada}")
        })
    }
}

// Com async fn em traits (Rust 1.75+), Pin e menos necessario:
// trait ServicoModerno {
//     async fn processar(&self, entrada: String) -> String;
// }

fn main() {
    let _future = buscar_dados("https://exemplo.com".into());
    let servico = MeuServico;
    let _resultado = servico.processar("dados".into());

    println!("BoxFuture = Pin<Box<dyn Future<...>>>");
    println!("E o padrao para futures como trait objects");
}
```

---

## Padroes Comuns

### Quando Voce Encontra Pin

Na pratica, voce encontra `Pin` em tres contextos:

1. **Implementando `Future` manualmente** — o metodo `poll` recebe `self: Pin<&mut Self>`
2. **Retornando futures como trait objects** — `Pin<Box<dyn Future<Output = T>>>`
3. **Usando APIs de streaming** — `Stream::poll_next` tambem recebe `Pin<&mut Self>`

### Regra Pratica de Unpin

Se seu tipo:
- Contem apenas tipos primitivos, `String`, `Vec`, `Box`, etc. -> e `Unpin` automaticamente
- Contem `PhantomPinned` -> e `!Unpin`
- E uma future gerada por `async` -> e `!Unpin`

### Pin<Box<T>> vs pin! macro

| Abordagem | Alocacao | Quando usar |
|---|---|---|
| `Box::pin(valor)` | Heap | Quando precisa de ownership transferivel |
| `pin!(valor)` | Stack | Quando o pinned value e local |

---

## Quando Usar (e Quando Nao Usar)

**Use `Pin` quando:**
- Implementar a trait `Future` manualmente
- Retornar futures como trait objects (`BoxFuture`)
- Criar tipos auto-referenciais (raro, mas necessario)
- Trabalhar com APIs que requerem `Pin` (como `tokio::select!`)

**Nao use `Pin` quando:**
- Todos os seus tipos forem `Unpin` (a maioria e!)
- Puder usar `async`/`await` normalmente sem implementar `Future` manualmente
- Puder usar `async fn` em traits (Rust 1.75+)
- Nao estiver trabalhando com futures ou structs auto-referenciais

**Dica:** Em codigo async cotidiano, voce raramente precisa interagir com `Pin` diretamente. O compilador e os runtimes (tokio, async-std) cuidam do pinning. Voce so precisa entender `Pin` quando estiver escrevendo abstractions de baixo nivel.

**Performance:** `Pin` tem custo zero — e apenas um wrapper que restringe a API em tempo de compilacao. Nao adiciona nenhum overhead em runtime.

---

## Veja Tambem

- [Async/Await em Profundidade](/artigos/async-await-profundidade/) — como Pin se integra ao sistema async
- [Modulo std::marker](/stdlib/marker-module/) — trait `Unpin` e `PhantomPinned`
- [Modulo std::mem](/stdlib/mem-module/) — `swap` e `replace` que Pin restringe
- [Modulo std::ptr](/stdlib/ptr-module/) — ponteiros raw usados em structs auto-referenciais
- [Documentacao oficial — std::pin](https://doc.rust-lang.org/std/pin/index.html)
