Команда Rust объявила о выходе новой стабильной версии Rust 1.31.0, который ознаменует собой также выход новой редакции «Rust 2018». Rust — это язык программирования, который позволяет каждому создавать надежное и эффективное программное обеспечение.
Если у вас установлена предыдущая версия Rust, обновиться до Rust 1.31.0 проще всего следующим образом:
rustup update stable
Если у вас ещё не установлен Rust, то это можно сделать, загрузив с сайта утилиту rustup
.
Что нового в Rust 1.31.0
Rust 2018
Данный релиз ознаменует собой выпуск редакции Rust 2018. Впервые Rust 2018 был упомянут в марте, затем в июле: прочтите их, чтобы понимать для чего нужен Rust 2018. Также, есть статья на сайте Mozilla Hacks.
Вкратце, Rust 2018 это возможность представить всю работу за последние три года в виде цельного пакета. Кроме возможностей языка, сюда входят:
- Инструментарий (поддержка IDE,
rustfmt
, Clippy) - Документация
- Работа различных рабочих групп
- Новый веб-сайт
Для обозначения редакций Rust был представлен ключ edition
в Cargo.toml
:
[package]
name = "foo"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
[dependencies]
Значение 2018
означает, что используется редакция Rust 2018; отсутствие ключа или значение 2015
означает использование редакции Rust 2015.
Важно отметить, что каждый пакет может быть в редакциях 2015 или 2018, и они без проблем могут работать вместе. Проект под редакцией 2018 может использовать зависимости 2015, а проект 2015 использовать зависимости 2018. Это гарантирует целостность экосистемы, сохраняя совместимость существующего кода. Кроме того, существует возможность автоматической миграции кода с редакции Rust 2015 на Rust 2018 при помощи cargo fix
.
Non-lexical lifetimes (NLL; Нелексические времена жизни)
В 2018 появились нелексические времена жизни, что на простом языке означает, что проверщик заимствований (borrow checker) стал умнее и теперь не отклоняет правильный код. Например:
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x;
}
В старых версиях этот код выдаст ошибку компиляции:
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> src/main.rs:5:18
|
4 | let y = &x;
| - immutable borrow occurs here
5 | let z = &mut x;
| ^ mutable borrow occurs here
6 | }
| - immutable borrow ends here
из-за того, что время жизни действует внутри лексического блока; то есть, заимствование будет удерживаться за y
, пока y
не покинет пределы main, несмотря на то, что y
больше не используется. Сегодня этот код скомпилируется правильно.
Другой пример:
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x;
println!("y: {}", y);
}
Старый Rust выдаст следующую ошибку:
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> src/main.rs:5:18
|
4 | let y = &x;
| - immutable borrow occurs here
5 | let z = &mut x;
| ^ mutable borrow occurs here
...
8 | }
| - immutable borrow ends here
В Rust 2018 вывод ошибки стал лучше:
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> src/main.rs:5:13
|
4 | let y = &x;
| -- immutable borrow occurs here
5 | let z = &mut x;
| ^^^^^^ mutable borrow occurs here
6 |
7 | println!("y: {}", y);
| - borrow later used here
Теперь, вместо того, чтобы показывать место, где y
покидает пределы лексического блока, показывается место, где происходят конфликтующие заимствования. Это значительно облегчает отладку подобных ошибок.
Пока эти возможности доступны в Rust 2018, но в будущем планируется портировать их на Rust 2015.
Изменения в системе модулей
Редакция Rust 2018 привносит некоторые изменения в работу с путями, что в конечном итоге привело к упрощению системы модулей.
Вкратце:
-
extern crate
больше не требуется практически во всех случаях. - Макросы теперь можно импортировать при помощи
use
вместо атрибута#[macro_use]
. - Абсолютные пути начинаются с названия пакета, где ключевое слово
crate
ссылается на текущий пакет. -
foo.rs
и поддиректорияfoo/
могут сосуществовать вместе;mod.rs
больше не нужен при размещении подмодулей в поддиректории.
Полную информацию можно прочесть в руководстве.
Упрощенные правила синтаксиса времени жизни
В обеих редакциях представлены новые правила синтаксиса времени жизни для блоков impl
и определениях функций. Следующий код:
impl<'a> Reader for BufReader<'a> {
// methods go here
}
impl Reader for BufReader<'_> {
// methods go here
}
'_
подсказывает, что BufReader
берёт параметр, но больше нет необходимости именовать его.
В структурах времена жизни всё ещё должны быть определены, но теперь без лишнего кода:
// Rust 2015
struct Ref<'a, T: 'a> {
field: &'a T
}
// Rust 2018
struct Ref<'a, T> {
field: &'a T
}
: 'a
добавляется автоматически. При желании, можно продолжать использовать явное определение.
const fn
Существует несколько способов определения функций в Rust: регулярная функция с fn
, небезопасная функция с unsafe fn
, внешняя функция с extern fn
. В этом релизе появился ещё один способ: const fn
, который выглядит следующим образом:
const fn foo(x: i32) -> i32 {
x + 1
}
const fn
могут вызываться как регулярные функции, но вычисляются во время компиляции, а не во время выполнения. Для стабильной работы, они должны иметь детерминированный результат и в настоящее время ограничены следующим минимальным набором операций:
- Арифметические операторы и операторы сравнения с целыми числами
- Все логические операторы, кроме
&&
и||
- Построение массивов, структур, перечислений и кортежей
- Вызов других функций
const fn
- Задание индекса массивам и срезам
- Доступ к полям структур и кортежей
- Чтение из констант
&
и*
на ссылках- Приведение типов, за исключением необработанных указателей на целые числа
В будущем данный набор будет расширяться, подробную информацию можно посмотреть здесь.
Новые инструменты
Наряду с Cargo, Rustdoc, и Rustup, которые являются ключевыми инструментами с версии 1.0, редакция 2018 представляет новое поколение инструментов: Clippy, Rustfmt, и поддержку IDE.
Clippy является статическим анализатором кода в Rust, достиг версии 1.0 и теперь доступен в стабильной версии Rust. Установку можно произвести следующим образом: rustup component add clippy
, запуск: cargo clippy
.
Rustfmt является инструментом для автоматического форматирования кода Rust в соответствии с официальной стилистикой Rust. В этом релизе он достиг версии 1.0 и, начиная с этой версии, гарантируется обратная совместимость для Rustfmt: отформатированный сегодня код останется неизменным в будущем (только с опциями использованными по-умолчанию), и несёт практическую ценность при использовании с системами непрерывной интеграции (CI; cargo fmt --check
). Установить Rustfmt можно следующим образом: rustup component add rustfmt
, использовать: cargo fmt
.
Поддержка IDE - одна из наиболее востребованных возможностей в Rust. Работы над поддержкой IDE ещё не закончены, но на данный момент уже существуют несколько высококачественных опций:
Tool lints
В Rust 1.30 были стабилизированы атрибуты инструментов, такие как #[rustfmt::skip]
. В Rust 1.31 стабилизированы «анализаторы инструментов» («tool lints») наподобие #[allow(clippy::bool_comparison)]
, у них появилось своё пространство имён и теперь ясно к какому инструменту они относятся.
Старые проверки Clippy теперь можно писать следующим образом, вам больше не нужен атрибут cfg_attr
:
// old
#![cfg_attr(clippy, bool_comparison)]
// new
#![allow(clippy::bool_comparison)]
Документация
В этом году Rustdoc увидел ряд улучшений, также полностью было переписано руководство по Rust.
Рабочие группы
В этом году было объявлено о создании четырёх рабочих групп в следующих областях:
- Сетевые сервисы
- Приложения командной строки
- WebAssembly
- Встраиваемые устройства
Каждая из этих групп очень много работала над тем, чтобы сделать Rust лучше в своей области. Некоторые основные моменты:
- Группа сетевых сервисов работает над интерфейсом Futures и async/await, который уже будет доступен в скором времени.
- Группа командной строки работает над библиотеками и документацией для создания ещё лучших приложений для командной строки.
- Группа WebAssembly выпустила огромное количество инструментария для использования Rust с wasm.
- Группа встраиваемых устройств добилась поддержки разработки ARM на стабильной версии Rust.
Новый сайт
Основной сайт получил новый дизайн.
Стабилизация библиотек
Добавлено множество реализаций From
:
u8
теперь реализуетFrom<NonZeroU8>
, то же самое для других числовых типов и ихNonZero
-эквивалентовOption<&T>
реализуетFrom<&Option<T>>
, аналогично для&mut
Были стабилизированы следующие функции:
slice::align_to
и её изменяемый аналогslice::chunks_exact
и её изменяемый иr
аналоги (такие какslice::rchunks_exact_mut
) во всех комбинациях
Подробный список изменений можно посмотреть здесь.
Cargo
Cargo теперь загружает пакеты параллельно, используя HTTP/2. В связи с тем, что extern crate
практически больше не требуется, было бы неудобно использовать пакет через extern crate foo as bar;
Это можно сделать в Cargo.toml
следующим образом:
[dependencies]
baz = { version = "0.1", package = "foo" }
или
[dependencies.baz]
version = "0.1"
package = "foo"
В примере выше, пакет foo
теперь может быть использован через baz
.
Подробный список изменений можно посмотреть здесь.
>>> Подробности