---
title: "Future is Not Send — Como Resolver no Rust"
url: "https://rustlang.com.br/erros/future-not-send/"
markdown_url: "https://rustlang.com.br/erros/future-not-send.MD"
description: "Como resolver o erro 'future is not Send' no Rust async. Entenda por que Rc, RefCell e MutexGuard causam este erro e aprenda a usar Arc, Mutex e técnicas corretas."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Future is Not Send — Como Resolver no Rust

Como resolver o erro 'future is not Send' no Rust async. Entenda por que Rc, RefCell e MutexGuard causam este erro e aprenda a usar Arc, Mutex e técnicas corretas.


# Future is Not Send

O erro **"future is not Send"** é um dos mais confusos da programação assíncrona em Rust. Ele ocorre quando você tenta enviar um future para outra thread (como ao usar `tokio::spawn`), mas o future contém tipos que não são seguros para compartilhar entre threads.

## A Mensagem de Erro

```
error: future cannot be sent between threads safely
   --> src/main.rs:10:5
    |
10  |     tokio::spawn(async {
    |     ^^^^^^^^^^^^ future created by async block is not `Send`
    |
    = help: within `{async block}`, the trait `Send` is not implemented for `Rc<String>`
note: future is not `Send` as this value is used across an await
   --> src/main.rs:12:9
    |
11  |     let dados = Rc::new(String::from("olá"));
    |         ----- has type `Rc<String>` which is not `Send`
12  |     alguma_funcao().await;
    |                    ^^^^^^ await occurs here, with `dados` maybe used later
```

## O Que Significa

No Rust, o trait `Send` indica que um tipo pode ser transferido com segurança entre threads. Quando você usa `tokio::spawn` (ou equivalentes em outros runtimes async), o future é movido para uma thread de trabalho. Para isso ser seguro, **tudo** dentro do future precisa ser `Send`.

Tipos que **NÃO** são `Send`:

| Tipo | Por que não é Send | Alternativa Send |
|---|---|---|
| `Rc<T>` | Contagem de referência não-atômica | `Arc<T>` |
| `RefCell<T>` | Empréstimo verificado em runtime, não thread-safe | `Mutex<T>` ou `RwLock<T>` |
| `Cell<T>` | Mutabilidade interior não thread-safe | `AtomicXxx` ou `Mutex<T>` |
| `MutexGuard<T>` | Lock guard mantido através de `.await` | Soltar guard antes do await |
| Ponteiros raw `*const T` / `*mut T` | Sem garantias de segurança | Encapsular em tipo Send |

O problema não é apenas **ter** esses tipos, mas **mantê-los vivos através de um `.await`**. O compilador precisa garantir que, se o runtime pausar o future no `.await` e continuar em outra thread, todos os dados serão válidos.

## Código com Erro

### Rc através de await

```rust
use std::rc::Rc;

#[tokio::main]
async fn main() {
    tokio::spawn(async {
        let dados = Rc::new(String::from("compartilhado"));
        fazer_algo().await;  // ERRO: `Rc` vivo através do await
        println!("{}", dados);
    });
}

async fn fazer_algo() {
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
```

### MutexGuard através de await

```rust
use std::sync::Mutex;

#[tokio::main]
async fn main() {
    let dados = std::sync::Arc::new(Mutex::new(vec![1, 2, 3]));

    tokio::spawn(async move {
        let guard = dados.lock().unwrap();
        // ERRO: MutexGuard mantido através do await
        fazer_algo().await;
        println!("{:?}", guard);
    });
}
```

### RefCell em contexto async

```rust
use std::cell::RefCell;

#[tokio::main]
async fn main() {
    tokio::spawn(async {
        let celula = RefCell::new(42);
        fazer_algo().await;  // ERRO
        println!("{}", celula.borrow());
    });
}
```

## Como Resolver

### Solução 1: Substituir Rc por Arc

```rust
use std::sync::Arc;

#[tokio::main]
async fn main() {
    tokio::spawn(async {
        let dados = Arc::new(String::from("compartilhado"));
        fazer_algo().await;
        println!("{}", dados);  // Funciona! Arc é Send
    });
}

async fn fazer_algo() {
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
```

### Solução 2: Substituir RefCell por Mutex/RwLock

```rust
use std::sync::{Arc, Mutex};

#[tokio::main]
async fn main() {
    let dados = Arc::new(Mutex::new(vec![1, 2, 3]));

    let dados_clone = Arc::clone(&dados);
    tokio::spawn(async move {
        dados_clone.lock().unwrap().push(4);
        fazer_algo().await;
        println!("{:?}", dados_clone.lock().unwrap());
    });
}
```

Para async, prefira `tokio::sync::Mutex` que não bloqueia a thread:

```rust
use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let dados = Arc::new(Mutex::new(vec![1, 2, 3]));

    let dados_clone = Arc::clone(&dados);
    tokio::spawn(async move {
        {
            let mut guard = dados_clone.lock().await;
            guard.push(4);
        } // guard liberado antes do await

        fazer_algo().await;
        println!("{:?}", dados_clone.lock().await);
    });
}
```

### Solução 3: Soltar o Guard Antes do await

Se o tipo não-Send é temporário, garanta que ele não cruza o `.await`:

```rust
use std::sync::{Arc, Mutex};

#[tokio::main]
async fn main() {
    let dados = Arc::new(Mutex::new(vec![1, 2, 3]));

    let dados_clone = Arc::clone(&dados);
    tokio::spawn(async move {
        // Escopo limita o guard
        {
            let mut guard = dados_clone.lock().unwrap();
            guard.push(4);
        } // guard destruído aqui — antes do await

        fazer_algo().await;  // OK: nenhum tipo não-Send vivo

        let guard = dados_clone.lock().unwrap();
        println!("{:?}", *guard);
    });
}
```

### Solução 4: Usar `spawn_local` para Tasks Não-Send

Se você realmente precisa de tipos não-Send, use `spawn_local` (executa na mesma thread):

```rust
use std::rc::Rc;
use tokio::task;

#[tokio::main]
async fn main() {
    let local = task::LocalSet::new();

    local.run_until(async {
        task::spawn_local(async {
            let dados = Rc::new(String::from("local"));
            fazer_algo().await;
            println!("{}", dados);  // OK com spawn_local
        }).await.unwrap();
    }).await;
}
```

### Solução 5: Extrair a Parte Não-Send para uma Closure

```rust
use std::sync::Arc;

#[tokio::main]
async fn main() {
    let dados = Arc::new(std::sync::Mutex::new(0));

    let dados_clone = Arc::clone(&dados);
    tokio::spawn(async move {
        // Processa antes do await
        let valor = {
            let guard = dados_clone.lock().unwrap();
            *guard // Copia o valor, guard destruído no fim do bloco
        };

        fazer_algo().await;
        println!("Valor: {}", valor);
    });
}

async fn fazer_algo() {
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
```

## Regra de Ouro

Se o tipo cruza um `.await` e será usado por `tokio::spawn`:
- `Rc` -> `Arc`
- `RefCell` -> `tokio::sync::Mutex` ou `tokio::sync::RwLock`
- `Cell` -> `std::sync::atomic::AtomicXxx`
- `MutexGuard` -> solte antes do `.await`

## Veja Também

- [E0728: await Usado Fora de Função Async](/erros/e0728-await-fora-async/)
- [E0277: Trait Não Implementado](/erros/e0277-trait-nao-implementado/)
- [Tutorial de Tratamento de Erros](/tutoriais/tratamento-de-erros/)
- [Glossário Rust](/glossario/)
