---
title: "cargo-expand: Debug de Macros Rust | Rust Brasil"
url: "https://rustlang.com.br/blog/cargo-expand-macros-rust-debug-2026/"
markdown_url: "https://rustlang.com.br/blog/cargo-expand-macros-rust-debug-2026.MD"
description: "Use cargo-expand para ver macros Rust expandidas: derive, serde, clap, proc-macros, filtros por item e fluxo de debug no dia a dia e na CI de bibliotecas."
date: "2026-08-18"
author: "Equipe Rust Brasil"
---

# cargo-expand: Debug de Macros Rust | Rust Brasil

Use cargo-expand para ver macros Rust expandidas: derive, serde, clap, proc-macros, filtros por item e fluxo de debug no dia a dia e na CI de bibliotecas.


**O `cargo-expand` é a ferramenta certa quando uma macro Rust gera código que você precisa enxergar de verdade — derive de Serde, parser de Clap, erro customizado com `thiserror`, ou a proc-macro que sua biblioteca publica.** Instale com `cargo install cargo-expand --locked`, rode `cargo expand` na raiz do crate e trate o dump como o primeiro passo para entender o que o compilador está compilando. Em bibliotecas, SDKs e crates com muitos derives, isso costuma encurtar debugs que o editor sozinho não fecha.

Este guia mostra o que o `cargo-expand` resolve, como filtrar por módulo e item, como usá-lo com [Serde](/ecossistema/serde/), [Clap](/ecossistema/clap/), macros e proc-macros, como combinar a inspeção com [rust-analyzer](/blog/rust-analyzer-guia-configuracao-2026/), [cargo-llvm-lines](/blog/cargo-llvm-lines-monomorfizacao-rust-2026/) e [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/), e quais armadilhas geram dumps enormes ou conclusões erradas.

## Resposta rápida: o fluxo recomendado

| Etapa | Comando ou configuração | Objetivo |
|---|---|---|
| Instalar | `cargo install cargo-expand --locked` | Disponibilizar o subcomando |
| Dump completo | `cargo expand` | Ver a expansão do crate atual |
| Filtrar módulo | `cargo expand caminho::do::modulo` | Reduzir ruído |
| Biblioteca | `cargo expand --lib` | Focar no target lib |
| Binário | `cargo expand --bin nome` | Expandir um binário específico |
| Teste | `cargo expand --test nome_do_teste` | Inspecionar macros em testes |
| Diff local | salvar saída e comparar versões | Detectar regressão de geração |

Antes de automatizar dumps em CI crítica, confira `cargo expand --help` e a documentação atual. A ferramenta e as flags do compilador evoluem; fixe a versão se a saída for usada em revisão formal.

## Por que macros Rust escondem o código real

Macros são o mecanismo que permite APIs ergonômicas em Rust:

- `#[derive(Serialize, Deserialize)]` em modelos de API;
- `#[derive(Parser)]` em CLIs com Clap;
- `#[derive(Error)]` com thiserror;
- macros declarativas de DSL interna;
- proc-macros que geram builders, clients e bindings.

O ganho de ergonomia tem um custo cognitivo. Quando o erro aponta para uma linha gerada, a mensagem pode citar tipos, traits ou lifetimes que não existem no arquivo que você editou. O [rust-analyzer](/blog/rust-analyzer-guia-configuracao-2026/) ajuda a expandir no editor, mas dumps longos, diffs entre versões e revisão assíncrona pedem texto versionável.

Cenários típicos em que a expansão paga o tempo investido:

1. o derive de Serde gera um `Visitor` que falha em um caso específico;
2. o Clap produz flags e help inesperados;
3. uma proc-macro emite `unsafe` ou imports que você não previa;
4. o código compila no seu laptop e quebra no consumidor com features diferentes;
5. a monomorphization de um derive explode o tempo de build ou o tamanho do binário;
6. o erro menciona um trait bound gerado que você precisa satisfazer manualmente.

O `cargo-expand` transforma “acho que a macro fez X” em “aqui está o código gerado”.

## O que é cargo-expand

O `cargo-expand` é um subcomando Cargo que orquestra a expansão de macros e imprime o resultado em Rust pretty-printed. Em termos práticos, ele aproxima o fluxo de “mostrar o código depois das macros” sem exigir que você memorize a invocação bruta do `rustc` a cada investigação.

Ele não é um formatador, não substitui testes e não prova corretude. É uma lente. Você usa a lente para:

- confirmar se a macro gerou o `impl` esperado;
- localizar o trecho responsável por um erro;
- comparar duas versões da mesma macro;
- ensinar ou documentar o efeito de um derive;
- auditar o volume de código gerado antes de medir com outras ferramentas.

Para o panorama mais amplo de macros declarativas e procedurais, combine este guia com o artigo [Macros em Rust](/blog/macros-rust-declarativas-procedurais-2026/) e a visão geral de [ferramentas essenciais do Cargo](/artigos/cargo-ferramentas-essenciais/).

## Instalando e primeiros comandos

```bash
cargo install cargo-expand --locked
rustup component add rustfmt --toolchain nightly
cargo expand --help
```

A expansão completa normalmente depende de nightly. Um padrão saudável em times brasileiros que publicam crates é:

- desenvolver e testar em **stable**;
- inspecionar expansão em **nightly** pontual;
- documentar no README qual toolchain usar para `cargo expand`.

Fluxo mínimo em um crate de biblioteca:

```bash
cd meu-crate
cargo expand --lib
```

Fluxo mínimo em um binário:

```bash
cargo expand --bin app
```

Se a saída for gigante, não role o terminal sem filtro. Reduza o escopo:

```bash
cargo expand models
cargo expand models::usuario
cargo expand --lib cli::args
```

Salve dumps relevantes quando for comparar:

```bash
cargo expand --lib models > /tmp/models-before.rs
# altere a macro, a feature ou a versão do derive
cargo expand --lib models > /tmp/models-after.rs
diff -u /tmp/models-before.rs /tmp/models-after.rs | less
```

## Filtrando ruído: módulo, item e target certos

A maior falha de uso do `cargo-expand` é pedir o dump do mundo inteiro. Workspaces com Axum, SQLx, Serde e dezenas de módulos geram milhares de linhas. Prefira:

1. escolher o **target** (`--lib`, `--bin`, `--test`, `--example`);
2. escolher o **caminho** do módulo ou item;
3. só então ampliar o escopo se o trecho não aparecer.

Exemplos úteis:

```bash
# só a lib
cargo expand --lib

# módulo de domínio
cargo expand --lib domain::pedido

# argumentos de CLI
cargo expand --bin api cli

# macros usadas em teste de integração
cargo expand --test http_contrato
```

Se o item não aparecer, confirme:

- o módulo está `mod` visível no target escolhido;
- a feature que habilita o módulo está ativa;
- você não está expandindo o pacote errado em um workspace.

Em workspaces, seja explícito:

```bash
cargo expand -p minha_lib --lib
cargo expand -p minha_cli --bin minha_cli
```

Esse cuidado combina bem com [Cargo workspaces](/blog/cargo-workspaces-monorepos-rust-2026/) e com matrizes de features via [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/).

## Serde, Clap e derives do dia a dia

### Serde

Modelos com `Serialize`/`Deserialize` são o caso de uso mais comum. Quando um payload JSON falha de forma opaca, expanda o módulo do modelo e procure o `Visitor`, os field names e os `#[serde(...)]` efetivos.

```rust
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Usuario {
    pub id: uuid::Uuid,
    pub nome_completo: String,
    #[serde(default)]
    pub ativo: bool,
}
```

```bash
cargo expand --lib models::usuario
```

Checklist rápido na saída:

- os nomes serializados batem com a API (`nomeCompleto` vs `nome_completo`);
- campos com `default`, `skip_serializing_if` e `flatten` aparecem como esperado;
- enums com `tag`/`content` geraram as variantes corretas;
- tipos newtype não introduziram wrapper surpresa.

Para o fluxo de API HTTP, conecte a inspeção com [Serde](/ecossistema/serde/), [Axum](/ecossistema/axum/) e o guia de [validação de dados](/blog/rust-validacao-dados-validator-garde-serde-2026/).

### Clap

CLIs com `#[derive(Parser)]` escondem parsing, help e env vars no código gerado. Se uma flag não aparece, se o default está errado ou se o help ficou inconsistente, expanda o módulo de argumentos.

```bash
cargo expand --bin minha_cli cli::args
```

Verifique na expansão:

- nomes longos/curtos das flags;
- valores default e `env`;
- subcomandos e enums de comando;
- obrigatoriedade de argumentos posicionais.

Combine com a página de [Clap](/ecossistema/clap/) e com o hábito de testar a CLI de ponta a ponta — expansão explica o parser; testes confirmam o comportamento.

### thiserror e anyhow

Derives de erro geram `Display`, `From` e source chaining. Quando a mensagem formatada ou a conversão entre erros não bate, expanda o módulo de erros antes de culpar o runtime.

```bash
cargo expand --lib error
```

Depois valide o comportamento com testes e, se necessário, revise o guia de [tratamento de erros com thiserror e anyhow](/blog/tratamento-erros-rust-thiserror-anyhow/).

## Proc-macros: o que inspecionar de verdade

Se você mantém uma proc-macro, o `cargo-expand` é parte do ciclo de desenvolvimento, não um luxo. Fluxo recomendado:

1. escreva um crate de exemplo mínimo que usa a macro;
2. expanda esse exemplo;
3. compare a saída com o contrato público documentado;
4. adicione testes de snapshot ou asserts sobre a expansão quando a estabilidade da API gerada importar;
5. rode a matriz de features com [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/) para garantir que a macro não depende de um conjunto mágico de flags.

Pontos de atenção na saída gerada:

- imports absolutos vs relativos;
- higiene de identificadores;
- emissão acidental de `unsafe`;
- bounds de trait implícitos demais;
- código que só compila com features internas do workspace.

Não transforme o dump em único teste. Expansão mostra estrutura; testes de integração mostram comportamento.

## Relação com rust-analyzer, llvm-lines e bloat

| Ferramenta | Pergunta que responde | Quando usar |
|---|---|---|
| rust-analyzer | o que esta macro gera aqui no cursor? | exploração rápida no editor |
| cargo-expand | qual é o código expandido completo deste target/módulo? | debug profundo, diff, review |
| cargo-llvm-lines | quanto código monomorphizado isso produz? | custo de compilação |
| cargo-bloat | o que inchou o binário? | tamanho de release |
| Criterion | a mudança ficou mais rápida? | performance runtime |

Sequência pragmática:

1. falhou a compilação ou o comportamento ficou estranho → `cargo expand` no módulo suspeito;
2. a expansão revela código repetitivo enorme → meça com [cargo-llvm-lines](/blog/cargo-llvm-lines-monomorfizacao-rust-2026/);
3. o release ficou pesado → inspecione com [cargo-bloat](/blog/cargo-bloat-reduzir-tamanho-binario-rust-2026/);
4. a hipótese de performance for clara → valide com [Criterion](/ecossistema/criterion/) ou com o guia de [profiling em produção](/blog/rust-profiling-performance-producao-2026/).

A expansão sozinha não autoriza micro-otimização. Ela só evita otimizar no escuro.

## Features, workspaces e dumps reproduzíveis

Macros frequentemente dependem de features. Expanda com as mesmas flags que o bug reproduz:

```bash
cargo expand --lib --features serde-full
cargo expand --lib --no-default-features --features alloc
```

Em workspaces, declare o pacote:

```bash
cargo expand -p sdk_core --lib types
cargo expand -p sdk_cli --bin sdk --features unstable
```

Boas práticas para dumps compartilhados em pull request:

- fixe a versão do `cargo-expand`;
- documente toolchain nightly usada;
- filtre o módulo mínimo que demonstra o problema;
- evite colar 5.000 linhas no GitHub sem contexto;
- se o dump for artefato de CI, publique como artifact, não como comentário gigante.

Se a macro só quebra em uma combinação rara de features, a matriz do [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/) encontra o cenário; o `cargo-expand` explica o cenário.

## Armadilhas comuns

1. **Expandir o crate inteiro sem filtro.** Gera ruído, esconde o item útil e consome tempo.
2. **Misturar target.** Expandir `--lib` quando o bug está no `--bin` ou no `--test`.
3. **Ignorar features.** A expansão sem a feature ofensora “prova” o que não existe no bug real.
4. **Tratar nightly como toolchain de produção.** Use nightly para inspecionar; mantenha stable/MSRV para build e release ([cargo-msrv](/blog/cargo-msrv-versao-minima-rust-ci-2026/)).
5. **Ler expansão como garantia de performance.** Código gerado verboso pode ser otimizado pelo LLVM — meça.
6. **Diffs instáveis.** Ordem de itens e formatação podem mudar entre versões; compare com critério e, se possível, mesma versão da ferramenta.
7. **Expor segredos.** Dumps podem incluir paths locais, nomes internos ou módulos privados; revise antes de colar em issues públicas.
8. **Confundir com `cargo expand` de dependências transitivas.** Comece pelo seu código; só aprofunde em crates externos quando a evidência apontar para eles — e aí a conversa encontra [cargo-vet](/blog/cargo-vet-auditoria-dependencias-rust-supply-chain-2026/) e [cargo-audit](/blog/cargo-audit-vulnerabilidades-dependencias-rust-ci-2026/).

## Checklist de adoção

- [ ] `cargo-expand` instalado com `--locked`
- [ ] nightly disponível apenas para inspeção
- [ ] comando mínimo documentado no README do crate (`cargo expand --lib modulo`)
- [ ] exemplos de Serde/Clap/erro cobertos por pelo menos um dump local na investigação
- [ ] features relevantes reproduzidas na expansão
- [ ] workspace usa `-p` explicitamente
- [ ] dumps grandes vão para artifact/diff, não para comentário cego
- [ ] hipóteses de custo seguem para llvm-lines/bloat/benchmark
- [ ] proc-macros críticas têm exemplo mínimo expansível

## cargo-expand e carreira Rust

Saber expandir macros é sinal de maturidade em bibliotecas e plataformas. Em entrevistas e portfólios brasileiros de Rust, isso aparece quando você:

- explica um bug de Serde/Clap mostrando o código gerado;
- documenta uma proc-macro com exemplo antes/depois;
- reduz tempo de build ao identificar derive excessivo;
- colabora em crates open source com reproduções mínimas.

Para montar trilha prática, combine este guia com [projetos práticos em Rust](/carreira/projetos-praticos-rust/), [entrevista backend](/carreira/entrevista-rust-backend/), [vagas Rust](/vagas/) e o hub de [carreira Rust 2026](/blog/carreira-rust-2026/). Empresas que publicam SDKs, CLIs e bibliotecas internas valorizam quem debuga o gerado, não só quem consome o derive.

## Perguntas frequentes

### O que é cargo-expand?

`cargo-expand` é uma ferramenta do ecossistema Cargo que mostra o código Rust gerado depois da expansão de macros. Ela ajuda a inspecionar derives, macros declarativas e procedurais, filtrar por módulo ou item e entender o que o compilador realmente vê antes de analisar erros obscuros.

### Quando vale a pena usar cargo-expand?

Vale a pena ao debugar derives de Serde, Clap, thiserror e similares, ao escrever ou manter proc-macros, ao investigar erros que apontam para código gerado e ao revisar o custo de abstrações baseadas em macros. Em código sem macros, `cargo check` e rust-analyzer costumam ser suficientes.

### cargo-expand substitui rust-analyzer ou cargo check?

Não. rust-analyzer oferece navegação e expansão parcial no editor; `cargo check` valida a compilação; `cargo-expand` materializa o código expandido em texto para inspeção completa, diff e compartilhamento em code review. As três ferramentas se complementam.

### Preciso de nightly para usar cargo-expand?

Em geral, sim: a expansão completa depende de recursos do compilador disponíveis no toolchain nightly. Na prática, você mantém o projeto em stable e usa nightly apenas para inspecionar a expansão. Confirme a documentação atual da ferramenta e fixe a versão na CI se for automatizar dumps.

### cargo-expand serve para performance?

Indiretamente. Expandir macros não otimiza o binário, mas revela código gerado repetitivo e padrões que depois você pode medir com [cargo-llvm-lines](/blog/cargo-llvm-lines-monomorfizacao-rust-2026/), [cargo-bloat](/blog/cargo-bloat-reduzir-tamanho-binario-rust-2026/) ou Criterion. Use a expansão para entender o que foi gerado; use benchmarks para decidir o que mudar.

## Conclusão

`cargo-expand` não substitui testes, typecheck ou bom design de macros. Ele remove a opacidade. Quando o erro mora no código gerado, a saída expandida é o mapa.

Comece pequeno: instale a ferramenta, expanda um módulo com Serde ou Clap, filtre até o item útil e documente o comando no README. Se a macro for sua, transforme o exemplo mínimo em parte do fluxo de desenvolvimento. Se o problema for custo de build ou tamanho, siga para llvm-lines e bloat com evidência, não com achismo.

Para continuar no cluster de tooling Rust, leia também [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/), [cargo-msrv](/blog/cargo-msrv-versao-minima-rust-ci-2026/), [macros em Rust](/blog/macros-rust-declarativas-procedurais-2026/), [Serde](/ecossistema/serde/) e a visão geral de [Cargo](/ecossistema/cargo/). Se estiver buscando aplicar isso em produto, explore as [vagas](/vagas/) e as [empresas que usam Rust no Brasil](/empresas/).
