Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Match Ergonomisi Çekinceleri

Özet

  • Bir bağ üzerinde mut, ref ya da ref mut yazmak artık yalnızca, o bağa kadar gelen desen tamamen açıksa mümkündür; yani match ergonomisi kullanmıyorsa.
    • Başka bir deyişle, varsayılan bağlama modu move değilse bağ üzerinde mut, ref ya da ref mut yazmak hatadır.
  • Referans desenlerine (& ya da &mut) yalnızca bir desenin tamamen açık olan ön kısmında izin verilir.
    • Başka bir deyişle, referans desenleri yalnızca varsayılan bağlama modu move iken scrutinee içindeki referanslarla eşleşebilir.

Ayrıntılar

Arka plan

match, let ve benzeri yapılarda bir desen ile bir scrutinee’yi eşleştiririz. Örneğin:

#![allow(unused)]
fn main() {
let &[&mut [ref x]] = &[&mut [()]]; // x: &()
//  ~~~~~~~~~~~~~~~   ~~~~~~~~~~~~
//      Desen          Scrutinee
}

Böyle bir desene tamamen açık denir; çünkü scrutinee içindeki hiçbir referansı atlamaz. Buna karşılık aşağıdaki, başka açıdan eşdeğer olan desen tamamen açık değildir:

#![allow(unused)]
fn main() {
let [[x]] = &[&mut [()]]; // x: &()
}

Bunun gibi desenler, ilk olarak RFC 2005 ile gelen match ergonomisini kullanıyor sayılır.

Match ergonomisi altında, bir deseni adım adım scrutinee ile eşleştirirken varsayılan bağlama modunu takip ederiz. Bu mod move, ref mut ya da ref olabilir ve başlangıçta movedur. Bir bağa ulaştığımızda açık bir bağlama modu verilmediyse bağın türüne karar vermek için varsayılan mod kullanılır.

Örneğin burada açık bir bağlama modu veriyoruz ve bu yüzden x referansla bağlanıyor:

#![allow(unused)]
fn main() {
let ref x = (); // &()
}

By contrast:

#![allow(unused)]
fn main() {
let [x] = &[()]; // &()
}

Burada desende, scrutinee içindeki dıştaki paylaşımlı referansı geçiyoruz. Bu, varsayılan bağlama modunu movedan refe çevirir. Açık bir bağlama modu belirtilmediği için x bağlanırken ref modu kullanılır.

mut kısıtı

Rust 2021 ve daha eski sürümlerde şu tuhaflığa izin veriliyordu:

#![allow(unused)]
fn main() {
let [x, mut y] = &[(), ()]; // x: &(), mut y: ()
}

Burada desende paylaşımlı referansı geçtiğimiz için varsayılan bağlama modu refe döner. Ama bu sürümlerde bağ üzerine mut yazmak, varsayılan bağlama modunu yeniden movea sıfırlar.

Bu şaşırtıcı olabilir; çünkü değiştirilebilirliğin türü etkilemesi sezgisel değildir.

Bunu düzeltebilmek için alan bırakmak adına, Rust 2024’te varsayılan bağlama modu move değilken bağ üzerine mut yazmak hata oldu. Yani mut, yalnızca desen o bağa kadar tamamen açıksa yazılabilir.

Rust 2024’te yukarıdaki örneği şöyle yazabiliriz:

#![allow(unused)]
fn main() {
let &[ref x, mut y] = &[(), ()]; // x: &(), mut y: ()
}

ref / ref mut kısıtı

Rust 2021 ve daha eski sürümlerde şuna izin veriliyordu:

#![allow(unused)]
fn main() {
let [ref x] = &[()]; // x: &()
}

Burada açık ref bağlama modu gereksizdir; çünkü paylaşımlı referansı geçmek, yani desende anmamak, bağlama modunu zaten refe çevirir.

Dil için başka olasılıklara yer bırakmak adına, Rust 2024’te gereksiz açık bağlama modlarına izin verilmiyor. Yukarıdaki örnek basitçe şöyle yazılabilir:

#![allow(unused)]
fn main() {
let [x] = &[()]; // x: &()
}

Referans desenleri kısıtı

Rust 2021 ve daha eski sürümlerde şu tuhaflığa izin veriliyordu:

#![allow(unused)]
fn main() {
let [&x, y] = &[&(), &()]; // x: (), y: &&()
}

Burada desendeki &, hem &() içindeki referansla eşleşir hem de varsayılan bağlama modunu yeniden move yapar. Bu şaşırtıcı olabilir; çünkü desendeki tek bir &, beklenenden büyük bir tür değişikliğine yol açıp iki kat referansı birden kaldırır.

Bunu düzeltebilmek için alan bırakmak adına, Rust 2024’te varsayılan bağlama modu move değilken desene & veya &mut yazmak hatadır. Yani & ya da &mut, yalnızca desen o noktaya kadar tamamen açıksa yazılabilir.

Rust 2024’te yukarıdaki örnek şöyle yazılabilir:

#![allow(unused)]
fn main() {
let &[&x, ref y] = &[&(), &()];
}

Taşıma

rust_2024_incompatible_pat lint’i, Rust 2024’te artık izin verilmeyen desenleri işaretler. Bu lint, cargo fix --edition çalıştırılırken otomatik uygulanan rust-2024-compatibility grubunun parçasıdır. Etkilenen desenleri, Rust 2024’te ve önceki tüm sürümlerde doğru çalışan tamamen açık desenlere otomatik olarak dönüştürür.

Kodunuzu Rust 2024 ile uyumlu hale getirmek için şunu çalıştırın:

cargo fix --edition

Örneğin bu komut şunu…

#![allow(unused)]
fn main() {
let [x, mut y] = &[(), ()];
let [ref x] = &[()];
let [&x, y] = &[&(), &()];
}

şuna dönüştürür:

#![allow(unused)]
fn main() {
let &[ref x, mut y] = &[(), ()];
let &[ref x] = &[()];
let &[&x, ref y] = &[&(), &()];
}

Alternatif olarak, taşınması gereken desenleri bulmak için lint’i elle etkinleştirebilirsiniz:

#![allow(unused)]
fn main() {
// Elle taşıma yapmak için bunu crate köküne ekleyin.
#![warn(rust_2024_incompatible_pat)]
}