Error Rust E0405: cannot find trait in this scope (trait tidak ditemukan)
E0405 artinya: kamu menyebut sebuah trait yang tidak bisa dilihat Rust dari tempat itu. Contoh klasiknya: kamu menulis impl Display for Point supaya struct-mu bisa dicetak, tapi kamu tidak pernah meng-import Display. Salah ketik pada nama trait, atau trait yang tinggal di modul lain, memberi error yang sama. Ini salah satu error yang paling gampang diperbaiki, karena rustc biasanya menampilkan baris use persis yang kamu butuhkan. Berbeda dengan E0412 (“cannot find type”), yang berubah menjadi E0425 di Rust 1.93, kode ini tidak berubah: rustc 1.97 masih menampilkan E0405 untuk trait. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0405]: cannot find trait `Display` in this scope --> src/main.rs:6:6 |6 | impl Display for Point { // ❌ `Display` tidak pernah di-import | ^^^^^^^ not found in this scope |help: consider importing this trait |1 + use std::fmt::Display; |Ini program yang menghasilkan error tersebut:
struct Point { x: i32, y: i32,}
impl Display for Point { // ❌ `Display` tidak pernah di-import fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) }}
fn main() { let p = Point { x: 3, y: 4 }; println!("{}", p);}Apa artinya
Section titled “Apa artinya”^^^^^^^ menunjuk ke Display di baris 6, dengan label “not found in this scope” (tidak ditemukan di scope ini). Rust sudah melihat setiap trait yang terlihat dari sana: yang kamu definisikan di modul ini, yang dimasukkan oleh baris use-mu, dan sekumpulan kecil trait di prelude. Tidak satu pun yang bernama Display.
help:-nya memberi tahu tempatnya: use std::fmt::Display;. Tanda 1 + berarti “tambahkan ini sebagai baris 1 yang baru”, di bagian paling atas file.
Kenapa Display tidak ada, padahal println! memakainya terus? Prelude, yaitu daftar nama yang didapat setiap file Rust secara gratis, berisi Clone, Iterator, From, Default, dan trait sehari-hari lainnya, tapi tidak berisi Display, Error, Hash, atau Write. Trait-trait itu tinggal di modulnya masing-masing (std::fmt, std::error, std::hash, std::io), dan kamu meng-import-nya saat ingin mengimplementasikannya.
Ini seperti resep yang bilang “pakai panci Display”. Si juru masak tahu panci-panci yang ada di atas kompor, tapi panci yang ini ada di dalam lemari, dan resepnya tidak pernah bilang lemari yang mana.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Rust tidak pernah mencari sebuah nama di seluruh standard library, atau di seluruh proyekmu. Ia hanya melihat apa yang ada di scope: item buatanmu, baris use-mu, dan prelude. Ini membuat nama tetap bisa diprediksi. Di std saja ada beberapa trait bernama Write dan Error, dan crate yang kamu tambahkan nanti bisa membawa lebih banyak lagi. Kalau Rust memilihkan salah satunya untukmu, menambahkan sebuah dependency bisa diam-diam mengubah arti kodemu.
Jadi kamu menyebutkan trait mana yang kamu maksud, sekali saja, di bagian atas file. Baris help-nya sudah melakukan pencarian untukmu dan menyarankan trait yang ditemukannya. Lihat Modul untuk cara kerja use, dan Trait yang Sering Dipakai untuk Display.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Tambahkan baris use yang disarankan rustc
Section titled “Perbaikan 1: Tambahkan baris use yang disarankan rustc”Pilih ini kalau help-nya bilang consider importing this trait (coba import trait ini), dan itu yang paling sering terjadi. Salin barisnya ke bagian atas file:
use std::fmt::Display;
struct Point { x: i32, y: i32,}
impl Display for Point { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "({}, {})", self.x, self.y) }}
fn main() { let p = Point { x: 3, y: 4 }; println!("{}", p); println!("Ferris ada di {}", Point { x: -1, y: 7 });}Output:
(3, 4)Ferris ada di (-1, 7)Kalau rustc menyarankan beberapa import, baca dulu sebelum memilih. Itu trait-trait berbeda yang kebetulan bernama sama, seperti std::fmt::Write dan std::io::Write.
Perbaikan 2: Import modulnya dan tulis fmt::Display
Section titled “Perbaikan 2: Import modulnya dan tulis fmt::Display”Pilih ini kalau kamu sedang mengimplementasikan Display, karena bagaimanapun kamu butuh Formatter dan Result dari modul yang sama. Import std::fmt sekali dan tulis fmt:: di depan ketiganya. Inilah gaya yang paling sering kamu lihat di kode Rust sungguhan:
use std::fmt;
struct Point { x: i32, y: i32,}
impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) }}
fn main() { let p = Point { x: 3, y: 4 }; let label = p.to_string(); println!("{} punya {} karakter", label, label.len());}Output:
(3, 4) punya 6 karakterMengimplementasikan Display juga memberimu .to_string() secara gratis. Kamu bisa melewatkan use sama sekali dan menulis impl std::fmt::Display for Point; itu tidak masalah untuk pemakaian sekali saja.
Perbaikan 3: Betulkan ejaan nama trait-nya
Section titled “Perbaikan 3: Betulkan ejaan nama trait-nya”Pilih ini kalau rustc bilang a trait with a similar name exists (ada trait dengan nama yang mirip). Nama trait peka huruf besar-kecil, jadi shape, Shap, dan Shape adalah tiga nama yang berbeda:
error[E0405]: cannot find trait `Shap` in this scope --> src/main.rs:9:6 |1 | trait Shape { | ----------- similarly named trait `Shape` defined here...9 | impl Shap for Square { // ❌ salah ketik: Shap | ^^^^ |help: a trait with a similar name exists |9 | impl Shape for Square { // ❌ salah ketik: Shap | +Artinya: trait Shap tidak ada, tapi ada trait bernama mirip, Shape, yang didefinisikan di baris 1. Program yang rusak:
trait Shape { fn area(&self) -> f64;}
struct Square { side: f64,}
impl Shap for Square { // ❌ salah ketik: Shap fn area(&self) -> f64 { self.side * self.side }}
fn main() { let s = Square { side: 3.0 }; println!("{}", s.area());}Tanda + di bawah baris 9 menunjukkan huruf yang kurang. Tambahkan hurufnya:
trait Shape { fn area(&self) -> f64;}
struct Square { side: f64,}
impl Shape for Square { fn area(&self) -> f64 { self.side * self.side }}
fn main() { let s = Square { side: 3.0 }; println!("{}", s.area());}Output:
9Kalau tidak ada nama yang mirip dan tidak ada saran import, berarti trait-nya memang belum ada. Definisikan dulu dengan trait Shape { ... }. Lihat Trait.
Perbaikan 4: Import trait buatanmu dari modulnya
Section titled “Perbaikan 4: Import trait buatanmu dari modulnya”Pilih ini kalau trait-nya buatanmu sendiri tapi tinggal di modul lain. Setiap modul punya scope sendiri, jadi trait di mod shapes tidak terlihat di level atas main.rs sampai kamu meng-import-nya:
error[E0405]: cannot find trait `Shape` in this scope --> src/main.rs:11:6 |11 | impl Shape for Square { // ❌ `Shape` ada di `mod shapes` | ^^^^^ not found in this scope |help: consider importing this trait | 1 + use crate::shapes::Shape; |Artinya: Shape tidak terlihat di baris 11, dan rustc menyarankan meng-import-nya dari crate::shapes. Program yang rusak:
mod shapes { pub trait Shape { fn area(&self) -> f64; }}
struct Square { side: f64,}
impl Shape for Square { // ❌ `Shape` ada di `mod shapes` fn area(&self) -> f64 { self.side * self.side }}
fn main() { println!("{}", Square { side: 2.0 }.area());}Tambahkan baris use-nya, dan pastikan trait-nya pub. Tanpa pub, import-nya sendiri gagal dengan E0603, “trait is private” (trait-nya private):
mod shapes { pub trait Shape { fn area(&self) -> f64; }}
use crate::shapes::Shape;
struct Square { side: f64,}
impl Shape for Square { fn area(&self) -> f64 { self.side * self.side }}
fn main() { println!("{}", Square { side: 2.0 }.area());}Output:
4Hal yang sama berlaku untuk trait dari crate: impl Serialize for User butuh use serde::Serialize; lebih dulu. Lihat Modul.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Box<dyn Error> di main atau di fungsi pembantu. fn run() -> Result<(), Box<dyn Error>> tanpa import memberi cannot find trait `Error` in this scope, dengan help: consider importing this trait, use std::error::Error;. Perbaikannya: tambahkan baris itu, atau tulis Box<dyn std::error::Error>. Lihat Error Kustom.
Trait bound pada generics. fn print_all<T: Display>(items: &[T]) memberi E0405 yang sama untuk Display, menunjuk ke bound-nya. Perbaikannya: use std::fmt::Display;. Lihat Generics.
Debug memberi kode yang berbeda. impl Debug for Point atau T: Debug tanpa import bukan E0405, melainkan E0404: expected trait, found derive macro `Debug` (yang diharapkan trait, yang ditemukan derive macro Debug). Prelude berisi makro #[derive(Debug)], tapi tidak berisi trait Debug. Perbaikannya: use std::fmt::Debug; (rustc menyarankannya), atau cukup #[derive(Debug)] kalau kamu tidak butuh format kustom.
Error terkait
Section titled “Error terkait”- E0425: tidak bisa menemukan nilai, fungsi, atau (sejak Rust 1.93) tipe di scope ini.
- E0412: kode lama untuk “cannot find type”, sekarang dilaporkan sebagai E0425.
- E0433: tidak bisa menemukan bagian pertama dari sebuah path, seperti
fmt::Displaytanpause std::fmt;. - E0599: method tidak ditemukan, sering karena trait yang menyediakan method itu belum di-import.
- E0277: trait-nya ditemukan, tapi tipemu tidak mengimplementasikannya.
- E0404: nama yang ada, tapi bukan trait (seperti makro
Debug), ditunjukkan di atas. - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Kamu menulis impl Display for Invoice dan mendapat E0405. Apa yang kurang?
2. Trait mana yang bisa kamu pakai tanpa baris use apa pun?
3. Trait Shape milikmu didefinisikan di mod shapes, dan impl Shape for Square ada di main.rs. Apa yang kamu butuhkan?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0405 — Rust error codes index (bahasa Inggris): penjelasan resmi, dengan dua perbaikannya: import trait-nya atau definisikan trait-nya.
- Implementing a Trait on a Type — The Rust Book (bahasa Inggris): cara kerja
impl Trait for Type, dan kenapa trait-nya harus ada di scope. std::fmt::Display— standard library docs (bahasa Inggris): trait dari halaman ini, dengan contohimpl fmt::Displayyang lengkap.- Display — Rust by Example (bahasa Inggris): mengimplementasikan
Displaylangkah demi langkah, denganuse std::fmt;. std::prelude— standard library docs (bahasa Inggris): daftar trait dan tipe yang bisa kamu pakai tanpa meng-import-nya.