Error Rust E0689: can't call method on ambiguous numeric type (tipe angka ambigu)
E0689 artinya: kamu memanggil method pada sebuah angka, tapi Rust belum tahu angka itu jenisnya apa. 2 bisa berupa i32, u8, u64, dan lainnya, dan masing-masing punya method pow sendiri. Kamu cukup memberi tahu Rust mana yang kamu maksud, biasanya dengan beberapa karakter tambahan seperti 2_i32 atau let x: f64. rustc bahkan menunjukkan di mana kamu harus menaruhnya. (Halaman ini bagian dari Penjelasan error compiler Rust.)
Pesan error-nya
Section titled “Pesan error-nya”error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> src/main.rs:2:16 |2 | let kb = 2.pow(10); // ❌ `2` ini integer jenis apa? | ^^^ |help: you must specify a concrete type for this numeric value, like `i32` |2 | let kb = 2_i32.pow(10); // ❌ `2` ini integer jenis apa? | ++++Artinya: method pow tidak bisa dipanggil pada tipe angka yang masih ambigu, {integer}. rustc menyarankan untuk menyebut tipe yang konkret, misalnya i32.
Ini program yang menghasilkan error tersebut:
fn main() { let kb = 2.pow(10); // ❌ `2` ini integer jenis apa? println!("{}", kb);}Hal yang sama terjadi pada bilangan desimal. Di sini angkanya disimpan dulu di sebuah variabel, jadi rustc menyarankan tipe untuk variabelnya:
error[E0689]: can't call method `sqrt` on ambiguous numeric type `{float}` --> src/main.rs:3:18 |3 | let root = x.sqrt(); // ❌ `x` ini f32 atau f64? | ^^^^ |help: you must specify a type for this binding, like `f32` |2 | let x: f32 = 2.0; | +++++Artinya: sqrt tidak bisa dipanggil pada {float} yang ambigu, dan rustc menyarankan memberi tipe pada variabel x, misalnya f32.
fn main() { let x = 2.0; let root = x.sqrt(); // ❌ `x` ini f32 atau f64? println!("{}", root);}Apa artinya
Section titled “Apa artinya”{integer} dan {float} adalah cara rustc bilang “sebuah angka yang tipe pastinya belum kupilih”. {integer} adalah salah satu tipe bilangan bulat (i8 sampai i128, u8 sampai u128, isize, usize). {float} adalah f32 atau f64.
Tanda ^^^ menunjuk ke nama method-nya. Sebuah method dimiliki oleh sebuah tipe: ada i32::pow, u64::pow, f32::sqrt, f64::sqrt, dan seterusnya. Hasilnya berbeda-beda (i32 tidak muat untuk 2 pangkat 40, sedangkan u64 muat). Untuk memanggil salah satunya, Rust harus tahu tipenya di titik itu dalam kode, dan di sini Rust belum tahu.
Ini seperti bertanya ke pelayan toko “berapa harganya 2?”. Dua apa? Dua apel dan dua TV harganya jauh berbeda. Begitu kamu bilang “2 apel”, jawabannya gampang.
Kenapa Rust melakukan ini
Section titled “Kenapa Rust melakukan ini”Rust memang punya tipe angka default. Kalau tidak ada hal lain yang menentukan, bilangan bulat menjadi i32 dan bilangan desimal menjadi f64. Lihat Integer (bilangan bulat) dan Floating-point (bilangan desimal).
Tapi default itu adalah pilihan terakhir. Rust membaca dulu sisa fungsinya untuk melihat apakah ada yang menentukan tipenya, misalnya angka itu dikirim ke fungsi yang menerima u8. Baru di akhir sekali Rust memakai i32 atau f64. Pemanggilan method tidak bisa menunggu selama itu: Rust perlu tahu pow yang mana yang dipanggil sebelum bisa memeriksa argumen dan tipe hasilnya. Jadi daripada menebak, Rust berhenti dan bertanya padamu.
Ini juga berarti kode yang datang belakangan tidak membantu. Bahkan let y: u64 = x.pow(10); tetap memberi E0689, karena Rust harus memilih tipe x sebelum memanggil pow, sedangkan u64 itu hanya ada di hasilnya. Yang membantu adalah memberi tipe pada angkanya sebelum pemanggilan method.
Cara memperbaikinya
Section titled “Cara memperbaikinya”Perbaikan 1: Tambahkan sufiks tipe pada angkanya
Section titled “Perbaikan 1: Tambahkan sufiks tipe pada angkanya”Pilih ini kalau kamu memanggil method langsung pada sebuah literal, seperti 2.pow(10) atau 2.0.sqrt(). Tulis tipenya tepat setelah angkanya. Tanda _ boleh tidak dipakai, gunanya hanya supaya mudah dibaca: 2_i32 dan 2i32 sama saja.
Untuk bilangan desimal, rustc menyarankan f32, tapi f64 adalah default Rust dan lebih presisi. Pilih f64, kecuali kamu punya alasan untuk menghemat memori.
fn main() { let kb = 2_i32.pow(10); // ✅ sebuah i32 let big = 2_u64.pow(40); // ✅ sebuah u64: 2^40 tidak muat di i32 let root = 2.0_f64.sqrt(); // ✅ sebuah f64 let dist = (-7_i32).abs(); // ✅ pakai tanda kurung, karena `-` datang sebelum pemanggilan method
println!("2^10 = {}", kb); println!("2^40 = {}", big); println!("sqrt(2) = {}", root); println!("|-7| = {}", dist);}Output:
2^10 = 10242^40 = 1099511627776sqrt(2) = 1.4142135623730951|-7| = 7Pilih tipe yang cukup besar untuk hasilnya. 2_i32.pow(40) bisa di-compile, tapi hasilnya overflow dan menyebabkan panic di build debug. Lihat Integer overflow.
Perbaikan 2: Beri tipe pada variabelnya
Section titled “Perbaikan 2: Beri tipe pada variabelnya”Pilih ini kalau angkanya disimpan dulu di sebuah variabel, seperti let x = 2.0;. Inilah yang disarankan baris help: dari rustc. Tambahkan : tipe setelah nama variabelnya:
fn main() { let x: f64 = 2.0; // ✅ sekarang x adalah f64 println!("{:.3}", x.sqrt());
let side: f64 = 3.5; println!("luas = {}", side.powi(2));
let temperature: i32 = -5; println!("{} derajat dari nol", temperature.abs());
let base: u64 = 2; let y = base.pow(10); // y juga u64 println!("{}", y);}Output:
1.414luas = 12.255 derajat dari nol1024Sufiks pada nilainya juga sama bagusnya: let x = 2.0_f64;. Pakai yang menurutmu lebih mudah dibaca. Lihat Anotasi tipe.
Perbaikan 3: Beri tipe pada variabel loop atau argumen closure
Section titled “Perbaikan 3: Beri tipe pada variabel loop atau argumen closure”Pilih ini kalau angkanya berasal dari sebuah range, seperti for i in 1..=3 atau (1..=5).map(|n| ...). Variabel i atau n bertipe {integer}, dan tidak ada let yang bisa diberi anotasi. rustc menunjuk ke variabelnya:
error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> src/main.rs:3:26 |2 | for i in 1..=3 { | - you must specify a type for this binding, like `i32`3 | println!("{}", i.pow(2)); | ^^^Artinya: rustc meminta kamu memberi tipe pada variabel i, misalnya i32.
Taruh sufiksnya di salah satu ujung range, atau beri tipe pada argumen closure-nya:
fn main() { for i in 1..=3_u32 { // ✅ seluruh range sekarang bertipe u32 println!("{} kuadrat adalah {}", i, i.pow(2)); }
// bisa dengan sufiks pada range... let total: u32 = (1..=5_u32).map(|n| n.pow(2)).sum(); // ...atau dengan tipe pada argumen closure let total2: u32 = (1..=5).map(|n: u32| n.pow(2)).sum(); println!("jumlah kuadrat: {} dan {}", total, total2);}Output:
1 kuadrat adalah 12 kuadrat adalah 43 kuadrat adalah 9jumlah kuadrat: 55 dan 55Perhatikan bahwa let total: u32 = ... saja tidak cukup: rustc butuh tipe n di dalam closure, sebelum sampai ke .sum(). Satu sufiks pada range sudah membereskan semuanya.
Di mana biasanya kamu melihatnya
Section titled “Di mana biasanya kamu melihatnya”abs() pada angka negatif. let x = -5; x.abs() memberi can't call method `abs` on ambiguous numeric type `{integer}`. Perbaikannya: let x: i32 = -5;. Hati-hati dengan sufiks pada literalnya: -5_i32.abs() berarti -(5_i32.abs()), yang hasilnya -5. Pakai tanda kurung: (-5_i32).abs().
Hitungan cepat di main atau di test. let area = 3.14 * r * r; berjalan lancar, karena * adalah operator, bukan method. Error-nya baru muncul begitu kamu memanggil method seperti .sqrt(), .round(), atau .powi(). Perbaikannya: let r: f64 = 2.0;.
Vec berisi angka. Dengan let nums = vec![1, 2, 3];, nums.iter().map(|n| n.pow(2)) memberi kode lain, E0599, no method named `pow` found for reference `&{integer}`, karena di sini n adalah referensi. Perbaikannya sama: vec![1_i32, 2, 3] atau let nums: Vec<i32> = vec![1, 2, 3];.
Error terkait
Section titled “Error terkait”- E0282: type annotations needed: Rust sama sekali tidak bisa menebak tipenya, misalnya untuk
Vec::new()atau.collect(). Idenya sama: sebutkan tipenya. - E0610: primitive type doesn’t have fields:
.somethingtanpa()pada{integer}, sepertix.abspadahal maksudnyax.abs(). - E0599: no method named x found: tipenya sudah diketahui, tapi tidak punya method itu, atau (seperti di atas) berupa referensi ke
{integer}. - E0308: mismatched types: error yang mungkin muncul berikutnya, kalau tipe yang kamu pilih tidak cocok dengan tempat angka itu dipakai.
- Semua error compiler: daftar lengkap halaman error.
Kuis singkat
Section titled “Kuis singkat”Kuis singkat
1. Baris mana yang bisa di-compile?
2. Kalau tidak ada hal lain yang menentukan, tipe apa yang diberikan Rust untuk 7 dan 7.0?
3. for i in 0..10 { println!("{}", i.pow(2)); } memberi E0689. Apa perbaikan paling sederhana?
Skor: 0 / 3
Bacaan lebih lanjut
Section titled “Bacaan lebih lanjut”- E0689 — Rust error codes index (bahasa Inggris): penjelasan resmi error ini.
- Data Types — The Rust Book (bahasa Inggris): tipe integer dan float, literal angka dengan sufiks seperti
57u8, dan defaulti32/f64. - Literals — Rust by Example (bahasa Inggris): bagaimana sufiks seperti
1u32dan1.0f64menentukan tipe. - Integer literal expressions — The Rust Reference (bahasa Inggris): aturan persis bagaimana sebuah literal mendapat tipenya, termasuk fallback ke
i32. f64::sqrt— dokumentasi standard library (bahasa Inggris): method float (sqrt,powi,round…) yang butuh tipe yang sudah diketahui.