E0412: Tipo Não Encontrado no Rust

Como resolver o erro E0412 do Rust: tipo não encontrado no escopo atual. Veja as causas comuns como imports faltando, typos, dependências ausentes e soluções.

E0412: Tipo Não Encontrado

O erro E0412 ocorre quando você usa um nome de tipo que o compilador não consegue encontrar no escopo atual. As causas mais comuns são: import (use) faltando, erro de digitação, dependência não adicionada ao Cargo.toml, ou o tipo está definido em outro módulo.

A Mensagem de Erro

error[E0412]: cannot find type `HashMap` in this scope
 --> src/main.rs:2:16
  |
2 |     let mapa: HashMap<String, i32> = HashMap::new();
  |               ^^^^^^^ not found in this scope
  |
help: consider importing this struct
  |
1 + use std::collections::HashMap;
  |

Variação com tipo de crate externo:

error[E0412]: cannot find type `Regex` in this scope
 --> src/main.rs:3:16
  |
3 |     let re: Regex = Regex::new(r"\d+").unwrap();
  |             ^^^^^ not found in this scope

O Que Significa

O Rust usa um sistema de módulos explícito. Diferente de algumas linguagens onde tudo está disponível globalmente, no Rust você precisa importar tipos antes de usá-los. O compilador não encontrou o tipo porque:

  1. Falta o use — Você esqueceu de importar o tipo
  2. Typo — Erro de digitação no nome do tipo
  3. Dependência ausente — O crate não está no Cargo.toml
  4. Módulo não declarado — O módulo onde o tipo está definido não foi declarado
  5. Feature flag — O tipo requer uma feature que não está ativada
  6. Visibilidade — O tipo é privado (pub não declarado)

Código com Erro

fn main() {
    // ERRO: HashMap não está no escopo
    let mut mapa: HashMap<String, i32> = HashMap::new();
    mapa.insert("chave".to_string(), 42);
}
// ERRO: typo — "Stirng" em vez de "String"
fn processar(texto: Stirng) {
    println!("{}", texto);
}
// ERRO: Regex não está disponível sem o crate `regex`
fn validar(email: &str) -> bool {
    let re = Regex::new(r"^[\w.-]+@[\w.-]+\.\w+$").unwrap();
    re.is_match(email)
}

Como Resolver

Solução 1: Adicionar o Import (use)

A solução mais comum — importe o tipo necessário:

use std::collections::HashMap;

fn main() {
    let mut mapa: HashMap<String, i32> = HashMap::new();
    mapa.insert("chave".to_string(), 42);
    println!("{:?}", mapa);
}

Imports comuns da biblioteca padrão:

use std::collections::{HashMap, HashSet, BTreeMap, VecDeque};
use std::io::{self, Read, Write, BufReader, BufWriter};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, RwLock};
use std::cell::{Cell, RefCell};
use std::fmt::{self, Display, Formatter};

Solução 2: Corrigir Erros de Digitação

O compilador frequentemente sugere o tipo correto:

error[E0412]: cannot find type `Stirng` in this scope
 --> src/main.rs:1:20
  |
1 | fn processar(texto: Stirng) {
  |                     ^^^^^^ help: a struct with a similar name exists: `String`
// Corrigido: String com grafia correta
fn processar(texto: String) {
    println!("{}", texto);
}

Solução 3: Adicionar Dependência ao Cargo.toml

Para tipos de crates externos, adicione a dependência:

cargo add regex

Ou edite Cargo.toml manualmente:

[dependencies]
regex = "1"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Depois importe:

use regex::Regex;

fn validar(email: &str) -> bool {
    let re = Regex::new(r"^[\w.-]+@[\w.-]+\.\w+$").unwrap();
    re.is_match(email)
}

Solução 4: Declarar Módulos Corretamente

Se o tipo está em outro arquivo do seu projeto:

src/
├── main.rs
├── modelos/
│   ├── mod.rs
│   └── usuario.rs
// src/modelos/usuario.rs
pub struct Usuario {
    pub nome: String,
    pub email: String,
}

// src/modelos/mod.rs
pub mod usuario;

// src/main.rs
mod modelos;
use modelos::usuario::Usuario;

fn main() {
    let u = Usuario {
        nome: "Alice".to_string(),
        email: "alice@email.com".to_string(),
    };
}

Solução 5: Ativar Feature Flags

Alguns tipos só estão disponíveis com features específicas:

# Cargo.toml
[dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
// Só disponível com feature "derive"
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Config {
    porta: u16,
    host: String,
}

Solução 6: Usar Caminho Completo sem Import

Você pode usar o caminho completo (fully qualified path) em vez de use:

fn main() {
    let mut mapa = std::collections::HashMap::new();
    mapa.insert("chave", 42);
}

Útil quando há conflito de nomes ou para uso esporádico.

Dica: rust-analyzer

Se você usa um editor com rust-analyzer (VS Code, Neovim, etc.), ele pode adicionar imports automaticamente. Ao digitar o nome de um tipo, o autocompletar sugere e insere o use necessário.

Veja Também