A Rust csapata pontosan tartotta a hathetes release-ciklust, és 2023. július 13-án megérkezett a Rust 1.71. Ha eddig rustup update-et még nem futtattad, most itt az idő – ez a kiadás ugyan nem hoz földindulásszerű nyelvi újításokat, de két olyan képességet stabilizál, amire a rendszerprogramozók és az IDE/debugger integrációval foglalkozók régóta vártak.

A C-unwind ABI stabilizálása

Eddig ha egy extern "C" függvényből panic terjedt ki (vagyis a stack unwinding átlépte az FFI határt), az undefined behavior volt. A Rust 1.71-ben az extern "C-unwind" ABI immár stabil, tehát explicit módon jelezheted a compilernek, hogy egy adott FFI-határon keresztül a panic-unwinding biztonságosan átmehet.

// Ez a függvény C ABI-t használ, de megengedi a stack unwindinget
// a határon át, ha panic történik hívás közben.
extern "C-unwind" fn hivhato_kivulrol(x: i32) -> i32 {
    if x < 0 {
        panic!("negativ ertek nem megengedett");
    }
    x * 2
}

fn main() {
    let eredmeny = hivhato_kivulrol(21);
    println!("Eredmeny: {eredmeny}");
}
Megjegyzés

A "C-unwind" nem azt jelenti, hogy most már bármikor panicolhatsz egy sima extern "C" blokkban. Az a viselkedés maradt undefined behavior. A C-unwind egy külön, explicit ABI-variáns, amit tudatosan kell választanod ott, ahol tényleg szükséges az unwinding-kompatibilitás.

Ez elsősorban azoknak fontos, akik C vagy C++ könyvtárakkal integrálnak Rust kódot, és a hívási lánc mindkét oldalán szükség lehet a exception/panic propagálásra – gondoljunk például callback-alapú API-kra, ahol a Rust callback panicolhat, és ezt a C oldalon szeretnénk kezelni, vagy éppen fordítva.

Debugger visualizer (natvis) támogatás

A másik nagy újdonság a #[debugger_visualizer] attribútum stabilizálása. Ez lehetővé teszi, hogy a crate-edhez natvis (Visual Studio) vagy GDB pretty-printer fájlokat csatolj, amelyeket a debugger automatikusan felszed, amikor a te típusaidat vizsgálja.

#![debugger_visualizer(natvis_file = "Sajat.natvis")]

pub struct Pont {
    x: f64,
    y: f64,
}

fn main() {
    let p = Pont { x: 3.0, y: 4.0 };
    println!("{p:?}", p = std::format_args!("({}, {})", p.x, p.y));
}

A Sajat.natvis fájlban XML formátumban leírhatod, hogy a Pont típus hogyan jelenjen meg a Visual Studio debuggerben – például "Pont(3, 4)" formában, a nyers memóriaréteg helyett. Ez korábban csak nightly feature-ként vagy külső eszközökkel volt elérhető, most már a stabil toolchain natívan támogatja.

Tipp

Ha könyvtárfejlesztő vagy, és a felhasználóid gyakran Visual Studio-ban vagy VS Code-ban debugolnak, érdemes natvis fájlt csatolni a komplexebb belső típusaidhoz (pl. custom smart pointerek, arena allocatorok). Ez drasztikusan javíthatja a debug-élményt anélkül, hogy a felhasználónak bármit tennie kellene.

Mit jelent ez a gyakorlatban?

Ha nem foglalkozol FFI-vel vagy debugger tooling-gal, a napi munkádban közvetlenül nem fogsz találkozni ezekkel a feature-ökkel – ez egy inkább "infrastrukturális" release. De van néhány dolog, ami közvetve mindenkit érint:

  1. Kompiláció stabilitása: a C-unwind ABI stabilizálása azt jelenti, hogy azok a crate-ek, amelyek eddig #![feature(c_unwind)]-et használtak nightly-n, most átválthatnak stabil toolchain-re. Ha egy függőséged unwinding-safe FFI wrappert épít (pl. bizonyos GUI binding-ek vagy audio library wrapperek), hamarosan látni fogod, hogy megszűnik a nightly-függőségük.
  2. Jobb debug-élmény könyvtárfejlesztőknek: ha te maga fejlesztesz publikus crate-et komplex belső típusokkal, most van eszközöd arra, hogy a debug-élményt is a csomag részévé tedd.
  3. Folytatódik a stabil nyelv fejlődése: emlékeztetőül, korábbi release-ekben stabilizált dolgok, mint a GAT-ok (Generic Associated Types), a let-else szintaxis, vagy az OnceCell/OnceLock típusok, továbbra is a Rust mindennapi eszköztárának részei, és a 1.71 zökkenőmentesen épül rájuk.
// Emlékeztető: a let-else szintaxis, amit korábbi release stabilizált,
// remekül kombinálható a mai kóddal is.
fn feldolgoz(input: Option<i32>) -> i32 {
    let Some(ertek) = input else {
        return 0;
    };
    ertek * 10
}

fn main() {
    println!("{}", feldolgoz(Some(5)));
    println!("{}", feldolgoz(None));
}
Jó tudni

A 1.71 továbbra is a 2021-es edition-t célozza alapértelmezetten – ha új projektet indítasz cargo new-val, ez marad az edition, amíg nem specifikálsz mást. Nincs szükség semmilyen Cargo.toml módosításra a frissítés miatt.

Hogyan frissíts?

A frissítés a szokásos módon zajlik rustup-pal:

rustup update stable
rustc --version

A rustc --version parancs kimenetében ellenőrizd, hogy 1.71.0 jelenik meg. Ha CI pipeline-t futtatsz, és Docker image-eket használsz, ne feledd frissíteni a rust:1.71 (vagy rust:latest) image tag-eket is, hogy a build szervereid is a friss toolchain-t kapják.

Figyelem

Ha a projekted egy régebbi crate-verziót pin-el, amely #![feature(c_unwind)]-et használt nightly-n, ellenőrizd a changelog-ját – lehet, hogy már kiadtak egy stabil-kompatibilis verziót, amit érdemes felhúznod, mielőtt teljesen stabil toolchain-re állítod át a CI-t.

Összefoglalás

A Rust 1.71 klasszikus "csendes, de fontos" release: nem kap akkora figyelmet, mint egy nagyobb nyelvi feature bevezetése, de a C-unwind ABI és a debugger visualizer stabilizálása pontosan azokat a régóta fájó pontokat oldja meg, amelyekkel az FFI-t és a tooling-integrációt komolyan vevő fejlesztők nap mint nap szembesültek. Ha ma még nem tetted meg, futtasd le a rustup update stable-t, és élvezd a friss toolchain-t – a szokásos garancia szerint semmi nem törik el a meglévő kódodban.