extern crate e use em Rust: qual é o truque e como não pisar em armadilhas
\n\nSe você já escreveu pelo menos algumas linhas em Rust, certamente já se deparou com as construções extern crate e use. À primeira vista, parece que elas fazem a mesma coisa — conectar código externo. Mas o diabo, como sempre, está nos detalhes. Esta questão está entre as mais populares no Stack Overflow (milhares de visualizações!), e os iniciantes se confundem constantemente com ela. Vamos de uma vez por todas entender a diferença entre extern crate e use, onde cada mágica acontece e como evitar erros típicos.
Resumindo: o que é o quê
\n\nImagine que seu projeto em Rust é uma casa grande. extern crate é a entrega dos materiais de construção no terreno. Você diz ao compilador: "Ei, esta caixa de tijolos (crate) que quero usar, traga-a". Sem este comando, o compilador nem saberá da existência da biblioteca externa.
use é a navegação interna da casa. Você diz: "Quero que a porta desta sala (módulo) leve diretamente à cozinha (tipo ou função específica)". use cria aliases (caminhos curtos) para módulos e tipos já conhecidos, para não precisar escrever o caminho completo toda vez.
Simplificando: extern crate responde à pergunta "o que podemos usar?", enquanto use responde à pergunta "como é mais conveniente nos referirmos a isso?".
Contexto histórico: por que todos se confundem
\n\nA confusão não surgiu do nada. Nas versões antigas do Rust (anteriores à edição 2018), extern crate era obrigatório para qualquer crate externo. Ficava assim:
// Rust 2015 — estilo antigo\nextern crate serde;\nuse serde::{Serialize, Deserialize};\n\nA partir do Rust 2018 edition, o compilador aprendeu a encontrar as dependências do Cargo.toml sozinho. Agora, escrever extern crate para a maioria dos crates não é necessário. Basta adicionar a dependência no Cargo.toml e usar diretamente o use:
// Rust 2018+ — novo estilo (extern crate não é obrigatório)\nuse serde::{Serialize, Deserialize};\n\nÉ aí que começa o inferno para os iniciantes. Eles veem exemplos antigos onde extern crate é usado, exemplos novos onde não é, e tentam entender quando ele ainda é necessário. Spoiler: é necessário, mas em casos muito raros.
Quando extern crate ainda é necessário (e isso é importante!)
\n\nExistem três situações em que não se pode evitar o extern crate:
- \n
- Vinculação com bibliotecas do sistema via
#[link]— se você está escrevendo bindings para código C/C++ e usando o atributo#[link(name = "sqlite3")], entãoextern crateé obrigatório. \n - Macros globais — alguns crates (por exemplo,
log) exportam macros que precisam ser visíveis em todo o programa. No Rust 2018, para isso é necessário escreverextern crate log;. \n - Compilação com nomes de crates não padrão — se você usa
extern crate my_crate as foo;para renomear um crate. \n
Em todos os outros casos, extern crate é um artefato do passado. Mas muitos desenvolvedores, por hábito, continuam a escrevê-lo, e os iniciantes copiam código de tutoriais antigos.
Top 5 erros ao trabalhar com extern crate e use
\n\nErro nº1: Usar extern crate onde ele não é necessário
\n\nO problema mais comum. Você adiciona um crate no Cargo.toml, depois escreve extern crate rand; — e o código funciona. Mas é uma linha desnecessária. Em projetos modernos (Rust 2018+), ela apenas polui o código e pode confundir outros desenvolvedores.
// Ruim (redundante no Rust 2018+)