Випуск Rust 1.13

Команда Rust рада представити випуск Rust 1.13.0. Rust — це мову програмування, націлений на безпеку, швидкість і паралельне виконання коду.
Як завжди, ви можете встановити Rust 1.13.0 з відповідної сторінки офіційного сайту, а також ознайомитися з докладним списком змін в 1.13.0 на GitHub. У цей випуск увійшло 1448 патчів.
Це була по-справжньому гаряча пора у Rust. Ми брали участь у трьох конференціях поспіль — RustConf, RustFest і Rust Belt Rust. Було класно побачити так багато любителів Rust; з багатьма ми вперше зустрілися! Ми багато думали про майбутнє, розробляли план на 2017 і створювали інструменти, потрібні нашим користувачам.
І незважаючи на все це, ми зібрали новий випуск з купою нових крутих фішок.
Що увійшло в стабільну версію 1.13
Випуск 1.13 включає довгоочікуваний оператор
?
, прискорення компіляції, додавання
деяких можливостей в Cargo та стандартну бібліотеку. Також цей випуск приносить безліч невеликих поліпшень в документацію і повідомлення про помилки. Це результат роботи багатьох людей, і вони не згадуються в зауваженнях до випуску індивідуально.
Випуск містить важливі виправлення вразливостей в Cargo. Він залежить від curl і OpenSSL,
а вони обидва нещодавно опублікували оновлення безпеки. Детальніше дивіться відповідні анонси curl 7.51.0 і OpenSSL 1.0.2 j.

Оператор
?

Rust придбав новий оператор
?
. Він робить роботу з помилками значно приємніше,
прибираючи візуальний шум. Наприклад, у нас є такий код для читання даних з файлу:
fn read_username_from_file() -> Result<String, io::Error> {
let f = File::open("username.txt");

let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};

let mut s = String::new();

match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}

Код містить два шляхи, які можуть завершитися помилкою: відкриття файлу і читання даних з нього. Якщо в одному з них станеться збій, нам потрібно повернути помилку функції
read_username_from_file
. Для цього нам доводиться
match
ить результат операцій вводу-виводу. Однак тут ми просто пробрасываем помилку в стеку викликів, і використання
match
— це постійно повторюваний шаблонний код. Його важко читати.
З
?
вищенаведений код буде виглядати так:
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("username.txt")?;
let mut s = String::new();

f.read_to_string(&mut s)?;

Ok(s)
}

?
є скороченням для цілого виразу
match
, що ми писали вище. Іншими словами,
?
бере
Result
, якщо він
Ok
, розгортає його і віддає вкладене значення. Якщо значення
Result
Err
,
?
повертає управління з поточної функції. Це набагато простіше читати: замість цілого виразу ми використовуємо символ "?". Так ми показуємо,
що обробляємо помилку стандартним способом, передаючи її вгору по стеку.
Досвідчені програмісти на Rust могуть зазначити, що це те ж саме, що і макрос
try!

доступний ще з Rust
1.0
. Дійсно, це те ж саме. До 1.13
read_username_from_file
могла бути реалізована так:
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = try!(File::open("username.txt"));
let mut s = String::new();

try!(f.read_to_string(&mut s));

Ok(s)
}

Так навіщо ж вносити розширення мова, якщо у нас вже є макрос? З різних причин.
По-перше,
try!
підтвердив свою виняткову корисність і часто використовується в идиоматичном Rust. Він використовується так часто, що заслуговує солодкого синтаксису. Такого роду еволюція є одним з великих переваг потужної системи макросів: передбачувані розширення синтаксису мови можуть бути прототипированы і протестовані без зміни самої мови. У свою чергу, макрос, що перетворився на виключно корисний, може вказувати на нестачу можливостей мови. Така еволюція
try!
на
?
— чудовий тому приклад.
Одна з причин, по яких
try!
потребує засахаривании — це те, що він досить негарний у разі повторного виклику в ланцюжку. Порівняйте:
try!(try!(try!(foo()).bar()).baz())

на противагу:
foo()?.bar()?.baz()?

Перший фрагмент досить складно читати, і кожний шар обробки помилок приписує
на початок вираження виклик
try!
. Це вимагає надмірної концентрації уваги для тривіального перекидання помилок, і затьмарює основний робочий код — виклики
foo
,
bar
та
baz
. Даний тип зчеплення викликів з обробкою помилок характерний для ситуацій на зразок шаблону проектування
builder
.
Нарешті, спеціалізований синтаксис полегшить виведення помилок — ми зможемо врахувати використання
?
. А для коду макросів складно зробити хороші помилки. Однак у цьому випуску повідомлення про помилки використання
?
реалізовані ще не повністю.
Хоча це невелике поліпшення, по нашому досвіду
?
стояча поліпшення ергономіки
try!
. Це хороший приклад послідовного поліпшення якості життя, які Rust буде отримувати і далі.
Докладніше
?
дивіться у RFC 243.

Поліпшення продуктивності

Ми серйозно зосередилися на продуктивності компілятора. У нас вже є хороші новини, але в майбутніх випусках буде ще краще.
Mark Simulacrum і Nick Cameron відточували perf.rust-lang.org, наш інструмент для відстеження продуктивності компілятора. Він регулярно запускає rustc-benchmarks
на вибраному обладнанні і відстежує зміни з часом. Цей інструмент записує результати кожного етапу компіляції і використовується розробниками, щоб
звузити діапазон пошуку комітів, що призвели до деградації продуктивності. Це важлива частина нашого інструментарію!
Ми можемо скористатися ним, щоб поглянути на графік продуктивності
у період розробки 1.13 — з 16 серпня по 29 вересня (графік показаний нижче). Графік починається з 25 серпня і відфільтрований за кількома критеріями — щоб виключити недостовірні, неповні або суперечливі результати. Можна помітити великі скорочення, які кількісно відображені на відповідній сторінці статистики.

Графік продуктивності

1 вересня відбулося значне покращення — Niko включив нормалізовані проекції кеша при трансляції. Це означає, що під час генерації LLVM IR компілятор більше не перераховує конкретні екземпляри асоційованих типів в кожному місці їх використання. Тепер він переиспользует раніше обчислені значення. Ця оптимізація не впливає на будь-код, але коли зустрічаються певні типові фрагменти, ви помітите різницю. Наприклад, для futures-rs час складання налагоджувальної версії покращився на 40%.
Інша подібна оптимізація реалізована Michael Woerister. Вона прискорює компіляцію контейнерів, які експортують безліч вбудованих функцій. Якщо функція позначена як
#[inline]
, компілятор зберігає її подання в MIR в rlib — крім звичайної трансляції для використання в поточному контейнері. Потім він транслює її в кожному контейнері, який викликає цю функцію. У ретроспективі, Michael зробив очевидну оптимізацію: в деяких випадках вбудовані функції призначені тільки для інших контейнерів, так що компілятор не повинен транслювати їх у контейнері, де вони
оголошені. Зрозуміло, крім випадку, коли вони там викликаються. Це економить час на перетворення функції в LLVM IR та її обробку LLVM: оптимізацію та кодогенерацию.
У деяких випадках це дає вражаючі результати. Час складання ndarray покращився на 50%, а для (неопублікованого) winapi 0.3, rustc тепер не виробляє машинний код зовсім.
Але почекайте, це ще не все! Nick Nethercote звернув свою увагу на продуктивність компілятора, сконцентрувавшись на профилировнии і микрооптимизациях. Даний випуск вже включає в себе деякі плоди його праці, інші заплановані на 1.14.
Докладніше дивіться зауваження до выпуску.
Інші помітні зміни
Випуск містить важливі виправлення вразливостей в Cargo. Він залежить від curl і OpenSSL, а вони обидва нещодавно опублікували оновлення безпеки. Детальніше дивіться відповідні анонси curl 7.51.0 і OpenSSL 1.0.2 j.
Тепер ви можете використовувати макроси на місці типу (RFC 873) і застосовувати атрибути до операторів (RFC 16):
// Використовуємо макрос, щоб назвати тип
macro_rules! Tuple {
{ $A:ty,$B:ty } => { ($A, $B) }
}

let x: Tuple!(i32, i32) = (1, 2);

// Застосовуємо атрибут статичного аналізу до єдиного оператора
#[allow(uppercase_variable)]
let BAD_STYLE = List::new();

Вбудовані прапори скидання (англ. inline drop flags) видалені. Раніше компілятор зберігав "прапор скидання" в структурах, щоб розуміти, виконувати чи деструктор, коли структури переміщалися в деяких шляхах виконання. Це збільшувало розмір структур, що заважало передачі типів з деструкторами через кордон FFI. Для коду, який не переміщує структури тільки в частині шляхів виконання, ця пам'ять витрачалася даремно. В 1.12 MIR став транслятором за замовчуванням — це було фундаментом багатьох поліпшень, включаючи видалення цих вбудованих прапорів скидання. Тепер прапори скидання лежать в стеку тих функцій, яким вони потрібні.
У 1.13 є серйозний баг в кодогенерации для ARM з апаратною реалізацією чисел з плаваючою точкою. Це більшість платформ на базі ARM. На даний момент ARM — це платформа 2 рівня підтримки, тому цей баг не блокує випуск. Оскільки 1.13 містить виправлення безпеки, ми рекомендуємо користувачам ARM використовувати бета-версії 1.14. Ця гілка скоро отримає виправлення даної проблеми.

Стабілізація мовних можливостей

Стабілізація бібліотек

Можливості Cargo

Докладніше дивіться зауваження до выпуску.
Розробники версії 1.13.0
155 осіб внесли свій внесок у 1.13.0. Велике вам спасибі!
Список учасників
  • Aaron Gallagher
  • Abhishek Kumar

  • aclarry
  • Adam Medziński
  • Ahmed Charles
  • Aleksey Kladov
  • Alexander von Gluck IV
  • Alexandre Oliveira
  • Alex Burka
  • Alex Crichton
  • Amanieu d Antras
  • Amit Levy
  • Andrea Corradi
  • Andre Bogus
  • Andrew Cann
  • Andrew Cantino
  • Andrew Lygin
  • Andrew Paseltiner
  • Andy Russell
  • Ariel Ben-Yehuda
  • arthurprs
  • Ashley Williams
  • athulappadan
  • Austin Hicks
  • bors
  • Brian Anderson
  • c4rlo
  • Caleb Jones
  • CensoredUsername
  • cgswords
  • changchun.fan
  • Chiu-Hsiang Hsu
  • Chris Stankus
  • Christopher Serr
  • Chris Wong
  • clementmiao
  • Cobrand
  • Corey Farwell
  • Cristi Cobzarenco
  • crypto-universe
  • dangcheng
  • Daniele Baracchi
  • DarkEld3r
  • David Tolnay
  • Dustin Bensing
  • Eduard Burtescu
  • Eduard-Mihai Burtescu
  • Eitan Adler
  • Erik Uggeldahl
  • Esteban Küber
  • Eugene Bulkin
  • Eugene R Gonzalez
  • Fabian Zaiser
  • Federico Ravasio
  • Felix S. Klock II
  • Florian Gilcher
  • Gavin Baker
  • Georg Brandl
  • ggomez
  • Gianni Ciccarelli
  • Guillaume Gomez
  • Jacob
  • jacobpadkins
  • Jake Goldsborough
  • Jake Goulding
  • Jakob Demler
  • James Duley
  • James Miller
  • Jared Roesch
  • Jared Wyles
  • Jeffrey Seyfried
  • JessRudder
  • Joe Neeman
  • Johannes Löthberg
  • John Firebaugh
  • johnthagen
  • Jonas Schievink
  • Jonathan Turner
  • Jorge Aparicio
  • Joseph Dunne
  • Josh Triplett
  • Justin LeFebvre
  • Keegan McAllister
  • Keith Yeung
  • Keunhong Lee
  • king6cong
  • Knight
  • knight42
  • Kylo Ginsberg
  • Liigo
  • Manish Goregaokar
  • Mark-Simulacrum
  • Matthew Piziak
  • Matt Ickstadt
  • mcarton
  • Michael Layne
  • Michael Woerister
  • Mikhail Modin
  • Mohit Agarwal
  • Nazım Can Altınova
  • Neil Williams
  • Nicholas Nethercote
  • Nick Cameron
  • Nick Platt
  • Niels Sascha Reedijk
  • Nikita Baksalyar
  • Niko Matsakis
  • Oliver Middleton
  • Oliver Schneider
  • orbea
  • Panashe M. Fundira
  • Patrick Walton
  • Paul Fanelli
  • philipp
  • Phil Ruffwind
  • Piotr Jawniak
  • pliniker
  • QuietMisdreavus
  • Rahul Sharma
  • Richard Janis Goldschmidt
  • Scott A Carr
  • Scott Olson
  • Sean McArthur
  • Sebastian Ullrich
  • Sébastien Marie
  • Seo Sanghyeon
  • Sergio Benitez
  • Shyam Sundar B
  • silenuss
  • Simonas Kazlauskas
  • Simon Sapin
  • Srinivas Reddy Thatiparthy
  • Stefan Schindler
  • Stephan Hügel
  • Steve Klabnik
  • Steven Allen
  • Steven Fackler
  • Terry Sun
  • Thomas Garcia
  • Tim Неймана
  • Tobias Bucher
  • Tomasz Miąsko
  • trixnz
  • Tshepang Lekhonkhobe
  • Ulrich Weigand
  • Ulrik Sverdrup
  • Vadim Chugunov
  • Vadim Petrochenkov
  • Vanja Cosic
  • Vincent Esche
  • Wesley Wiser
  • William Lee
  • Ximin Luo
  • Yossi Konstantinovsky
  • zjhmale

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.