Error Rust E0411: cannot find type Self in this scope (Self di luar impl)
E0411 artinya: kamu menulis Self di tempat yang membuat Rust tidak tahu apa yang dimaksud. Self adalah singkatan untuk “tipe yang sedang dibahas blok impl (atau trait) ini”, jadi ia hanya bisa dipakai di dalam impl, trait, atau definisi tipe. Penyebab yang paling umum adalah constructor seperti fn new() -> Self yang ditulis di level atas file, atau method yang kamu salin keluar dari blok impl-nya. Error ini sering muncul dan cepat diperbaiki. Berbeda dengan E0412, yang berubah menjadi E0425 di Rust 1.93, kode ini tidak berubah: rustc 1.97 masih menampilkan E0411. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0411]: cannot find type `Self` in this scope --> src/main.rs:5:21 |5 | fn new_counter() -> Self { // ❌ `Self` di luar `impl` | ----------- ^^^^ `Self` is only available in impls, traits, and type definitions | | | `Self` not allowed in a functionIni program yang menghasilkan error tersebut:
struct Counter { count: u32,}
fn new_counter() -> Self { // ❌ `Self` di luar `impl` Counter { count: 0 }}
fn main() { let c = new_counter(); println!("{}", c.count);}Apa artinya
Section titled “Apa artinya”rustc menunjuk ke dua hal di baris 5:
^^^^di bawahSelf: “Selfis only available in impls, traits, and type definitions” (Selfhanya tersedia di impl, trait, dan definisi tipe). Itulah aturannya, dalam satu baris.-----di bawahnew_counter: “Selfnot allowed in a function” (Selftidak boleh dipakai di fungsi). Inilah alasannya di sini:new_counteradalah fungsi biasa, bukan bagian dariimplmana pun.
Kamu mungkin tahu bahwa new_counter mengembalikan Counter, karena kamu baru saja menulis Counter { count: 0 }. Tapi Rust tidak membaca isi fungsi untuk menebak arti Self. Self mendapat artinya hanya dari impl Counter { ... } atau trait ... { ... } yang membungkusnya, dan di sini tidak ada.
Ini seperti kata “di sini” pada selembar kertas tempel. Di peta, “kamu di sini” masuk akal. Di kertas yang tergeletak di meja dapur, tidak ada yang tahu “di sini” itu di mana.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Self bukan tipe tersendiri. Ia adalah placeholder (tempat kosong) yang diisi oleh setiap impl atau trait: di dalam impl Counter, Self berarti Counter; di dalam impl Timer, ia berarti Timer; di dalam trait, ia berarti “tipe mana pun yang mengimplementasikan trait ini”. Itulah yang membuatnya berguna: kamu bisa mengganti nama struct, atau menyalin method ke impl lain, dan Self ikut menyesuaikan.
Fungsi bebas (free function) tidak menjadi milik tipe mana pun, jadi tidak ada yang bisa mengisinya. Rust bisa saja mencoba menebak dari isi fungsinya, tapi kalau begitu sebuah signature akan bergantung pada kode di dalamnya, padahal Rust sengaja memeriksa signature secara terpisah. Lihat Struct untuk tempat yang biasa bagi fn new() -> Self.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Pindahkan fungsinya ke blok impl
Section titled “Perbaikan 1: Pindahkan fungsinya ke blok impl”Pilih ini hampir setiap saat. Fungsi yang membuat atau mengolah satu tipe tertentu tempatnya di blok impl tipe itu, dan di sana Self bekerja seperti yang kamu harapkan. Panggil dengan Counter::new():
struct Counter { count: u32,}
impl Counter { fn new() -> Self { Self { count: 0 } }
fn increment(&mut self) { self.count += 1; }}
fn main() { let mut c = Counter::new(); c.increment(); c.increment(); println!("{}", c.count);}Output:
2Di dalam impl, kamu bisa memakai Self sebagai tipe (-> Self) sekaligus untuk membuat nilai (Self { count: 0 }). Lihat Struct.
Perbaikan 2: Tulis nama tipenya, bukan Self
Section titled “Perbaikan 2: Tulis nama tipenya, bukan Self”Pilih ini kalau fungsinya memang harus tetap menjadi fungsi bebas, misalnya fungsi pembantu yang membuat beberapa tipe sekaligus, atau yang tinggal di modul lain. Tulis saja tipe sebenarnya, Counter, di tempat kamu menulis Self:
struct Counter { count: u32,}
fn new_counter(start: u32) -> Counter { Counter { count: start }}
fn reset(c: &mut Counter) { c.count = 0;}
fn main() { let mut c = new_counter(10); println!("{}", c.count); reset(&mut c); println!("{}", c.count);}Output:
100Ini juga perbaikan untuk fn reset(c: &mut Self) yang disalin keluar dari impl: setiap Self di signature dan di isi fungsinya diganti menjadi Counter.
Perbaikan 3: Pakai tipe generic kalau maksudmu “tipe apa saja”
Section titled “Perbaikan 3: Pakai tipe generic kalau maksudmu “tipe apa saja””Pilih ini kalau kamu memakai Self dengan maksud “tipe apa pun yang diinginkan pemanggil”. Itu tugas untuk generic T, bukan Self. Deklarasikan <T> beserta trait yang dibutuhkan fungsinya. Di sini, T: Default membuat fungsinya bisa membuat nilai awal untuk tipe apa saja:
fn fresh_pair<T: Default>() -> (T, T) { (T::default(), T::default())}
fn main() { let numbers: (u32, u32) = fresh_pair(); let words: (String, String) = fresh_pair(); println!("{:?}", numbers); println!("{:?}", words);}Output:
(0, 0)("", "")Kalau kamu ingin setiap tipe menentukan sendiri cara ia dibuat, taruh fungsinya di sebuah trait: trait Reset { fn fresh() -> Self; }. Di dalam trait, Self berarti “tipe yang mengimplementasikannya”. Lihat Generics dan Trait.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Self { ... } di main atau di fungsi bebas. let c = Self { count: 0 }; memberi E0411 dengan judul yang sedikit berbeda: cannot find struct, variant or union type `Self` in this scope. Perbaikannya: tulis Counter { count: 0 }, atau panggil Counter::new().
Fungsi pembantu yang bersarang di dalam method. Di dalam impl Counter, method yang berisi fn helper() -> Self miliknya sendiri mendapat kode lain, E0401: can't use `Self` from outer item (tidak bisa memakai Self dari item luar). Fungsi di dalam fungsi tidak mewarisi impl di luarnya. Perbaikannya: tulis Counter di fungsi dalamnya, atau pakai closure, atau pindahkan helper ke atas, ke dalam impl, sebagai method tersendiri.
Tertukar antara Self dan self. Self dengan huruf kapital adalah tipe; self dengan huruf kecil adalah nilai tempat sebuah method dipanggil. Memakai self di luar method adalah error yang berbeda, E0424. Perbaikan untuk keduanya: pastikan kodenya berada di dalam blok impl yang tepat.
Error terkait
Section titled “Error terkait”- E0424:
self(huruf kecil, nilainya) dipakai di luar method. - E0425: tidak bisa menemukan nilai, fungsi, atau (sejak Rust 1.93) tipe dengan nama biasa.
- E0412: kode lama untuk “cannot find type”, sekarang dilaporkan sebagai E0425.
- E0405: tidak bisa menemukan sebuah trait, biasanya karena kurang baris
use. - E0401:
Selfdariimplluar dipakai di dalam fungsi bersarang, ditunjukkan di atas. - Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Di mana kamu bisa memakai Self sebagai tipe?
2. fn make_user() -> Self di level atas memberi E0411. Apa perbaikan yang biasa?
3. Di dalam impl Counter, apa yang dibuat oleh Self { count: 0 }?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0411 — Rust error codes index (bahasa Inggris): penjelasan resmi tentang apa arti
Self, dan kenapa ia hanya bekerja di impl, trait, atau definisi tipe. - Method Syntax — The Rust Book (bahasa Inggris): associated function seperti
fn square(size: u32) -> Self, dan cara kerjaSelfdi dalamimpl. - The
Selfkeyword — standard library docs (bahasa Inggris): artiSelfdi impl, trait, dan definisi tipe. Selfin paths — The Rust Reference (bahasa Inggris): aturan persisnya, termasuk kenapa item bersarang tidak bisa memakaiSelfdari luar.