Tim pengembangan Rust dengan bangga mengumumkan rilis versi baru Rust: 1.30.0. Rust adalah bahasa pemrograman sistem yang ditujukan untuk keamanan, kecepatan, dan eksekusi kode paralel.
Jika Anda memiliki versi Rust sebelumnya yang diinstal menggunakan rustup
, maka untuk meningkatkan versi Rust ke versi 1.30.0 Anda hanya perlu melakukan:
$ rustup update stable
Jika Anda belum menginstal rustup
, Anda dapat menginstalnya dari halaman yang sesuai di situs web kami. Catatan rilis terperinci untuk Rust 1.30.0 tersedia di GitHub.
Apa yang termasuk dalam versi stabil 1.30.0
Rust 1.30 adalah rilis luar biasa dengan sejumlah inovasi penting. Tetapi pada hari Senin, blog resmi akan menerbitkan permintaan untuk memeriksa versi beta Rust 1.31, yang akan menjadi rilis pertama "Rust 2018". Anda akan menemukan informasi lebih lanjut tentang ini di publikasi kami sebelumnya "Apa itu Rust 2018" .
Makro Prosedural
Kembali di Rust 1.15, kami menambahkan kemampuan untuk mendefinisikan "macro turunan khusus." Misalnya, menggunakan serde_derive
, Anda dapat mendeklarasikan:
#[derive(Serialize, Deserialize, Debug)] struct Pet { name: String, }
Dan konversi Pet
ke JSON dan kembali ke struktur menggunakan serde_json
. Ini dimungkinkan berkat inferensi otomatis Deserialize
Serialize
dan Deserialize
menggunakan makro prosedural di serde_derive
.
Karat 1,30 memperluas fungsionalitas makro prosedural dengan menambahkan kemampuan untuk mendefinisikan dua jenis makro lain: "atribut prosedural makro" dan "makro prosedural fungsional".
Makro atribut mirip dengan mendapatkan makro untuk keluaran otomatis, tetapi alih-alih menghasilkan kode hanya untuk atribut #[derive]
, makro memungkinkan pengguna untuk membuat atribut baru mereka sendiri. Ini membuatnya lebih fleksibel: turunan makro hanya berfungsi untuk struktur dan enumerasi, tetapi atribut dapat diterapkan ke objek lain, seperti fungsi. Misalnya, atribut macro akan memungkinkan Anda untuk melakukan hal berikut saat menggunakan kerangka kerja web:
#[route(GET, "/")] fn index() {
Atribut #[route]
ini akan didefinisikan dalam kerangka itu sendiri sebagai makro prosedural. Tanda tangannya akan terlihat seperti ini:
#[proc_macro_attribute] pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
Di sini kita memiliki dua parameter input tipe TokenStream
: yang pertama adalah untuk konten atribut itu sendiri, yaitu, ini adalah parameter GET, "/"
. Yang kedua adalah badan objek yang atributnya diterapkan. Dalam kasus kami, ini adalah fn index() {}
dan seluruh isi fungsi.
Makro fungsional mendefinisikan makro yang penggunaannya mirip dengan panggilan fungsi. Misalnya, sql!
:
let sql = sql!(SELECT * FROM posts WHERE id=1);
Makro ini di dalam dirinya sendiri akan mengurai ekspresi SQL dan memeriksanya untuk kebenaran sintaksis. Makro yang serupa harus dinyatakan sebagai berikut:
#[proc_macro] pub fn sql(input: TokenStream) -> TokenStream {
Ini mirip dengan tanda tangan dari turunan makro: kami mendapatkan token yang ada di dalam tanda kurung dan mengembalikan kode yang dihasilkan oleh mereka.
Macro dan use
Sekarang Anda dapat mengimpor makro ke dalam cakupan menggunakan kata kunci penggunaan . Misalnya, untuk menggunakan makro json
dari paket serde-json
, entri yang digunakan adalah:
#[macro_use] extern crate serde_json; let john = json!({ "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] });
Dan sekarang Anda harus menulis:
extern crate serde_json; use serde_json::json; let john = json!({ "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] });
Di sini, makro diimpor serta elemen lainnya, jadi tidak perlu menggunakan anotasi macro_use
.
Akhirnya, paket proc_macro distabilkan , yang menyediakan API yang diperlukan untuk menulis makro prosedural. Itu juga secara signifikan meningkatkan API penanganan kesalahan, dan paket-paket seperti syn
dan quote
sudah menggunakannya. Misalnya, sebelumnya:
#[derive(Serialize)] struct Demo { ok: String, bad: std::thread::Thread, }
menyebabkan kesalahan ini:
error[E0277]: the trait bound `std::thread::Thread: _IMPL_SERIALIZE_FOR_Demo::_serde::Serialize` is not satisfied --> src/main.rs:3:10 | 3 | #[derive(Serialize)] | ^^^^^^^^^ the trait `_IMPL_SERIALIZE_FOR_Demo::_serde::Serialize` is not implemented for `std::thread::Thread`
Sekarang akan diterbitkan:
error[E0277]: the trait bound `std::thread::Thread: serde::Serialize` is not satisfied --> src/main.rs:7:5 | 7 | bad: std::thread::Thread, | ^^^ the trait `serde::Serialize` is not implemented for `std::thread::Thread`
Memperbaiki sistem modul
Sistem modul telah lama menjadi tempat sakit bagi pemula di Rust; beberapa aturannya tidak praktis dalam praktik. Perubahan ini adalah langkah pertama yang kami ambil untuk menyederhanakan sistem modul.
Selain perubahan di atas untuk makro, ada dua peningkatan baru untuk use
. Pertama, paket eksternal sekarang ditambahkan ke pendahuluan , yaitu:
Tangkapannya adalah bahwa gaya lama tidak selalu diperlukan karena fitur sistem modul Rust:
extern crate serde_json; fn main() { // ; , `serde_json` // let json = serde_json::from_str("..."); } mod foo { fn bar() { // ; `foo`, `serde_json` // let json = serde_json::from_str("..."); } // - `use` use serde_json; fn baz() { // - `::serde_json`, // , let json = ::serde_json::from_str("..."); } }
Itu menjengkelkan untuk mendapatkan kode yang rusak hanya dengan memindahkan fungsi ke submodule. Sekarang bagian pertama dari jalan akan diperiksa, dan jika itu sesuai dengan beberapa extern crate
, maka itu akan digunakan terlepas dari posisi panggilan dalam hirarki modul.
Akhirnya, penggunaan mulai mendukung impor elemen ke dalam cakupan saat ini dengan jalur yang dimulai pada peti :
mod foo { pub fn bar() {
Kata kunci crate
di awal jalan menunjukkan bahwa jalan akan dimulai pada akar paket. Sebelumnya, jalur yang ditunjukkan dalam baris impor use
selalu ditentukan relatif terhadap akar paket, tetapi jalur di sisa kode yang secara langsung merujuk ke elemen ditentukan relatif terhadap modul saat ini, yang menyebabkan perilaku yang bertentangan dari jalur:
mod foo { pub fn bar() {
Segera setelah gaya baru ini digunakan secara luas, diharapkan akan membuat jalur absolut menjadi lebih jelas tanpa perlu menggunakan awalan jelek ::
.
Semua perubahan ini bersama-sama menyederhanakan pemahaman tentang bagaimana jalur diselesaikan. Di mana pun Anda melihat jalan a::b::c
, kecuali untuk pernyataan use
, Anda dapat bertanya:
- Apakah nama paket? Maka Anda perlu mencari
b::c
di dalamnya. - Apakah
a
kata kunci? Maka Anda perlu mencari b::c
dari root paket saat ini. - Jika tidak, Anda perlu mencari
a::b::c
dari posisi saat ini di hierarki modul.
Perilaku lama jalur yang use
, selalu dimulai dari akar paket, masih berlaku. Tetapi dengan transisi satu kali ke gaya baru, aturan ini akan diterapkan ke jalur di mana-mana secara seragam, dan Anda harus lebih khawatir tentang impor saat memindahkan kode.
Pengidentifikasi mentah
Anda sekarang dapat menggunakan kata kunci sebagai pengidentifikasi menggunakan sintaks baru berikut:
Sejauh ini, tidak banyak kasus saat ini berguna bagi Anda. Tetapi suatu hari Anda akan mencoba menggunakan paket untuk Rust 2015 dalam proyek untuk Rust 2018 atau sebaliknya, maka rangkaian kata kunci mereka akan berbeda. Kami akan membicarakan lebih lanjut tentang hal ini dalam pengumuman Rust 2018 yang akan datang.
Aplikasi tanpa pustaka standar
Kembali di Rust 1.6, kami mengumumkan stabilisasi "no_std" dan libcore untuk membuat proyek tanpa pustaka standar. Namun, dengan satu klarifikasi: itu mungkin untuk membuat perpustakaan saja, tetapi tidak aplikasi.
Di Rust 1.30, Anda dapat menggunakan atribut #[panic_handler]
untuk secara mandiri menerapkan panik. Ini berarti bahwa sekarang Anda dapat membuat aplikasi, bukan hanya perpustakaan yang tidak menggunakan perpustakaan standar.
Lainnya
Satu hal terakhir: di makro, Anda sekarang dapat memetakan pengubah ruang lingkup , seperti pub
, menggunakan kualifikasi vis
. Selain itu, "atribut alat", seperti #[rustfmt::skip]
, sekarang distabilkan . Benar untuk digunakan dengan alat analisis statis , seperti #[allow(clippy::something)]
, mereka belum stabil.
Lihat catatan rilis untuk lebih jelasnya.
Stabilisasi perpustakaan standar
API berikut telah distabilkan dalam rilis ini:
Ipv4Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}
Ipv6Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}
Iterator::find_map
Selain itu, pustaka standar telah lama memiliki fungsi untuk menghapus spasi di satu sisi beberapa teks, seperti trim_left
. Namun, untuk bahasa RTL, arti "kanan" dan "kiri" di sini menyebabkan kebingungan. Karena itu, kami memperkenalkan nama-nama baru untuk fungsi-fungsi ini:
trim_left
-> trim_start
trim_right
-> trim_end
trim_left_matches
-> trim_start_matches
trim_right_matches
-> trim_end_matches
Kami berencana untuk mendeklarasikan nama-nama lama usang (tetapi tidak menghapus, tentu saja) di Rust 1.33.
Lihat catatan rilis untuk lebih jelasnya.
Peningkatan Kargo
Peningkatan Cargo terbesar dalam rilis ini adalah bahwa kami sekarang memiliki progress bar!

Lihat catatan rilis untuk lebih jelasnya.
Pengembang 1.30.0
Banyak orang bersama-sama menciptakan Rust 1.30. Kami tidak dapat menyelesaikan pekerjaan tanpa Anda masing-masing. Terima kasih
Dari penerjemah: Saya mengucapkan terima kasih khusus kepada anggota komunitas Rustycrate dan secara pribadi vitvakatu dan Virtuos86 atas bantuan mereka dengan terjemahan dan proofreading.