Rust 2024 edition, dilin geriye dönük uyumsuz değişikliklerini topluca getiren en yeni edition'dır; Edition Guide'a göre Rust 1.85.0 ile yayımlandı. En görünür yenilikler şunlar: if ve while koşullarında let zincirleri, gen kelimesinin rezerve edilmesi, extern bloklarının ve bazı özniteliklerin unsafe olarak işaretlenme zorunluluğu, if let ile kuyruk ifadelerindeki geçici değerlerin daha erken bırakılması, std::env::set_var fonksiyonunun unsafe hale gelmesi ve Cargo tarafında rust-version bilen bağımlılık çözücüsü. Mevcut bir projeyi taşımak için önce cargo fix --edition çalıştırır, ardından Cargo.toml içinde edition = "2024" yazarsınız.
Bu yazıda her değişikliği Rust 1.99.1 ile hem 2021 hem 2024 edition'da derleyip gerçek çıktılarla gösteriyoruz ve küçük bir projeyi baştan sona geçiriyoruz. Rust'ın genel tanıtımı için Rust nedir yazısına, araçların kurulumu için Rust kurulumu: rustup ve Cargo rehberine bakabilirsiniz. Cargo'nun son sürümlerindeki araç değişiklikleri ise ayrı bir konu olduğu için Cargo son sürüm değişiklikleri yazısında ele alınıyor.
Edition nedir, Rust sürümünden farkı ne?
Rust sürümleri (1.85, 1.99 gibi) altı haftada bir çıkar ve kararlı bir özelliği bir daha kırmama sözü verir. Ancak bazen yeni bir anahtar kelime eklemek gibi uyumsuz değişiklikler gerekir. Edition mekanizması bu değişiklikleri isteğe bağlı hale getirir: her crate hangi edition ile derleneceğini kendisi seçer ve seçmediği sürece eski kurallarla derlenmeye devam eder. Edition Guide, async anahtar kelimesinin yalnızca 2018 ve sonrası seçildiğinde anahtar kelime sayılmasını buna örnek gösterir.
En önemli kural, farklı edition'lardaki crate'lerin birlikte sorunsuz çalışmasıdır. 2021 edition'da kalan bir kütüphaneyi 2024 edition'daki uygulamanızda kullanabilirsiniz; geçiş kararı her crate için özeldir ve ekosistemi bölmez. Bu yüzden edition değişiklikleri yüzeyseldir: derleyici hangi edition olursa olsun kodu aynı iç temsile indirger. Edition, Cargo.toml dosyasındaki edition anahtarıyla seçilir. Bu anahtar hiç yoksa Cargo 2015 edition'ı varsayar. cargo new ise en yeni kararlı edition'ı yazar; Cargo 1.99.1 ile oluşturduğumuz projede bu değer 2024 çıktı.
[package]
name = "araclar"
version = "0.1.0"
edition = "2024"Doğrudan rustc ile derlerken edition'ı --edition 2024 bayrağıyla verirsiniz. Bu yazıdaki tüm tek dosyalık örnekleri bu bayrakla, karşılaştırma gereken yerlerde ayrıca --edition 2021 ile derledik.
Değişikliklerin özet tablosu
| Değişiklik | Ne oldu | Geçişte yardımcı olan lint veya araç |
|---|---|---|
| let zincirleri | if ve while koşulunda && ile birden çok let | Gerekmez, yalnızca yeni olanak |
| gen anahtar kelimesi | gen artık rezerve, tanımlayıcı olamaz | keyword_idents_2024 (r#gen yapar) |
| Rezerve sözdizimi | #"foo"# ve ## gibi diziler hata | rust_2024_guarded_string_incompatible_syntax |
| if let geçici kapsamı | Geçici değer else dalından önce bırakılır | if_let_rescope |
| Kuyruk ifadesi geçicileri | Bloğun yerel değişkenlerinden önce bırakılır | tail_expr_drop_order (yalnızca uyarı) |
| unsafe extern | extern blokları unsafe extern olmalı | missing_unsafe_on_extern |
| unsafe öznitelikler | no_mangle, export_name, link_section için unsafe(...) | unsafe_attr_outside_unsafe |
| unsafe fn gövdesi | unsafe işlemler için ayrıca unsafe blok | unsafe_op_in_unsafe_fn (uyarı) |
| static mut referansları | static mut için & ve &mut varsayılan olarak hata | static_mut_refs (deny) |
| Prelude | Future ve IntoFuture prelude içinde | rust_2024_prelude_collisions |
| Box<[T]>.into_iter() | Referans yerine değer üretir | boxed_slice_into_iter |
| set_var, remove_var | unsafe fonksiyon oldu | deprecated_safe_2024 |
| Cargo resolver | edition 2024, resolver 3 demektir | Otomatik geçiş yok |
| Cargo.toml anahtar adları | [project], dev_dependencies gibi eski adlar kaldırıldı | cargo fix --edition düzeltir |
Tablodaki lint'lerin çoğu rust-2024-compatibility grubundadır ve cargo fix --edition çalıştırıldığında otomatik uygulanır. Aşağıda her birini sırayla açıyoruz.
Dil değişiklikleri

let zincirleri: if ve while koşullarında birden çok let
2024 edition'dan önce let yalnızca if let veya while let biçiminde, koşulun hemen başında kullanılabiliyordu. Artık koşul, && ile bağlanmış birden çok let ifadesi ve sıradan bool ifadelerinin karışımı olabilir. İç içe if let yazmaya gerek kalmaz. Sınır şudur: let ifadeleri koşulun en üst düzeyinde durmalıdır; || ile bağlamak veya parantez içine almak hâlâ yasaktır.
fn ilk_iki_toplam(sayilar: &[u8]) -> Option<u8> {
let mut it = sayilar.iter();
if let Some(a) = it.next()
&& let Some(b) = it.next()
&& *a > 0
{
a.checked_add(*b)
} else {
None
}
}
fn main() {
println!("{:?}", ilk_iki_toplam(&[10, 20, 30]));
println!("{:?}", ilk_iki_toplam(&[7]));
println!("{:?}", ilk_iki_toplam(&[200, 100]));
println!("{:?}", ilk_iki_toplam(&[0, 5]));
}
// çıktı: Some(30)
// çıktı: None
// çıktı: None
// çıktı: NoneÜçüncü satırdaki None, checked_add taşmayı yakaladığı için gelir; dördüncüsü ise *a > 0 koşulu sağlanmadığı için. Aynı dosyayı --edition 2021 ile derlediğimizde derleyici açıkça error: let chains are only allowed in Rust 2024 or later mesajını verdi. Edition Guide, bu özelliğin edition'a bağlı olmasının nedenini if let geçici değer kapsamının değişmesine dayandırır. Mevcut kodu bozmadığı için geçiş sırasında bir şey yapmanız gerekmez. Desen eşleştirmenin geri kalanı için match ve if let yazısına bakabilirsiniz.
gen artık rezerve bir anahtar kelime
gen kelimesi, ileride gelecek ve iterator yazmayı kolaylaştıracak gen bloklarına yer açmak için rezerve edildi. Bu yüzden 2024 edition'da gen adlı bir fonksiyon veya değişken tanımlayamazsınız:
fn gen() -> u32 {
42
}
fn main() {
println!("{}", gen());
}
// error: expected identifier, found reserved keyword `gen`Çözüm ham tanımlayıcı sözdizimidir: r#gen yazdığınızda ad, anahtar kelimeyle çakışmadan kullanılabilir ve kod her iki edition'da da derlenir. keyword_idents_2024 lint'i bu dönüşümü cargo fix --edition sırasında sizin yerinize yapar.
fn r#gen() -> u32 {
42
}
fn main() {
println!("{}", r#gen());
}
// çıktı: 42Benzer bir rezervasyon dizgi sözdiziminde de var: önek almayan korumalı dizgiler (#"foo"#) ve arada boşluk olmadan yan yana iki veya daha fazla # karakteri artık hata. Bu daha çok makro çağrılarını etkiler; rust_2024_guarded_string_incompatible_syntax lint'i gereken yerlere boşluk ekleyerek token'ların eskisi gibi ayrı okunmasını sağlar.
if let içindeki geçici değerler daha erken bırakılıyor
Bu, davranışı sessizce değiştirebilen nadir değişikliklerden biridir. if let DESEN = IFADE yazdığınızda IFADE hesaplanırken oluşan geçici değerler, 2021'de bütün if let ifadesi bitene kadar, yani else dalının sonuna kadar yaşıyordu. 2024'te ise then bloğu bittiğinde veya program else dalına girmeden hemen önce bırakılıyor. Farkı, Drop uygulayan küçük bir tiple görebilirsiniz:
struct Kilit(&'static str);
impl Drop for Kilit {
fn drop(&mut self) {
println!("{} bırakıldı", self.0);
}
}
impl Kilit {
fn deger(&self) -> Option<u8> {
None
}
}
fn main() {
if let Some(x) = Kilit("geçici kilit").deger() {
println!("değer: {x}");
} else {
println!("else dalı çalışıyor");
}
println!("if let bitti");
}
// --edition 2024 çıktısı:
// çıktı: geçici kilit bırakıldı
// çıktı: else dalı çalışıyor
// çıktı: if let bitti
// --edition 2021 çıktısı:
// çıktı: else dalı çalışıyor
// çıktı: geçici kilit bırakıldı
// çıktı: if let bittiEdition Guide'daki gerçek hayat örneği bir RwLock içerir: koşulda value.read() ile alınan okuma kilidi 2021'de else dalı boyunca tutulduğu için, o dalda value.write() ile yazma kilidi istemek kilitlenmeye yol açar. 2024'teki yeni sıra bu tuzağı ortadan kaldırır. Eski davranışa gerçekten ihtiyacınız varsa match kullanabilirsiniz; match ifadesinin geçici değerleri ifadenin sonuna kadar yaşamaya devam eder. if_let_rescope lint'i, özel Drop uygulayan bir geçici değer gördüğünde kodu match biçimine çevirmeyi önerir. Bu öneriyi körü körüne kabul etmeyin: kilit örneğinde match tam da kaçınmak istediğiniz kilitlenmeyi geri getirir.
Kuyruk ifadesindeki geçici değerler
Bir bloğun veya fonksiyonun son ifadesine kuyruk ifadesi denir. 2021'de bu ifadede oluşan geçici değerler, bloğun yerel değişkenlerinden daha uzun yaşıyordu. Bu da şaşırtıcı ödünç alma hatalarına yol açıyordu. Aşağıdaki kod 2021'de error[E0597]: `c` does not live long enough verir, 2024'te ise sorunsuz derlenir:
use std::cell::RefCell;
fn uzunluk() -> usize {
let c = RefCell::new("merhaba");
c.borrow().len()
}
fn main() {
println!("{}", uzunluk());
}
// --edition 2024 çıktısı:
// çıktı: 7
// --edition 2021: error[E0597]: `c` does not live long enoughDeğişikliğin bir de ters yüzü var: geçici değerin kapsamı daralabildiği için 2021'de derlenen bazı kodlar 2024'te derlenmez. Edition Guide'ın örneğinde blok içinde oluşturulan bir String referansı bloğun dışında kullanılıyor:
fn main() {
let x = { &String::from("1234") }.len();
println!("{x}");
}
// --edition 2021 çıktısı: 4
// --edition 2024: error[E0716]: temporary value dropped while borrowedÇözüm, blok ifadesini önce bir değişkene almaktır. Referansın doğrudan bir let ile bağlandığı durumda geçici değerin ömrü uzatılır ve sonraki satırda kullanılabilir:
fn main() {
let s = { &String::from("1234") };
let x = s.len();
println!("{x}");
}
// çıktı: 4Bu değişiklik için anlamı koruyan otomatik bir dönüşüm yok. tail_expr_drop_order lint'i, kuyruk ifadesinde özel Drop uygulayan bir geçici değer gördüğünde uyarı verir ama kodu değiştirmez; uyarıları tek tek incelemeniz gerekir. Bu tür hataların ayrıntısı E0597 ve lifetime hataları yazısında.
extern blokları artık unsafe extern
Yabancı fonksiyon bildirimlerinde imzanın doğru olduğunu derleyici denetleyemez; yanlış imza tanımsız davranışa yol açabilir. Bu sorumluluğu görünür kılmak için 2024'te extern bloklarının başına unsafe yazmak zorunlu. Edition Guide'a göre bu yazım Rust 1.82'den beri tüm edition'larda kullanılabiliyordu; 2024'te zorunlu oldu. Aşağıdaki kod 2021'de derlenip 5 yazar, 2024'te ise reddedilir:
extern "C" {
fn abs(x: i32) -> i32;
}
fn main() {
let n = unsafe { abs(-5) };
println!("{n}");
}
// error: extern blocks must be unsafeYeni yazımda blok içindeki her öğeyi ayrıca safe veya unsafe olarak işaretleyebilirsiniz. safe işaretli bir fonksiyon unsafe blok olmadan çağrılabilir; işaret konmayan öğeler ise varsayılan olarak unsafe kabul edilir:
unsafe extern "C" {
// abs her i32 değeriyle güvenle çağrılabilir; bunu biz taahhüt ediyoruz
safe fn abs(x: i32) -> i32;
}
fn main() {
let n = abs(-5);
println!("{n}");
}
// çıktı: 5missing_unsafe_on_extern lint'i bu anahtar kelimeyi otomatik ekler, fakat imzaların doğruluğunu kontrol etmez. Ham işaretçiler ve FFI için unsafe Rust ve ham işaretçiler yazısına bakabilirsiniz.
unsafe öznitelikler: no_mangle, export_name, link_section
Bu üç öznitelik sembol adlarını ve bağlama davranışını değiştirir. Bütün bağlanan kütüphanelerin sembolleri ortak bir ad alanında yaşadığı için yanlış kullanım, güvenli görünen kodda bile çökmeye yol açabilir. 2024'te bunların unsafe(...) içinde yazılması zorunlu:
#[no_mangle]
pub extern "C" fn keydal_topla(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
println!("{}", keydal_topla(2, 3));
}
// error: unsafe attribute used without unsafe// GÜVENLİK: bu adla başka bir global sembol tanımlanmıyor
#[unsafe(no_mangle)]
pub extern "C" fn keydal_topla(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
println!("{}", keydal_topla(2, 3));
}
// çıktı: 5Öznitelik üstüne neden güvenli olduğunu açıklayan bir yorum yazmak iyi bir alışkanlıktır. unsafe_attr_outside_unsafe lint'i dönüşümü yapar ama kullanımın doğru olup olmadığını yine siz denetlersiniz.
unsafe fn gövdesinde ayrı unsafe blok
Eskiden unsafe fn iki iş görüyordu: çağıranın ek şartları sağlaması gerektiğini bildiriyor ve gövdede unsafe işlemlere serbestçe izin veriyordu. İkinci rol riskli bulundu. 2024'te unsafe_op_in_unsafe_fn lint'i varsayılan olarak uyarı veriyor: gövdedeki her unsafe işlem kendi unsafe { } bloğunda olmalı.
unsafe fn ilk_eleman(v: &[i32]) -> i32 {
*v.get_unchecked(0)
}
fn main() {
let v = [7, 8, 9];
println!("{}", unsafe { ilk_eleman(&v) });
}
// çıktı: 7 (derleme sırasında şu uyarıyla)
// warning[E0133]: call to unsafe function `core::slice::<impl [T]>::get_unchecked` is unsafe and requires unsafe block/// # Safety
/// `v` boş olmamalıdır.
unsafe fn ilk_eleman(v: &[i32]) -> i32 {
// GÜVENLİK: çağıran, dilimin boş olmadığını garanti ediyor
unsafe { *v.get_unchecked(0) }
}
fn main() {
let v = [7, 8, 9];
println!("{}", unsafe { ilk_eleman(&v) });
}
// çıktı: 7static mut referansları varsayılan olarak hata
static_mut_refs lint'i 2024'te deny seviyesine çıktı. Bir static mut değişkene paylaşılan veya değiştirilebilir referans almak, Rust'ın aynı anda hem paylaşım hem değişiklik yasağını küresel ölçekte düşünmenizi gerektirir; Edition Guide, referans hiç okunmasa bile kural ihlalinin anında tanımsız davranış olduğunu vurgular. println! gibi makrolar da arka planda referans aldığı için hata verir.
static mut SAYAC: u32 = 0;
fn main() {
unsafe {
SAYAC += 1;
let r = &SAYAC;
println!("{r}");
}
}
// error: creating a shared reference to mutable staticÖnerilen yol, mut olmayan bir static ile iç değişebilirlik sağlayan bir tip kullanmaktır. Basit sayaçlar için atomik tipler yeterlidir; daha karmaşık durumlar için Arc, Mutex ve atomikler yazısına bakın. Ham işaretçi kaçınılmazsa derleyici &raw const ve &raw mut önerir.
use std::sync::atomic::{AtomicU32, Ordering};
static SAYAC: AtomicU32 = AtomicU32::new(0);
fn main() {
SAYAC.fetch_add(1, Ordering::Relaxed);
SAYAC.fetch_add(1, Ordering::Relaxed);
println!("{}", SAYAC.load(Ordering::Relaxed));
}
// çıktı: 2Desenlerde mut, ref ve referans deseni kısıtı
Bir referansı referans olmayan bir desenle eşleştirdiğinizde (match ergonomics) varsayılan bağlama kipi ref olur. 2021'de böyle bir desenin içinde mut yazmak bu kipi sessizce move durumuna geri çeviriyordu; bu kafa karıştırıcı bulunduğu için 2024'te hata oldu. Örnekte b 2021'de i32 olarak bağlanıp 1 12 yazdırır, 2024'te ise derlenmez:
fn main() {
let dizi = &[1, 2];
let [a, mut b] = dizi;
b += 10;
println!("{a} {b}");
}
// error: cannot mutably bind by value within an implicitly-borrowing patternDeseni tamamen açık yazmak, yani referansı & ile karşılamak sorunu çözer ve kod her iki edition'da aynı anlama gelir. Desen sözdiziminin tamamı Rust pattern sözdizimi yazısında.
fn main() {
let dizi = &[1, 2];
let &[a, mut b] = dizi;
b += 10;
println!("{a} {b}");
}
// çıktı: 1 12Makrolar, never tipi ve dönüş tipi yakalama kuralları
macro_rules! içindeki expr parça belirteci 2024'te const { ... } bloklarını ve _ ifadesini de eşleştiriyor. Aşağıdaki makro 2021'de ikinci kuralı, 2024'te birinci kuralı seçer. Eski davranışı korumak isteyenler için expr_2021 belirteci eklendi; geçiş lint'i tüm expr kullanımlarını expr_2021 yapar, ancak çoğu durumda bu değişikliği geri alıp yeni davranışı tercih etmeniz önerilir. Makro yazımının ayrıntıları macro_rules ile makro yazma yazısında.
macro_rules! ornek {
($e:expr) => { println!("birinci kural") };
(const $e:expr) => { println!("ikinci kural") };
}
fn main() {
ornek!(const { 1 + 1 });
}
// --edition 2024 çıktısı: birinci kural
// --edition 2021 çıktısı: ikinci kuralİki değişiklik daha kod örneği gerektirmeyecek kadar dar kapsamlıdır. Birincisi never tipi (!) için yedek tipin () yerine ! olmasıdır; bu konuda otomatik düzeltme yoktur, ancak etkilenecek kod derleyici tarafından tespit edilir ve never_type_fallback_flowing_into_unsafe lint'i deny seviyesine çıkmıştır. İkincisi impl Trait dönüş tiplerinin artık kapsamdaki tüm generic parametreleri, lifetime'lar dahil, örtük olarak yakalamasıdır; daha dar yakalama isterseniz use<..> sınırı yazarsınız. Bir makro kuralında parça belirteci olmayan metadeğişken hatası ise Edition Guide'a göre önce yalnızca 2024 için hata olmuş, Rust 1.89 ile tüm edition'larda hataya dönüşmüştür.
Standart kütüphane değişiklikleri
Prelude, her modüle otomatik içe aktarılan öğeler kümesidir. 2024 prelude'una std::future::Future ve std::future::IntoFuture eklendi. Kendi trait'inizde poll adlı bir metot varsa ve bu metodu bir future üzerinde çağırıyorsanız çağrı belirsizleşebilir; rust_2024_prelude_collisions lint'i bu çağrıları tam nitelikli sözdizimine çevirir. Asenkron programlamanın temelleri için async/await ve Future yazısına bakabilirsiniz.
Box<[T]> üzerinde .into_iter() çağrısının anlamı da değişti. Edition Guide'a göre IntoIterator uygulaması Rust 1.80 ile tüm edition'lara eklendi, ama metot çağrısı biçimi eski edition'larda geriye uyumluluk için hâlâ referans döndüren iterator'e gidiyor. 2024'te ise değerlerin kendisini üretiyor:
use std::any::type_name_of_val;
fn main() {
let kutu: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
for x in kutu.into_iter() {
println!("{}", type_name_of_val(&x));
break;
}
}
// --edition 2024 çıktısı: u32
// --edition 2021 çıktısı: &u32 (ve boxed_slice_into_iter uyarısı)Son olarak std::env::set_var, std::env::remove_var ve Unix'e özgü CommandExt::before_exec artık unsafe. Bazı platformlarda süreç ortamının işlenme biçimi nedeniyle bu fonksiyonları çok iş parçacıklı bir programda çağırmak güvenli değil. 2024'te çağrı bir unsafe blok ister:
use std::env;
fn main() {
env::set_var("UYGULAMA_MODU", "test");
println!("{:?}", env::var("UYGULAMA_MODU"));
}
// error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe blockuse std::env;
fn main() {
// GÜVENLİK: program bu noktada tek iş parçacığıyla çalışıyor
unsafe { env::set_var("UYGULAMA_MODU", "test") };
println!("{:?}", env::var("UYGULAMA_MODU"));
}
// çıktı: Ok("test")unsafe blok eklemek yalnızca derleme hatasını kapatır; asıl iş, çağrının başka hiçbir iş parçacığı çalışmıyorken yapıldığından emin olmaktır. Mümkünse ortam değişkenini değiştirmek yerine değeri parametre olarak taşıyın. Ortam değişkenlerini okumak için komut satırı argümanları ve ortam değişkenleri yazısına bakabilirsiniz.
Cargo, rustdoc ve rustfmt tarafı
edition = "2024" yazmak resolver = "3" anlamına gelir. Bu çözücü, bağımlılık sürümü seçerken paketinizin rust-version değerini dikkate alır ve bu sürümle uyumsuz bağımlılık sürümlerine yalnızca başka seçenek kalmadığında başvurur. Çözücü ayarı çalışma alanı genelindedir; sanal bir workspace kullanıyorsanız [workspace] tablosunda resolver alanını ayrıca yazmanız gerekir. Bu geçiş için otomatik araç yoktur.
Cargo.toml içinde aynı şeyi iki farklı biçimde yazmaya izin veren eski adlar 2024'te kaldırıldı: [project] yerine [package], dev_dependencies yerine dev-dependencies, build_dependencies yerine build-dependencies, default_features yerine default-features, crate_type yerine crate-type, proc_macro yerine proc-macro. Denediğimizde 2021 projesinde Cargo bunu uyarı olarak bildirdi, 2024'te ise manifest hiç okunmadı:
$ cargo check
error: failed to parse manifest at `...\anahtar\Cargo.toml`
Caused by:
`dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies`Workspace'ten miras alınan bir bağımlılıkta, workspace tarafı varsayılan özellikleri açık bırakıyorsa paket tarafında default-features = false yazmak da artık hata; zaten etkisi yoktu. Rustdoc'ta doctest'ler tek bir ikili dosyada birleştirilerek çalıştırılıyor, bu da test süresini kısaltır. Rustfmt ise artık style edition kavramını destekliyor: cargo fmt, Cargo.toml içindeki edition'ı kullanır; isterseniz rustfmt.toml içinde style_edition = "2024" ile ayrıca belirleyebilirsiniz. Ayrıntılar için Cargo.toml ve bağımlılıklar, rustdoc ve doc test ve clippy ve rustfmt yazılarına bakın.
Adım adım geçiş: küçük bir projeyi 2024'e taşımak
Edition Guide'ın önerdiği sıra beş adımdır: bağımlılıkları cargo update ile güncellemek, cargo fix --edition çalıştırmak, Cargo.toml içindeki edition değerini değiştirmek, cargo build veya cargo test ile doğrulamak ve son olarak cargo fmt çalıştırmak. Bu sırayı, birkaç 2024 uyumsuzluğunu bilerek içeren bir 2021 projesinde denedik:
extern "C" {
fn abs(x: i32) -> i32;
}
fn gen(n: i32) -> i32 {
unsafe { abs(n) * 2 }
}
fn main() {
std::env::set_var("MOD", "deneme");
let kutu: Box<[i32]> = vec![-3, 4].into_boxed_slice();
for x in kutu.into_iter() {
println!("{}", gen(*x));
}
println!("{:?}", std::env::var("MOD"));
}
// çıktı: 6
// çıktı: 8
// çıktı: Ok("deneme")Proje sürüm kontrolü altında olmadığı için --allow-no-vcs bayrağını ekledik. Gerçek bir projede önce değişikliklerinizi commit etmeniz daha güvenlidir; böylece aracın yaptığı her değişikliği ayrı ayrı görebilirsiniz.
$ cargo fix --edition --allow-no-vcs
Migrating Cargo.toml from 2021 edition to 2024
Checking gecis v0.1.0 (...)
Migrating src\main.rs from 2021 edition to 2024
Fixed src\main.rs (5 fixes)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23sAraç beş düzeltme yaptı. Sonuç aşağıda; dikkat ederseniz into_iter() çağrısı eski davranışı korumak için iter() oldu, set_var çağrısının üstüne de denetlemeniz gerektiğini söyleyen bir FIXME yorumu eklendi:
unsafe extern "C" {
fn abs(x: i32) -> i32;
}
fn r#gen(n: i32) -> i32 {
unsafe { abs(n) * 2 }
}
fn main() {
// FIXME: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("MOD", "deneme") };
let kutu: Box<[i32]> = vec![-3, 4].into_boxed_slice();
for x in kutu.iter() {
println!("{}", r#gen(*x));
}
println!("{:?}", std::env::var("MOD"));
}Önemli bir ayrıntı: cargo fix --edition kodu iki edition'da da derlenecek hale getirir ama Cargo.toml içindeki edition değerine dokunmaz. Denememizde komuttan sonra değer hâlâ 2021 idi. Değeri elle 2024 yaptıktan sonra cargo run aynı 6, 8 ve Ok("deneme") çıktısını verdi, cargo fmt --check ise biçim farkı bulmadı.
Sık yapılan hatalar

- Önce edition değerini değiştirmek:
edition = "2024"yazıp sonracargo fix --editionçalıştırmak sırayı bozar. Önce kodu düzeltin, sonra edition değerini değiştirin. - if_let_rescope önerisini incelemeden kabul etmek: Araç
if letifadesinimatchile değiştirerek eski bırakma sırasını korur. Kilit içeren kodda bu, düzeltilmek istenen kilitlenmeyi geri getirebilir; her değişikliği okuyun. - expr_2021 dönüşümünü olduğu gibi bırakmak: Makrolarınız
constblokları veya_ile çakışmıyorsa yeniexprdavranışını korumak genellikle daha doğrudur. - set_var için yalnızca unsafe eklemek: Asıl gereksinim, çağrı anında başka iş parçacığı olmamasıdır. Yalnızca derleyiciyi susturmak sorunu çözmez.
- Sanal workspace'te resolver alanını unutmak: Kök paketi olmayan bir workspace'te
resolver = "3"otomatik gelmez. - static mut hatasını allow ile kapatmak: Lint'i bastırmak tanımsız davranış riskini ortadan kaldırmaz; atomik tip veya kilit gibi bir alternatife geçin.
Sık Sorulan Sorular
2024 edition'a geçmek zorunda mıyım?
Hayır. Edition'lar isteğe bağlıdır ve yeni Rust sürümleri eski edition'lardaki kodu derlemeye devam eder. Ancak let zincirleri gibi bazı yeni olanaklar yalnızca 2024 edition'da açıktır; yeni projeler için cargo new zaten 2024 seçer.
2021 edition'daki bir kütüphaneyi 2024 projemde kullanabilir miyim?
Evet. Edition Guide'ın temel kuralı, farklı edition'lardaki crate'lerin sorunsuz birlikte çalışmasıdır. Her bağımlılık kendi edition kurallarıyla derlenir.
cargo fix bütün sorunları çözer mi?
Çoğunu çözer ama hepsini değil. Kuyruk ifadesi değişikliği, resolver değişikliği ve never tipi değişikliği için otomatik dönüşüm yoktur; araç yalnızca uyarı verir. extern imzalarının ve set_var çağrılarının doğruluğunu da sizin denetlemeniz gerekir.
Bir değişikliği tüm projeyi geçirmeden nasıl görebilirim?
Edition Guide her değişiklik için ilgili lint'i elle açmayı önerir. Örneğin crate kökünüze #![warn(if_let_rescope)] veya #![warn(keyword_idents_2024)] ekleyip cargo check çalıştırırsanız, etkilenen yerleri kodu değiştirmeden listeleyebilirsiniz.
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 · Cargo son sürüm değişiklikleri · Cargo.toml ve bağımlılıklar · unsafe Rust · match ve if let · Lifetime hataları