Rust 에러 E0433: failed to resolve, use of undeclared type (선언되지 않은 타입)
E0433은 HashMap::new()나 rand::rng() 같은 경로를 썼는데, Rust가 그 첫 부분이 무엇인지 모른다는 뜻이에요. 거의 항상 한 줄이 빠져 있어요. use 줄, Cargo.toml의 의존성, 또는 mod 선언이에요. 다행히 rustc가 보통 그 줄을 그대로 출력해 주니까 복사해서 붙이면 돼요. 이 페이지는 Rust 컴파일러 에러 해설의 일부예요.
에러 메시지
섹션 제목: “에러 메시지”error[E0433]: cannot find type `HashMap` in this scope --> src/main.rs:2:21 |2 | let mut stock = HashMap::new(); | ^^^^^^^ use of undeclared type `HashMap` |help: consider importing this struct |1 + use std::collections::HashMap; |“이 스코프에서 HashMap 타입을 찾을 수 없고, 선언되지 않은 타입 HashMap을 썼다”는 뜻이에요. help는 “이 구조체를 가져와 보라”며 넣을 줄을 보여 줘요.
이 에러를 내는 프로그램은 다음과 같아요.
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}예전 Rust 버전은 같은 에러를 “failed to resolve: use of undeclared type HashMap”(해석 실패: 선언되지 않은 타입 사용)이라고 출력해요. 무엇이 빠졌느냐에 따라 라벨이 use of undeclared type 대신 use of unresolved module or unlinked crate(찾을 수 없는 모듈이나 연결되지 않은 크레이트 사용, 크레이트나 모듈일 때)라고 나오기도 해요. 모두 E0433이고, 고치는 방법도 같아요.
무슨 뜻인가요
섹션 제목: “무슨 뜻인가요”^^^^^^^는 HashMap, 즉 ::의 앞부분을 가리켜요. HashMap::new()를 호출하려면 Rust는 먼저 HashMap이라는 것을 찾아야 해요. 2번째 줄에서 보이는 모든 것을 살펴봤지만 그런 이름이 없었고, 그래서 new는 찾기 시작할 수조차 없었어요.
중요한 건 help: 줄이에요. rustc가 표준 라이브러리를 뒤져서 std::collections에 있는 HashMap이라는 구조체를 찾았고, 그걸 보이게 해 줄 use 줄을 보여 줘요. 1 +는 “이걸 1번째 줄로 추가하라”는 뜻이에요.
도서관 사서에게 책 제목은 말하지 않고 “그 책의 3장 주세요”라고 하는 것과 비슷해요. 3장이 있는 책은 많지만, 사서는 먼저 제목을 알아야 해요.
Rust가 이렇게 하는 이유
섹션 제목: “Rust가 이렇게 하는 이유”모든 Rust 파일에서 자동으로 보이는 이름은 몇 개 안 돼요. 이걸 프렐루드(prelude)라고 해요. Vec, String, Option, Some, None, Result, Ok, Err, Box, 그리고 몇 가지 트레이트예요. HashMap, HashSet, fs, Ordering을 포함한 나머지는 모두 use로 가져오거나 전체 경로로 써야 해요.
이렇게 하면 프렐루드가 작게 유지되고 이름 충돌도 피할 수 있어요. 예를 들어 표준 라이브러리에는 서로 다른 Ordering 타입이 두 개 있고, 내 코드에도 Duration이나 Result가 있을 수 있어요. Rust는 내가 어느 쪽을 뜻했는지 짐작하지 않아요. 파일 맨 위에 한 번 적어 두면, 코드를 읽는 누구나 각 이름이 어디서 왔는지 알 수 있어요.
크레이트와 모듈도 마찬가지예요. 크레이트는 Cargo.toml에 적힌 뒤에야, 모듈은 mod 줄이 있어야 내 코드에 존재해요. 모듈과 Cargo와 크레이트를 참고하세요.
고치는 방법
섹션 제목: “고치는 방법”방법 1: rustc가 제안하는 use 줄 추가하기
섹션 제목: “방법 1: rustc가 제안하는 use 줄 추가하기”help:가 consider importing(가져와 보라)이라고 말할 때 이 방법을 고르세요. 단연 가장 흔한 해결책이에요. 제안된 줄을 파일 맨 위에 복사하세요.
use std::collections::HashMap;
fn main() { let mut stock = HashMap::new(); stock.insert("apples", 12); println!("{:?}", stock.get("apples"));}실행 결과:
Some(12)다른 방법은 호출하는 곳에서 std::collections::HashMap::new()처럼 전체 경로를 쓰는 거예요. 이것도 동작하지만 쓸 때마다 반복해야 하니, 보통은 use 줄을 써요. 이 타입에 대해서는 HashMap에서 더 볼 수 있어요.
rustc가 가져올 후보를 여러 개 보여 주면(consider importing one of these), 하나를 고르기 전에 꼭 읽어 보세요. 이름만 같은 서로 다른 타입이고, 그중 하나만 내가 원한 거예요.
방법 2: 타입 이름을 고치거나 타입 선언하기
섹션 제목: “방법 2: 타입 이름을 고치거나 타입 선언하기”그 이름이 내가 만든 타입일 때 이 방법을 고르세요. help:가 아예 없다면 그 타입은 아직 없는 거예요. 오타라면 rustc가 비슷한 이름을 가리켜 줘요.
error[E0433]: cannot find type `Invetory` in this scope --> src/main.rs:12:17 |12 | let stock = Invetory::new(); | ^^^^^^^^ use of undeclared type `Invetory` |help: a struct with a similar name exists |12 | let stock = Inventory::new(); | +help는 “비슷한 이름의 구조체가 있다”는 뜻이고, 줄 아래의 +가 빠진 글자를 보여 줘요. 철자를 고치세요.
struct Inventory { items: Vec<String>,}
impl Inventory { fn new() -> Self { Inventory { items: Vec::new() } }}
fn main() { let stock = Inventory::new(); println!("물건 {}개", stock.items.len());}실행 결과:
물건 0개Order::new()가 아무 제안 없이 E0433을 낸다면, 아직 struct Order를 쓰지 않은 거예요(또는 mod로 선언하지 않은 파일에 있거나요). 대문자도 확인하세요. inventory::new()와 Inventory::new()는 서로 다른 이름이에요.
방법 3: 타입이 들어 있는 모듈 이름 쓰기
섹션 제목: “방법 3: 타입이 들어 있는 모듈 이름 쓰기”타입이나 열거형이 어떤 모듈 안에 정의되어 있는데 그 밖에서 쓸 때 이 방법을 고르세요. 여기서는 열거형이 mod traffic 안에 있는데, main이 Light::Green이라고 썼어요.
error[E0433]: cannot find type `Light` in this scope --> src/main.rs:11:15 |11 | let now = Light::Green; | ^^^^^ use of undeclared type `Light` |help: consider importing this enum | 1 + use crate::traffic::Light; |열거형을 가져오세요(또는 traffic::Light::Green이라고 쓰세요). 가져오는 건 열거형이고, 각 배리언트(variant)는 여전히 Light::Green처럼 써야 한다는 점을 기억하세요.
mod traffic { #[derive(Debug)] pub enum Light { Red, Yellow, Green, }}
use crate::traffic::Light;
fn can_go(light: &Light) -> bool { match light { Light::Green => true, Light::Yellow | Light::Red => false, }}
fn main() { let now = Light::Green; println!("{now:?}: 출발 가능 = {}", can_go(&now));}실행 결과:
Green: 출발 가능 = true배리언트 경로는 정확히 두 부분, Enum::Variant로 이루어져요. Light::Red::Green처럼 한 부분을 더 쓰면 cannot find module `Red` in `Light` (Light에서 모듈 Red를 찾을 수 없음)와 `Red` is a variant, not a module(Red는 모듈이 아니라 배리언트) 라벨이 붙은 E0433이 나요. 열거형을 참고하세요.
방법 4: 크레이트를 추가하거나 모듈 선언하기
섹션 제목: “방법 4: 크레이트를 추가하거나 모듈 선언하기”라벨이 use of unresolved module or unlinked crate라고 말할 때 이 방법을 고르세요. 경로의 첫 부분이 Rust가 모르는 크레이트나 모듈이에요.
error[E0433]: cannot find module or crate `rand` in this scope --> src/main.rs:4:19 |4 | let mut rng = rand::rng(); | ^^^^ 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`help는 “rand라는 크레이트를 쓰려던 거라면 cargo add rand로 Cargo.toml에 추가하라”는 뜻이에요. crates.io의 크레이트라면 프로젝트 폴더에서 cargo add rand를 실행하세요. fs 같은 표준 라이브러리 모듈이라면 rustc가 대신 use std::fs;를 제안해요. 그리고 src/inventory.rs 같은 내 파일이라면 help가 to make use of source file src/inventory.rs, use `mod inventory` in this file to declare the module(src/inventory.rs를 쓰려면 이 파일에서 mod inventory로 모듈을 선언하라)이라고 말해요.
src/├── main.rs inventory::count_items() ← 맨 위에 `mod inventory;` 필요└── inventory.rs pub fn count_items() -> u32 { 42 }아래는 같은 프로그램을 한 파일에 담은 거예요. Playground에서 실행되도록 모듈을 안에 바로 적었어요.
mod inventory { pub fn count_items() -> u32 { 42 }}
fn main() { println!("재고 수량: {}", inventory::count_items());}실행 결과:
재고 수량: 42파일을 따로 나눈다면, 달라지는 건 mod inventory { ... }가 mod inventory;가 되고 본문이 src/inventory.rs로 옮겨 간다는 것뿐이에요.
extern crate는 어떤가요?
섹션 제목: “extern crate는 어떤가요?”오래된 코드에서 extern crate rand;를 볼 수도 있어요. 2018 에디션부터는 필요 없어요. 크레이트가 Cargo.toml에 있으면 바로 쓸 수 있어요. extern crate를 추가해도 E0433은 고쳐지지 않아요. 의존성이 없으면 에러가 E0463, can't find crate for rand(rand 크레이트를 찾을 수 없음)로 바뀔 뿐이에요. 진짜 해결책은 cargo add예요.
자주 보게 되는 곳
섹션 제목: “자주 보게 되는 곳”cmp로 비교할 때. match a.cmp(&b)에 Ordering::Less 갈래를 쓰면 E0433이 나고, rustc가 use std::cmp::Ordering;과 use std::sync::atomic::Ordering; 두 가지를 제안해요. 원하는 건 std::cmp::Ordering이에요. atomic 쪽은 스레드용이에요. match를 참고하세요.
mod tests 블록 안의 테스트. 테스트 모듈은 자식 모듈이라서, 가져오지 않으면 내 타입을 볼 수 없어요. mod tests 안에서 Inventory::new()를 쓰면 help: consider importing this struct와 use crate::Inventory;가 붙은 E0433이 나요. 해결: 테스트 모듈 맨 위에 use super::*;를 넣으세요. 테스트를 참고하세요.
문서나 블로그 글에서 붙여 넣은 코드. 예제는 use 줄을 생략할 때가 많아요. fs::read_to_string(...)은 cannot find module or crate `fs` in this scope와 use std::fs;라는 help를 내며 실패해요. 해결: rustc가 보여 주는 줄을 추가하거나, 그 항목의 문서 페이지에서 경로를 확인하세요.
관련 에러
섹션 제목: “관련 에러”- E0432:
use줄에서 생기는 같은 종류의 문제,unresolved import예요. - E0425: 오타 난 변수처럼 값이나 함수를 찾을 수 없어요(
::는 없어요). 최신 rustc는let m: HashMap<&str, u32>처럼 타입 자리에 빠진 타입에도 E0425를 쓰고, 예전 버전은 그걸 E0412라고 불러요. 같은use줄로 고쳐져요. - E0599: 타입은 찾았지만
::뒤의 메서드나 배리언트가 없어요.Light::Blue처럼요. - E0463:
can't find crate. 의존성 없이extern crate를 쓰면 나요. - 전체 컴파일러 에러: 에러 페이지 전체 목록이에요.
이해도 점검
섹션 제목: “이해도 점검”이해도 점검
1. Vec::new()는 아무것도 가져오지 않아도 되는데, HashSet::new()는 왜 E0433을 낼까요?
2. match a.cmp(&b)에 대해 rustc가 use std::cmp::Ordering;과 use std::sync::atomic::Ordering;을 둘 다 제안해요. 어느 쪽을 고를까요?
3. rand::rng()가 'use of unresolved module or unlinked crate' 라벨이 붙은 E0433을 내요. 무엇으로 고칠까요?
점수: 0 / 3
더 알아보기
섹션 제목: “더 알아보기”- E0433 — Rust error codes index (영어): 선언되지 않은 타입과 연결되지 않은 크레이트 경우를 다룬 공식 설명이에요.
- use 키워드로 경로를 스코프 안으로 가져오기 — The Rust Programming Language 한국어판:
use가 동작하는 방식과,HashMap같은 타입을 가져오는 게 왜 자연스러운지 설명해요. - 경로를 사용하여 모듈 트리의 아이템 참조하기 — The Rust Programming Language 한국어판: 전체 경로,
crate::,super::를 다뤄요. std::prelude— 표준 라이브러리 문서 (영어):use없이 보이는 이름의 정확한 목록이에요.- Path and module changes in Rust 2018 — Edition Guide (영어):
extern crate가 더 이상 필요 없는 이유를 설명해요.