Pular para o conteúdo

Erro E0432 do Rust: unresolved import (import não resolvido)

O E0432 quer dizer que uma das suas linhas use aponta para algo que o Rust não encontra. Talvez o crate ainda não esteja no Cargo.toml, talvez haja um pequeno erro de digitação no caminho, ou talvez exista um arquivo que o Rust não sabe que é um módulo. Parece assustador, mas quase sempre se resolve com uma linha, e o compilador normalmente diz qual. Para os outros erros desta série, veja Erros do compilador Rust.

error[E0432]: unresolved import `rand`
--> src/main.rs:1:5
|
1 | use rand::random_range;
| ^^^^ use of unresolved module or unlinked crate `rand`
|
= help: if you wanted to use a crate named `rand`, use `cargo add rand` to add it to your `Cargo.toml`

Em português: “import não resolvido rand”. O compilador não conhece nenhum módulo nem crate chamado rand e sugere rodar cargo add rand para colocá-lo no Cargo.toml.

Este é o programa que gera o erro, num projeto recém-criado com cargo new e nada em [dependencies]:

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("You rolled {roll}");
}

O texto embaixo do ^^^^ muda conforme a causa. Todos estes são E0432, e cada um leva a uma correção diferente abaixo:

O que o rótulo diz O que costuma ter dado errado Correção
use of unresolved module or unlinked crate falta o crate no Cargo.toml, ou um arquivo está sem a linha mod Correção 1 ou 3
could not find `collection` in `std` um erro de digitação no meio do caminho Correção 2
no `Hashmap` in `collections` um erro de digitação (ou de maiúsculas) no último nome Correção 2
could not find `inventory` in the crate root caminho com crate:: para um módulo que não foi declarado Correção 3
no external crate o caminho começa no módulo errado Correção 4

Uma linha use é um atalho. use rand::random_range; diz “daqui em diante, random_range significa a coisa que está em rand::random_range”. Antes de criar esse atalho, o Rust precisa percorrer o caminho uma parte de cada vez: primeiro encontrar rand e depois encontrar random_range dentro dele.

O ^^^^ marca a primeira parte que falhou. Aqui é rand, o primeiro pedaço, então o Rust nem chegou a procurar random_range. A linha help: dá um palpite do motivo: rand é um crate do crates.io, e este projeto não o adicionou.

É como dar a um taxista o endereço “Rua do Porto, 12, Florianópols”. Se o nome da cidade está errado, o motorista nem começa a procurar a rua.

O Rust resolve todos os caminhos na compilação, não quando o programa roda. Nada é carregado “só por garantia”. O seu código só enxerga três tipos de coisa: os crates listados no Cargo.toml (mais o std), os módulos que você declarou com mod e os itens dentro deles. Se uma linha use cita algo fora desse conjunto, o Rust para na hora em vez de adivinhar.

Isso é bom. Um import com erro de digitação em Python ou JavaScript muitas vezes só falha quando aquela linha finalmente roda, talvez em produção. Em Rust, o programa nem compila. Isso também quer dizer que um crate que você nunca adicionou não tem como entrar escondido no seu programa.

Desde a edição 2018, um caminho de use começa num destes lugares: o nome de um crate (std, rand), crate (a raiz do seu próprio crate), self (o módulo atual), super (o módulo pai) ou um módulo declarado no módulo atual. A lição de Módulos explica isso em detalhes, e Cargo e crates explica as dependências.

Escolha esta quando a primeira parte do caminho é um crate do crates.io, como rand, serde ou regex, e a linha help: fala em cargo add. É a causa mais comum, principalmente quando você copia código de um post de blog. Rode isto na pasta que contém o Cargo.toml:

Terminal window
cargo add rand

O Cargo encontra a versão mais nova e acrescenta uma linha ao Cargo.toml para você:

[dependencies]
rand = "0.10.3"

Agora o mesmo código compila. Esta versão imprime uma verificação em vez do número sorteado, para que a saída seja sempre a mesma:

use rand::random_range;
fn main() {
let roll = random_range(1..=6);
println!("O dado deu entre 1 e 6: {}", (1..=6).contains(&roll));
}

Saída:

O dado deu entre 1 e 6: true
▶ Experimente você mesmo

Duas coisas costumam confundir aqui. Primeiro, nomes de crate com hífen usam sublinhado no código: você roda cargo add tracing-subscriber, mas escreve use tracing_subscriber::.... Segundo, se o crate é uma dependência do seu workspace, ele ainda precisa estar listado no Cargo.toml do pacote que o usa.

Escolha esta quando o rótulo disser could not find `X` in `Y` (não encontrei X em Y) ou no `X` in `Y` (não há X em Y). Alguma parte no meio ou no fim do caminho está escrita errado. Um clássico:

error[E0432]: unresolved import `std::collection`
--> src/main.rs:1:10
|
1 | use std::collection::HashMap;
| ^^^^^^^^^^ could not find `collection` in `std`

O compilador não encontrou collection dentro de std. O módulo se chama collections, com s. Os nomes também diferenciam maiúsculas de minúsculas: use std::collections::Hashmap; falha com no `Hashmap` in `collections`, e o rustc acrescenta help: a similar name exists in the module (existe um nome parecido no módulo) com a grafia certa. O import corrigido:

use std::collections::HashMap;
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("apples", 12);
println!("{:?}", stock.get("apples"));
}

Saída:

Some(12)
▶ Experimente você mesmo

Se você não tem certeza do caminho exato, procure na documentação da biblioteca padrão (em inglês). A página de cada item mostra o caminho completo no topo. Veja HashMaps para saber mais sobre esse tipo.

Escolha esta quando você criou um arquivo novo, digamos src/inventory.rs, e use inventory::... não o encontra. Em Rust, um arquivo não é um módulo até que um arquivo pai o declare. O seu projeto está assim:

src/
├── main.rs use inventory::count_items; ← sem `mod inventory;`
└── inventory.rs pub fn count_items() -> u32 { 42 }

E o rustc diz exatamente o que falta:

error[E0432]: unresolved import `inventory`
--> src/main.rs:1:5
|
1 | use inventory::count_items;
| ^^^^^^^^^ use of unresolved module or unlinked crate `inventory`
|
help: to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module
|
1 + mod inventory;
|

O help diz: para usar o arquivo src/inventory.rs, declare o módulo com mod inventory neste arquivo. Acrescente mod inventory; no topo de src/main.rs (ou de src/lib.rs, se o módulo fizer parte da sua biblioteca). Escrever use crate::inventory::count_items; não resolve; isso falha com could not find `inventory` in the crate root (não encontrei inventory na raiz do crate), porque o módulo continua sem declaração.

No Playground tudo fica num único arquivo, então aqui o módulo é escrito direto no código com mod inventory { ... }. Funciona exatamente como o arquivo separado:

mod inventory {
pub fn count_items() -> u32 {
42
}
}
use inventory::count_items;
fn main() {
println!("Itens em estoque: {}", count_items());
}

Saída:

Itens em estoque: 42
▶ Experimente você mesmo

Declare cada módulo uma vez só, no módulo pai. Os outros arquivos chegam até ele com use crate::inventory::.... Não coloque mod inventory; em todo arquivo que o usa.

Escolha esta quando o import está dentro de um módulo e o item mora em outro módulo do seu próprio crate. Aqui receipt está dentro de shop e quer shop::store_name:

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod receipt {
use store_name; // ❌ procura no lugar errado
pub fn header() -> String {
format!("== {} ==", store_name())
}
}
}
error[E0432]: unresolved import `store_name`
--> src/main.rs:7:13
|
7 | use store_name; // ❌ procura no lugar errado
| ^^^^^^^^^^ no external crate `store_name`

O compilador diz que não existe nenhum crate externo chamado store_name. Um nome solto no começo de um caminho de use significa “um crate, ou algo declarado aqui mesmo neste módulo”. store_name não é nenhum dos dois, então o Rust procurou um crate com esse nome. Diga a ele por onde começar:

Prefixo Começa em Exemplo
crate:: a raiz do seu crate (main.rs ou lib.rs) use crate::shop::prices::price_of;
super:: o módulo pai use super::store_name;
self:: o módulo atual use self::lines::line;

Os três num só programa:

mod shop {
pub fn store_name() -> &'static str {
"Ferris Fruits"
}
pub mod prices {
pub fn price_of(item: &str) -> u32 {
if item == "apple" { 3 } else { 5 }
}
}
pub mod receipt {
use super::store_name; // módulo pai: shop
use crate::shop::prices::price_of; // a partir da raiz do crate
use self::layout::line; // filho deste módulo
mod layout {
pub fn line(item: &str, price: u32) -> String {
format!("{item}: {price}")
}
}
pub fn print(item: &str) {
println!("== {} ==", store_name());
println!("{}", line(item, price_of(item)));
}
}
}
fn main() {
shop::receipt::print("apple");
}

Saída:

== Ferris Fruits ==
apple: 3
▶ Experimente você mesmo

use layout::line; também funcionaria aqui, porque layout está declarado no módulo atual; o self:: só deixa isso explícito. Na dúvida, crate:: com o caminho completo sempre funciona de qualquer lugar do seu crate, e o rustc muitas vezes sugere isso: help: a similar path exists (existe um caminho parecido) seguido da versão com crate::.

Código escrito para uma versão mais antiga do crate. Muitos tutoriais usam o rand 0.8. Com o rand 0.10 você recebe:

error[E0432]: unresolved import `rand::thread_rng`
--> src/main.rs:1:5
|
1 | use rand::thread_rng;
| ^^^^^^^^^^^^^^^^ no `thread_rng` in the root

Ou seja, não existe thread_rng na raiz do crate. Correção: confira a documentação do crate no docs.rs para a versão que está no seu Cargo.toml. Aqui o novo nome é rand::rng(). Veja Números aleatórios.

Um pacote com main.rs e lib.rs. São dois crates separados. Dentro de main.rs, crate:: significa o binário, então use crate::inventory::count_items; falha com could not find `inventory` in the crate root mesmo que lib.rs tenha pub mod inventory;. Correção: use o nome do pacote, use shop_app::inventory::count_items; (com os hífens trocados por sublinhados).

O item existe, mas é privado. Esse é outro erro, o E0603, não o E0432:

error[E0603]: function `count_items` is private
--> src/main.rs:7:16
|
7 | use inventory::count_items;
| ^^^^^^^^^^^ private function

O compilador encontrou a função, mas avisa que ela é privada. Correção: coloque pub na frente do fn (e na frente de qualquer mod no caminho, já que um módulo privado dá module `prices` is private). Veja Módulos.

  • E0433: um caminho dentro do seu código (como HashMap::new() ou rand::rng()) não pode ser resolvido. As causas são as mesmas, mas não numa linha use.
  • E0425: não foi possível encontrar um valor ou uma função, muitas vezes resolvido pela mesma linha use.
  • E0603: o import foi encontrado, mas é privado. Acrescente pub.
  • E0463: can't find crate (crate não encontrado), que aparece com extern crate rand; quando o crate não está no Cargo.toml.
  • Todos os erros do compilador: a lista completa de páginas de erro.

Teste o que aprendeu

1. Você copiou use serde::Serialize; para um projeto novo e recebe um E0432 dizendo que o crate serde não foi resolvido. Qual é a correção?

2. Você criou src/billing.rs, mas use billing::total; no main.rs falha. O que está faltando?

3. Dentro de mod shop { mod receipt { ... } }, como receipt importa uma função definida diretamente em shop?

Pontuação: 0 / 3