Rust'ta error[E0277], bir tipin o noktada beklenen trait'i uygulamadığını söyler: örneğin {:?} ile yazdırılan bir generic tipte Debug sınırı eksiktir, i32 ile f64 çarpılmaya çalışılmaktadır ya da ? operatörü Result döndürmeyen bir fonksiyonda kullanılmaktadır. error[E0308]: mismatched types ise beklenen tip ile verilen tipin uyuşmadığını bildirir; en sık nedenleri fonksiyon sonundaki fazladan noktalı virgül, if ve else dallarının farklı tip döndürmesi ve String beklenen yere &str vermektir. E0425 bulunamayan bir değer adını, E0433 ise içe aktarılmamış bir tip veya modülü gösterir.
Bu yazıda dört hatayı Rust 1.99.1'in gerçek mesajlarıyla, en sık karşılaşılan durumlar üzerinden inceliyoruz. Trait ve generic kavramlarının kendisi trait tanımlama ve impl ile Rust generics yazılarında, tipler arası dönüşüm From, Into ve TryFrom yazısında anlatılıyor. Sahiplik ve ödünç alma kaynaklı hatalar için E0382 ve E0502 yazılarına bakabilirsiniz.
E0277: trait bound is not satisfied

Hata kodu dizinine göre E0277, belirli bir trait'i bekleyen bir yerde o trait'i uygulamayan bir tip kullandığınızda çıkar. En açık hali, kendi trait'inizi isteyen bir generic fonksiyonu bu trait'i uygulamayan bir tiple çağırmaktır:
trait Kaydedilebilir {
fn kaydet(&self) -> String;
}
fn arsivle<T: Kaydedilebilir>(oge: T) {
println!("{}", oge.kaydet());
}
fn main() {
arsivle(5i32);
}
// error[E0277]: the trait bound `i32: Kaydedilebilir` is not satisfiedMesaj iki yeri birbirine bağlar: çağrıdaki 5i32 değeri için the trait `Kaydedilebilir` is not implemented for `i32` der, ardından bir not ile sınırın nerede konduğunu gösterir: required by this bound in `arsivle`. Rust 1.99.1 burada trait'in hiç uygulaması olmadığını da fark edip bir tane eklemeyi önerir. Çözüm tam olarak budur:
trait Kaydedilebilir {
fn kaydet(&self) -> String;
}
impl Kaydedilebilir for i32 {
fn kaydet(&self) -> String {
format!("sayı:{self}")
}
}
fn arsivle<T: Kaydedilebilir>(oge: T) {
println!("{}", oge.kaydet());
}
fn main() {
arsivle(5i32);
}
// çıktı: sayı:5Generic fonksiyonda sınır eksikse
E0277'nin ikinci yüzü, hatanın çağrıda değil fonksiyon tanımında çıkmasıdır. Aşağıdaki fonksiyon yalnızca Debug uygulayan i32 ile çağrılıyor, yine de derlenmiyor:
fn yazdir<T>(deger: T) {
println!("{:?}", deger);
}
fn main() {
yazdir(5);
}
// error[E0277]: `T` doesn't implement `Debug`Hata kodu dizini bunun nedenini açıklar: generic fonksiyon, olası tüm girdi tipleri için çalışmak zorundadır ve Rust yalnızca çağrılan fonksiyonun imzasına bakar. Bu yüzden her tip parametresinin ihtiyaç duyduğu tüm yetenekler imzada yazmalıdır. Derleyici T için std::fmt::Debug sınırı eklemeyi önerir. Sınırı ekledikten sonra fonksiyon Debug uygulayan her tiple çağrılabilir:
use std::fmt::Debug;
fn yazdir<T: Debug>(deger: T) {
println!("{:?}", deger);
}
fn main() {
yazdir(5);
yazdir("metin");
yazdir(vec![1.5, 2.0]);
}
// çıktı: 5
// çıktı: "metin"
// çıktı: [1.5, 2.0]Birden çok sınır gerektiğinde T: Debug + Clone biçiminde birleştirebilir veya imza uzadıysa where yan tümcesine taşıyabilirsiniz; bu yazımlar trait yazısında ayrıntılı.
Kendi tipinizi {} ile yazdırmak
println!("{}", x) biçimi tipin Display trait'ini uygulamasını ister. Kendi struct'ınız için bu trait otomatik gelmez:
struct Urun {
ad: String,
fiyat: u32,
}
fn main() {
let u = Urun { ad: String::from("Kalem"), fiyat: 15 };
println!("{}", u);
}
// error[E0277]: `Urun` doesn't implement `std::fmt::Display`Derleyici iki yol önerir: hata ayıklama çıktısı yeterliyse {:?} kullanmak (bunun için tipe #[derive(Debug)] eklemeniz gerekir) ya da kullanıcıya gösterilecek biçimi Display uygulayarak kendiniz tanımlamak. Display türetilemez, elle yazılır:
use std::fmt;
#[derive(Debug)]
struct Urun {
ad: String,
fiyat: u32,
}
impl fmt::Display for Urun {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ({} TL)", self.ad, self.fiyat)
}
}
fn main() {
let u = Urun { ad: String::from("Kalem"), fiyat: 15 };
println!("{}", u);
println!("{:?}", u);
}
// çıktı: Kalem (15 TL)
// çıktı: Urun { ad: "Kalem", fiyat: 15 }Biçimlendirme belirteçlerinin tamamı Display ve Debug formatlama, türetilebilir trait'ler derive ile Debug, Clone, PartialEq yazısında.
Farklı sayı tiplerini birlikte kullanmak
Rust sayı tiplerini kendiliğinden birbirine çevirmez. i32 ile f64 çarpmak bir tip hatası değil, trait hatası olarak raporlanır, çünkü * operatörü Mul trait'i üzerinden çalışır ve i32 için Mul<f64> uygulaması yoktur:
fn main() {
let adet: i32 = 3;
let fiyat: f64 = 2.5;
let toplam = adet * fiyat;
println!("{toplam}");
}
// error[E0277]: cannot multiply `i32` by `f64`Çözüm, bir tarafı açıkça diğer tipe çevirmektir. i32 değerinin f64 tipine dönüşümü kayıpsız olduğu için standart kütüphane From uygulaması sunar. as ile dönüşüm de mümkündür, ama kayıplı dönüşümlerde sessizce kırpma veya yuvarlama yapabildiği için kayıpsız bir yol varsa from tercih edilir:
fn main() {
let adet: i32 = 3;
let fiyat: f64 = 2.5;
let toplam = f64::from(adet) * fiyat;
println!("{toplam}");
}
// çıktı: 7.5Vec veya dilimi i32 ile indekslemek
Dilim ve vektör indeksleri usize tipindedir. Başka bir tamsayı tipiyle indekslemek E0277 verir ve mesaj bunu açıkça söyler: slice indices are of type `usize` or ranges of `usize`. Mesajdaki [{integer}], vektör elemanlarının tipinin henüz kesinleşmemiş bir tamsayı olduğunu gösterir:
fn main() {
let v = vec![10, 20, 30];
let i: i32 = 1;
println!("{}", v[i]);
}
// error[E0277]: the type `[{integer}]` cannot be indexed by `i32`Negatif bir i32 değerinin geçerli bir indeks olamayacağını unutmayın. usize::try_from dönüşümü negatif değerlerde hata döndürür; bu, as usize yazmaktan daha güvenlidir. get metodu ile birleştirildiğinde sınır dışı indekslerde de panik yerine None alırsınız:
fn main() {
let v = vec![10, 20, 30];
let i: i32 = 1;
let j = usize::try_from(i).expect("negatif indeks");
println!("{}", v[j]);
let k: i32 = -1;
println!("{:?}", usize::try_from(k).ok().and_then(|x| v.get(x)));
}
// çıktı: 20
// çıktı: Nonecollect ile yanlış tipte koleksiyon kurmak
collect hedef koleksiyonu tip bilgisinden seçer ve bunun için FromIterator trait'ine dayanır. Iterator'ün ürettiği eleman tipi hedefle uyuşmuyorsa sonuç yine E0277'dir. Aşağıda split metni &str parçalarına ayırır, ama hedef Vec<i32> olarak yazılmış:
fn main() {
let sayilar: Vec<i32> = "1,2,3".split(',').collect();
println!("{sayilar:?}");
}
// error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `&str`Parçaları önce sayıya çevirmek gerekir. Dönüşüm başarısız olabileceği için Result değerlerinden oluşan bir iterator'ü Result<Vec<i32>, _> içine toplamak, ilk hatada duran ve hatayı döndüren düzgün bir yoldur:
fn main() {
let sayilar: Vec<i32> = "1,2,3".split(',').map(|s| s.parse().unwrap()).collect();
println!("{sayilar:?}");
let sonuc: Result<Vec<i32>, _> = "1,x,3".split(',').map(|s| s.parse::<i32>()).collect();
println!("{sonuc:?}");
}
// çıktı: [1, 2, 3]
// çıktı: Err(ParseIntError { kind: InvalidDigit })? operatörünü main içinde kullanmak
? operatörü hata durumunda değeri çağırana döndürür; bu yüzden yalnızca Result, Option veya uyumlu başka bir tip döndüren fonksiyonlarda kullanılabilir. Dönüş tipi () olan sıradan bir main içinde kullanmak E0277 verir:
fn main() {
let n: i32 = "42".parse()?;
println!("{n}");
}
// error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)Kitabın hata yönetimi bölümünde gösterildiği gibi main fonksiyonu Result döndürebilir. Aşağıda ilk dönüşüm başarılı olur, ikincisi başarısız olur ve main hatayı döndürür. Program standart hata çıktısına hatanın Debug biçimini yazar ve sıfırdan farklı bir kodla, denememizde 1 ile çıkar:
use std::num::ParseIntError;
fn main() -> Result<(), ParseIntError> {
let n: i32 = "42".parse()?;
println!("{n}");
let m: i32 = "kırk".parse()?;
println!("{m}");
Ok(())
}
// çıktı: 42
// çıktı: Error: ParseIntError { kind: InvalidDigit }Farklı hata tiplerini tek bir main içinde ? ile kullanmak için Box<dyn Error> veya kendi hata tipiniz gerekir; bu konu Result ve hata yönetimi ile özel hata tipi ve Error trait yazılarında.
E0308: mismatched types
E0308, bir ifadenin derleyicinin beklediğinden farklı bir tipte olduğunu söyler. Mesajın kalbi her zaman expected X, found Y kalıbıdır ve bir etiket de beklentinin nereden doğduğunu gösterir (expected due to this). Hata kodu dizinine göre en yaygın durum, fonksiyon parametresiyle uyuşmayan bir argüman vermektir; aşağıda bunun dışında da çok sık karşılaşılan dört durumu inceliyoruz.
Fonksiyon sonundaki noktalı virgül
Rust'ta fonksiyonun son ifadesi dönüş değeridir. Sonuna noktalı virgül koyduğunuzda ifade deyime dönüşür ve değer üretmez; fonksiyon bu durumda () döndürür:
fn kare(x: i32) -> i32 {
x * x;
}
fn main() {
println!("{}", kare(4));
}
// error[E0308]: mismatched typesRust 1.99.1 bu hatayı çok net açıklar: dönüş tipinde expected `i32`, found `()` yazar, fonksiyon adının altına gövdede kuyruk ifadesi veya return olmadığı için örtük olarak () döndürdüğünü not eder ve help: remove this semicolon to return this value der. Noktalı virgülü kaldırmak yeterlidir. İfade ile deyim farkı fonksiyonlar, ifade ve deyim yazısında ayrıntılı.
if ve else dallarının farklı tip döndürmesi
if bir ifade olduğu için her iki dalı aynı tipte değer üretmelidir. Mesaj bu kez `if` and `else` have incompatible types diye başlar ve ilk dalı beklentinin kaynağı olarak gösterir:
fn main() {
let stok = 0;
let durum = if stok > 0 { "var" } else { 0 };
println!("{durum}");
}
// error[E0308]: `if` and `else` have incompatible typesDallar aynı tipe getirilir. Burada ikisi de &str olunca kod derlendi ve yok yazdı. Bazen gerçekten iki farklı tür sonuç vardır; o zaman bir enum veya Option tanımlamak daha doğru bir modeldir. Kontrol akışı ifadeleri için if, loop, while ve for yazısına bakabilirsiniz.
String beklenen yere &str vermek
Bir dizgi sabitinin tipi &str tipidir, String değil. Parametresi String olan bir fonksiyona sabit vermek E0308 verir ve derleyici .to_string() ile dönüştürmeyi önerir:
fn selamla(ad: String) {
println!("Merhaba {ad}");
}
fn main() {
selamla("Zeynep");
}
// error[E0308]: mismatched typesÖneri işe yarar, ama fonksiyon metni yalnızca okuyorsa daha iyi çözüm parametreyi &str yapmaktır. Böylece hem sabitleri hem de &String değerlerini kabul eder; &String otomatik olarak &str tipine dönüşür. İki tip arasındaki fark String ve &str farkı yazısında:
fn selamla(ad: &str) {
println!("Merhaba {ad}");
}
fn main() {
selamla("Zeynep");
let sahipli = String::from("Kaan");
selamla(&sahipli);
}
// çıktı: Merhaba Zeynep
// çıktı: Merhaba KaanOption<T> değerini doğrudan T gibi kullanmak
Option<i32> bir i32 değildir; değer olmayabilir ve Rust bunu sizin ele almanızı ister:
fn main() {
let x: Option<i32> = Some(3);
let y: i32 = x;
println!("{y}");
}
// error[E0308]: mismatched typesMesaj expected `i32`, found `Option<i32>` der ve Option::expect çağırmayı önerir; ancak bu, değer None olduğunda panik demektir. Varsayılan bir değer kabul edilebilirse unwrap_or, iki durumu ayrı ele almak gerekiyorsa match daha güvenlidir. Option metotları için enum ve Option yazısına bakabilirsiniz:
fn main() {
let x: Option<i32> = Some(3);
let y: i32 = x.unwrap_or(0);
let z: i32 = match x {
Some(n) => n * 2,
None => 0,
};
println!("{y} {z}");
}
// çıktı: 3 6E0425: cannot find value in this scope
E0425, kullandığınız bir adın o kapsamda çözülemediğini söyler. Hata kodu dizini nedenleri sayar: adın yanlış yazılması, tanımın başka bir kapsamda kalması veya başka bir modüldeki öğenin use ile içe aktarılmamış ya da pub yapılmamış olması. Yazım hatalarında Rust 1.99.1 benzer adlı bir yerel değişkeni kendisi önerir:
fn main() {
let toplam = 10;
println!("{}", topla);
}
// error[E0425]: cannot find value `topla` in this scopeBu örnekte yardım satırı a local variable with a similar name exists diyerek toplam adını önerir. Değişken bir blok içinde tanımlandıysa ve blok dışında kullanılıyorsa, öneri gelmeyebilir; o durumda tanımın kapsamını kontrol edin. Başka bir modüldeki fonksiyonlar için yol ve görünürlük kuralları modül sistemi: mod, use, pub yazısında.
E0433: undeclared type or module
E0433, bir yolun başındaki tip, modül veya crate adının bulunamadığını bildirir. En sık örnek, HashMap tipini içe aktarmadan kullanmaktır; çünkü Vec ve String prelude içindeyken HashMap değildir. Hata kodu dizinindeki mesaj metni eski bir derleyiciye aittir; Rust 1.99.1 aynı kod için şunu yazdı:
fn main() {
let mut sayac = HashMap::new();
sayac.insert("a", 1);
println!("{:?}", sayac.get("a"));
}
// error[E0433]: cannot find type `HashMap` in this scopeYardım satırı doğrudan eklenecek satırı verir: use std::collections::HashMap;. Bu satırı dosyanın başına eklediğinizde kod derlenir. Hata kodu dizini iki durumu daha hatırlatır: harici bir crate kullanıyorsanız Cargo.toml dosyasına bağımlılık olarak eklenmiş olmalıdır; kendi crate'inizdeki bir modülü kullanıyorsanız yolun başına crate:: yazmanız gerekebilir. Bağımlılık eklemek için Cargo.toml ve bağımlılıklar yazısına bakabilirsiniz.
Derleyici mesajını okumanın kısa yolu

Bu dört hatada mesajlar benzer bir düzen izler ve okuma alışkanlığı kazanmak çözüm süresini kısaltır. İlk satır hata kodunu ve özeti verir. Ardından gelen --> satırı dosya, satır ve sütunu gösterir. Altı çizili ^^^ işaretleri sorunlu ifadeyi, tire işaretli ikincil etiketler ise beklentinin kaynağını gösterir. note: satırları bağlam verir (örneğin bir sınırın hangi fonksiyonda konduğunu), help: satırları ise somut bir düzeltme önerir. Son satırdaki rustc --explain E0277 komutu, hata kodu dizinindeki açıklamanın tamamını terminalde gösterir.
| Kod | Mesajın özü | İlk bakılacak yer | Tipik çözüm |
|---|---|---|---|
| E0277 | trait bound is not satisfied, doesn't implement | Hangi tip, hangi trait | impl yazmak, sınır eklemek, tip dönüştürmek |
| E0308 | mismatched types, expected X found Y | expected due to this etiketi | Noktalı virgül, dal tipleri, dönüşüm metodu |
| E0425 | cannot find value in this scope | Yazım ve kapsam | Adı düzeltmek, use veya pub eklemek |
| E0433 | cannot find type, use of undeclared type | use satırları ve Cargo.toml | use std::collections::HashMap gibi içe aktarma |
Sık yapılan hatalar
- Generic fonksiyonda sınırı gövdeye bakarak beklemek: Rust yalnızca imzaya bakar; gövdede kullandığınız her yetenek imzada sınır olarak yazmalıdır.
- Sayı tiplerini as ile gelişigüzel çevirmek: Kayıpsız dönüşümler için
From, başarısız olabilecekler içinTryFromkullanın;assessizce kırpabilir. - Option ve Result değerlerini unwrap ile susturmak: Derleyicinin önerdiği
expectpanik riskini taşır;match,unwrap_orveya?çoğu zaman daha doğrudur. - Display ile Debug'ı karıştırmak:
{}içinDisplay,{:?}içinDebuggerekir;Displaytüretilemez. - Fonksiyon sonuna alışkanlıkla noktalı virgül koymak: Değer döndürmesi gereken son satırda noktalı virgül, dönüşü
()yapar.
Sık Sorulan Sorular
E0277 bir tip hatası mı, trait hatası mı?
Trait hatasıdır, ama sonuç olarak bir tipin beklenen yeteneği taşımadığını söyler. Operatörler de trait'ler üzerinden çalıştığı için i32 * f64 gibi işlemler E0308 değil E0277 verir.
Derleyici neden i32 değerini otomatik olarak f64'e çevirmiyor?
Rust sayı tipleri arasında örtük dönüşüm yapmaz; dönüşümü açıkça yazmanızı ister. Bu sayede kayıp olabilecek dönüşümler kodda görünür kalır.
Hata kodu dizinindeki mesaj neden derleyicimin mesajından farklı?
Dizindeki örnek yorumlar bazı hata kodlarında eski derleyici sürümlerinin metnini yansıtır. Örneğin E0433 için dizin "failed to resolve" yazarken Rust 1.99.1 "cannot find type `HashMap` in this scope" yazdı. Hata kodu aynıdır; anlam değişmez.
? operatörünü Option döndüren fonksiyonda kullanabilir miyim?
Evet. Mesajın da belirttiği gibi ?, Result veya Option döndüren fonksiyonlarda kullanılabilir. Ancak aynı fonksiyonda Result ve Option değerlerini karıştırırsanız birini diğerine dönüştürmeniz gerekir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Rust öğrenme rehberi · Trait tanımlama · From, Into ve TryFrom · Result ve hata yönetimi · Display ve Debug · E0382 move hataları