Error Rust E0255: the name is defined multiple times (import vs item lokal)
E0255 artinya: sebuah baris use dan sesuatu yang kamu definisikan sendiri punya nama yang sama. Contoh klasiknya: kamu meng-import std::io::Error di bagian atas file, lalu di bawahnya menulis enum Error buatanmu sendiri. Rust tidak bisa membiarkan satu nama berarti dua hal, jadi ia berhenti. Error ini sangat sering muncul saat kamu mulai menulis tipe error sendiri, dan perbaikannya cukup satu baris pendek. Berbeda dengan E0412, kode ini tidak berubah di rilis-rilis terbaru: rustc 1.97 masih melaporkannya sebagai E0255. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0255]: the name `Error` is defined multiple times --> src/main.rs:3:1 |1 | use std::io::Error; | -------------- previous import of the type `Error` here2 |3 | enum Error { // ❌ nama sama dengan import di baris 1 | ^^^^^^^^^^ `Error` redefined here | = note: `Error` must be defined only once in the type namespace of this modulehelp: you can use `as` to change the binding name of the import |1 | use std::io::Error as OtherError; | +++++++++++++
warning: unused import: `std::io::Error` --> src/main.rs:1:5 |1 | use std::io::Error; | ^^^^^^^^^^^^^^Ini program yang menghasilkan error tersebut:
use std::io::Error;
enum Error { // ❌ nama sama dengan import di baris 1 EmptyName, TooLong(usize),}
fn check_name(name: &str) -> Result<(), Error> { if name.is_empty() { return Err(Error::EmptyName); } if name.len() > 10 { return Err(Error::TooLong(name.len())); } Ok(())}
fn main() { match check_name("") { Ok(()) => println!("nama sudah benar"), Err(Error::EmptyName) => println!("nama kosong"), Err(Error::TooLong(n)) => println!("nama punya {} huruf, maksimal 10", n), }}Apa artinya
Section titled “Apa artinya”rustc menunjuk ke tiga hal:
- Baris
---(baris 1): “previous import of the typeErrorhere” (import sebelumnya untuk tipeErrorada di sini). Barisuseitu sudah memasukkan namaErrorke modul ini. - Baris
^^^(baris 3): “Errorredefined here” (Errordidefinisikan ulang di sini).enum Errorbuatanmu mencoba memakai nama yang sama. help:-nya menawarkan jalan keluar: beri import itu nama lokal yang lain denganas.
warning: unused import (import tidak dipakai) di bawahnya adalah petunjuk yang berguna. Artinya, tidak ada bagian kodemu yang benar-benar memakai std::io::Error (setiap Error di program ini maksudnya enum buatanmu). Kalau begitu, kamu cukup menghapus baris 1. Kalau kamu memang butuh keduanya, baca terus.
Catatannya menyebut type namespace (namespace tipe). Tipe, trait, dan modul berbagi satu daftar nama; fungsi, konstanta, dan static berbagi daftar lain. Jadi use std::mem::swap; ditambah fn swap buatanmu sendiri adalah error yang sama, tapi di “value namespace” (namespace nilai).
Bayangkan sebuah kelas dengan dua murid bernama Andi. Guru tidak bisa lagi sekadar memanggil “Andi”. Salah satunya butuh nama panggilan, seperti “Andi B.”, dan itulah persisnya yang diberikan as kepada sebuah import.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Sebuah nama di dalam modul menunjuk ke tepat satu item. Saat Rust membaca Error::EmptyName di baris 10, ia harus tahu Error mana yang kamu maksud, dan ia menolak menebak. Kalau diam-diam memilih enum-mu, baris use-mu jadi tidak berguna; kalau memilih io::Error, enum-mu tidak bisa dipakai. Apa pun pilihannya, pilihan diam-diam akan menyembunyikan sebuah kesalahan.
Karena itulah E0255 bersaudara dengan E0428 (dua item buatanmu sendiri dengan satu nama) dan E0252 (dua baris use dengan satu nama). Aturannya sama: satu nama, satu hal, per modul. Lihat Modul untuk cara kerja use.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Ganti nama import dengan as
Section titled “Perbaikan 1: Ganti nama import dengan as”Pilih ini kalau kamu butuh kedua tipe di file yang sama, dan itu cukup sering: Error buatanmu untuk aturan aplikasimu, dan io::Error untuk file dan jaringan. Beri import itu nama panggilan yang menunjukkan asalnya. IoError lebih enak dibaca daripada nama sementara dari rustc, OtherError:
use std::io::Error as IoError;use std::io::ErrorKind;
#[derive(Debug)]enum Error { EmptyName, TooLong(usize),}
fn check_name(name: &str) -> Result<(), Error> { if name.is_empty() { return Err(Error::EmptyName); } if name.len() > 10 { return Err(Error::TooLong(name.len())); } Ok(())}
fn save_name(name: &str) -> Result<(), IoError> { if name == "root" { return Err(IoError::new(ErrorKind::PermissionDenied, "nama itu sudah dicadangkan")); } Ok(())}
fn main() { println!("{:?}", check_name("Ferris")); println!("{:?}", check_name("")); println!("{:?}", check_name("Ferris the Crab")); match save_name("root") { Ok(()) => println!("tersimpan"), Err(e) => println!("error io: {}", e), }}Output:
Ok(())Err(EmptyName)Err(TooLong(15))error io: nama itu sudah dicadangkanas hanya mengganti nama di file ini. Di tempat lain, tipenya tetap std::io::Error.
Perbaikan 2: Import modulnya, bukan tipenya
Section titled “Perbaikan 2: Import modulnya, bukan tipenya”Pilih ini kalau kamu ingin setiap Error menunjukkan asalnya di setiap tempat ia dipakai. Import modul induknya dengan use std::io; lalu tulis io::Error. Error buatanmu tetap memakai nama pendeknya. Banyak programmer Rust lebih suka gaya ini untuk tipe dengan nama umum seperti Error dan Result:
use std::io;
enum Error { EmptyName,}
fn check_name(name: &str) -> Result<(), Error> { if name.is_empty() { return Err(Error::EmptyName); } Ok(())}
fn save_name(name: &str) -> Result<(), io::Error> { if name == "root" { return Err(io::Error::new(io::ErrorKind::PermissionDenied, "nama yang dicadangkan")); } Ok(())}
fn main() { if let Err(Error::EmptyName) = check_name("") { println!("nama kosong"); } if let Err(e) = save_name("root") { println!("error io: {}", e); }}Output:
nama kosongerror io: nama yang dicadangkanPerbaikan 3: Ganti nama item buatanmu sendiri
Section titled “Perbaikan 3: Ganti nama item buatanmu sendiri”Pilih ini kalau tipemu akan dipakai di banyak file, atau oleh orang lain. Nama yang spesifik seperti NameError atau AppError lebih jelas daripada Error kedua, dan baris use-nya bisa tetap seperti semula:
use std::io::Error;
#[derive(Debug)]enum NameError { EmptyName, TooLong(usize),}
fn check_name(name: &str) -> Result<(), NameError> { if name.is_empty() { return Err(NameError::EmptyName); } if name.len() > 10 { return Err(NameError::TooLong(name.len())); } Ok(())}
fn main() { println!("{:?}", check_name("Ferris the Crab")); let disk = Error::other("disk penuh"); println!("{}", disk);}Output:
Err(TooLong(15))disk penuhUntuk proyek yang lebih besar, crate thiserror membuat enum error seperti ini jauh lebih singkat untuk ditulis. Lihat Error Kustom.
Perbaikan 4: Hapus import yang tidak kamu pakai
Section titled “Perbaikan 4: Hapus import yang tidak kamu pakai”Pilih ini kalau rustc juga menampilkan warning: unused import, seperti pada error di atas. Import itu sisa dari kode lama, atau ditambahkan oleh editor-mu. Hapus barisnya, dan program di awal halaman ini langsung jalan seperti yang ditulis:
enum Error { EmptyName, TooLong(usize),}
fn check_name(name: &str) -> Result<(), Error> { if name.is_empty() { return Err(Error::EmptyName); } if name.len() > 10 { return Err(Error::TooLong(name.len())); } Ok(())}
fn main() { match check_name("") { Ok(()) => println!("nama sudah benar"), Err(Error::EmptyName) => println!("nama kosong"), Err(Error::TooLong(n)) => println!("nama punya {} huruf, maksimal 10", n), }}Output:
nama kosongDi mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”Fungsi buatanmu dengan nama dari std. use std::mem::swap; ditambah fn swap(a: &mut i32, b: &mut i32) memberi E0255 dengan “previous import of the value swap here” dan catatan “value namespace”. Perbaikannya: beri nama swap_values pada fungsimu, atau hapus import-nya kalau kamu memang ingin menulis versimu sendiri.
Copy-paste antarmodul. Kamu memindahkan struct User ke mod models, menambahkan use models::User; di bagian atas, tapi lupa menghapus struct User yang lama di main.rs. Perbaikannya: hapus salinan lamanya, supaya User hanya berarti yang ada di models.
Trait dengan nama dari std. use std::fmt::Display; dan trait Display buatanmu bentrok dengan cara yang sama (“previous import of the trait Display”). Perbaikannya: ganti nama trait-mu (Describe, Render), atau tulis use std::fmt; dan fmt::Display.
Perlu diketahui: import glob seperti use std::io::*; tidak pernah menyebabkan E0255. Item buatanmu sendiri diam-diam menang atas nama yang masuk lewat *. Itu praktis, tapi juga bisa menyembunyikan Error mana yang sedang kamu pakai, jadi import yang eksplisit biasanya lebih jelas.
Error terkait
Section titled “Error terkait”- E0252: dua baris
usememasukkan nama yang sama, sepertifmt::Resultdanio::Result. - E0428: dua item buatanmu sendiri bernama sama, sering karena mencoba overloading sebuah fungsi.
- E0592: dua method dengan nama yang sama di blok
impl. - E0432: baris
useitu sendiri menunjuk ke sesuatu yang tidak ada. - E0425: masalah kebalikannya: nama yang sama sekali tidak didefinisikan di tempat kamu memakainya.
- Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. File-mu diawali use std::fmt::Result; dan di bawahnya mendefinisikan enum Result { Pass, Fail }. Error apa yang kamu dapat?
2. Kamu butuh std::io::Error dan enum Error buatanmu sendiri di satu file. Apa perbaikan yang rapi?
3. rustc menampilkan E0255 dan juga warning: unused import: std::io::Error. Apa yang diberitahukan warning itu?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0255 — Rust error codes index (bahasa Inggris): penjelasan resmi, dengan
use bar::foo;yang bentrok denganfn foo, diperbaiki denganasatau path induknya. - Providing New Names with the
asKeyword — The Rust Book (bahasa Inggris): caraasmengganti nama sebuah import, dengan contoh dua tipeResult. - Use declarations — The Rust Reference (bahasa Inggris): semua bentuk
use, termasukas, grup, dan glob. - Namespaces — The Rust Reference (bahasa Inggris): type namespace dan value namespace yang disebut di catatan error-nya.
- The
usedeclaration — Rust by Example (bahasa Inggris): contoh singkat yang bisa dijalankan tentang meng-import dan mengganti nama.