- PVSM.RU - https://www.pvsm.ru -

Выпуск Rust 1.31 и Rust 2018

Команда разработчиков Rust рада сообщить о выпуске новой версии Rust, 1.31.0, а также "Rust 2018". Rust — это язык программирования, который дает возможность каждому создавать надежное и эффективное программное обеспечение.

Если у вас установлена предыдущая версия Rust с помощью rustup, то для обновления Rust до версии 1.31.0 вам достаточно выполнить:

$ rustup update stable

Если у вас еще не установлен rustup, вы можете установить его [1] с соответствующей страницы нашего веб-сайта. С подробными примечаниями к выпуску Rust 1.31.0 [2] можно ознакомиться на GitHub.

Что вошло в стабильную версию 1.31.0

Rust 1.31, возможно, самый значительный выпуск со времен Rust 1.0! В данный выпуск включена первая итерация «Rust 2018», но это не единственное нововведение! Обзор улучшений будет длинный, поэтому вот оглавление:

  • Rust 2018
    • Нелексические времена жизни
    • Изменения системы модулей
  • Дополнительные правила вывода времен жизни
  • const fn
  • Новые инструменты
  • Инструментальные проверки качества кода
  • Документация
  • Предметные рабочие группы
  • Новый веб-сайт
  • Стабилизация стандартной библиотеки
  • Улучшения в Cargo
  • Разработчики выпуска

Rust 2018

Мы писали о Rust 2018 впервые в марте [3], и затем в июле [4]. За подробностями зачем нужен Rust 2018, обратитесь к этим публикациям. В данном обзоре нам и так много что нужно рассказать, поэтому мы сосредоточимся только на том, что такое Rust 2018. Также об этом можно почитать в посте на Mozilla Hacks [5] (перевод [6]).

Вкратце, Rust 2018 — это возможность объединить в связное целое всю работу, которую мы проделали за последние три года. Rust 2018 — это нечто большее, чем просто набор улучшений языка. В дополнении к ним, он включает:

  • Инструментарий (поддержка в IDE, rustfmt, Clippy)
  • Документацию
  • Работу предметных рабочих групп
  • Новый веб-сайт

Дальше мы расскажем обо всем этом подробнее и о других нововведениях.

Давайте создадим новый проект с помощью Cargo:

$ cargo new foo

Вот содержимое Cargo.toml:

[package]
name = "foo"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"

[dependencies]

В секцию [package] был добавлен новый ключ: edition. Обратите внимание, что он установлен в 2018. Вы также можете установить его в 2015 — это значение будет установлено по умолчанию, если ключ отсутствует.

С использованием Rust 2018 будут разблокированы некоторые новые возможности, которые не разрешены в Rust 2015.

Важно отметить, что каждый пакет может быть в режиме 2015 или 2018, и они будут работать вместе. Ваш проект 2018 редакции может использовать зависимости 2015 редакции, а проект 2015 редакции может использовать зависимости 2018 редакции. Это гарантирует целостность экосистемы и что все новые возможности будут опциональны, сохраняя совместимость с существующим кодом. Кроме того, когда вы решите перенести код Rust 2015 на Rust 2018, изменения могут быть внесены автоматически через cargo fix.

Вы можете спросить: а что с самими новыми возможностями? Во-первых, они добавляются также и в Rust 2015, если оказываются совместимы с особенностями этой редакции. Таким образом, большая часть языка остается одинаковой везде. Вы можете посмотреть руководство по редакциям [7], чтобы узнать минимальную версию rustc для каждой новой возможности и другие ее требования. Однако, есть несколько больших нововведений, о которых нужно упомянуть отдельно: нелексические времена жизни и некоторые изменения в системе модулей.

Нелексические времена жизни

Если вы следили за развитием Rust последние несколько лет, то вы могли время от времени встречать термин "NLL" или "нелексические времена жизни" ("non-lexical lifetimes"). Это — жаргонизм, который, если говорить простыми словами, означает: анализатор заимствований стал умнее и теперь принимает некоторый корректный код, который до этого отклонял. Рассмотрим пример:

fn main() {
    let mut x = 5;

    let y = &x;

    let z = &mut x;
}

Раньше 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 |     
6 |     let z = &mut x;
  |                  ^ mutable borrow occurs here
7 | }
  | - immutable borrow ends here

Это потому, что область жизни ссылок определялась "лексически"; то есть, заимствование y считалось активным, пока y не выйдет из области видимости в конце main, даже если мы никогда больше не используем y внутри области. С кодом выше все в порядке, но анализатор зависимостей не мог этого понять.

Теперь этот код замечательно компилируется.

Но что, если бы мы использовали 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 1.31 это улучшение исключительно для Rust 2018. Мы планируем добавить его в Rust 2015 позже.

Изменения системы модулей

Система модулей может вызывать затруднения у людей, впервые изучающих Rust. Конечно, всегда есть что-то, для освоения чего требуется время. Но главная причина того, почему модули так смущают многих — несмотря на простые и последовательные правила, определяющие систему модулей, последствия их применения могут казаться противоречивыми, загадочными и противоестественными.

Поэтому редакция 2018 вносит некоторые изменения в то, как работают пути, упрощая систему модулей и делая ее понятнее.

Вот краткое резюме:

  • extern crate больше не требуется практически нигде.
  • Вы можете импортировать макросы с помощью use, вместо использования атрибута #[macro_use].
  • Абсолютные пути начинаются с имени контейнера, где ключевое слово crate относится к текущему контейнеру.
  • foo.rs и поддиректория foo/ могут сосуществовать; mod.rs больше не требуется при размещении подмодулей в поддиректории.

Это выглядит как произвольный набор правил, но в целом ментальная модель теперь значительно упростилась.

Тут еще много деталей, пожалуйста, обратитесь к руководству по редакциям [8] за выяснением всех подробностей.

Дополнительные правила вывода времен жизни

Давайте поговорим об улучшении, доступном в обоих редакциях: мы добавили некоторые дополнительные правила вывода для блоков impl и определений функций. Код вроде такого:

impl<'a> Reader for BufReader<'a> {
    // здесь методы
}

может быть теперь записан так:

impl Reader for BufReader<'_> {
    // здесь методы
}

Время жизни '_ по-прежнему показывает, что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 SIX: i32 = foo(5);

Функция foo выполнится во время компиляции и SIX примет значение 6.

Константные функции не могут делать все то, что могут делать нормальные функции: они должны иметь детерминированный результат. Это важно из соображений надежности. В текущем виде константные функции могут совершать минимальное подмножество операций. Вот некоторые примеры того, что вы можете в них делать:

  • Использовать целочисленные арифметические операции и операции сравнения
  • Использовать любые логические операции, кроме && и ||
  • Конструировать массивы, структуры, перечисления и кортежи
  • Вызывать другие константные функции
  • Обращаться по индексу в массивах и срезах
  • Обращаться к полям структур и кортежей
  • Использовать константы (но не статические значения, и даже не ссылки на них)
  • Использовать & и * ссылки
  • Приводить типы, исключая приведение сырого указателя к целочисленному значению

Мы будем расширять возможности константных функций, но приведенного выше набора уже достаточно, чтобы использовать const fn на практике.

Подробности смотрите в справочнике [9].

Новые инструменты

Редакция 2018 знаменует начало нового уровня зрелости экосистемы инструментов Rust. Cargo, Rustdoc и Rustup были основными инструментами, начиная с версии 1.0; с редакцией 2018 приходит новое поколение инструментов, которыми теперь все могут пользоваться: Clippy, Rustfmt и поддержка IDE.

Статический анализатор кода clippy [10] теперь доступен в стабильном Rust. Вы можете установить его через rustup component add clippy и запустить командой cargo clippy. Clippy теперь получил версию 1.0 и имеет такие же гарантии стабильности статических проверок, что и rustc. Новые проверки могут добавляться, или может расширяться функционал старых, но старые не могут быть удалены (могут быть только помечены как устаревшие). Это означает, что код, который компилируется с clippy, будет продолжать компилироваться с clippy (при условии, что для проверок не задано генерировать
ошибку через deny), но может выдавать новые предупреждения.

Rustfmt [11] — это инструмент для форматирования кода в Rust. Автоматическое форматирование кода позволит вам сэкономить время, кроме того, оно приблизит ваш код к официальному стилю Rust [12]. Вы можете установить его через rustup component add rustfmt и использовать командой cargo fmt.

Текущий выпуск включает Rustfmt 1.0. Отныне мы гарантируем обратную совместимость для Rustfmt: если вы отформатируете свой код сегодня, то форматирование не изменится в будущем (только для параметров по умолчанию). Обратная совместимость означает, что теперь практично запускать Rustfmt на вашем CI (используйте cargo fmt --check). Попробуйте это вместе с "форматированием при сохранении" в редакторе, и ваш рабочий процесс революционизируется.

Поддержка IDE — одна из самых востребованных возможностей инструментов для Rust. Сейчас имеется несколько решений высокого качества:

Работа по поддержке в IDE не закончена. В частности, автодополнение кода в редакторах, основанных на RLS, не на высоте. Однако, если вы в основном хотите поддержку типов, документации и "перехода к определению", то вы останетесь довольны.

Инструментальные проверки качества кода (tool lints)

В Rust 1.30 [18] мы стабилизировали "инструментальные атрибуты", такие как #[rustfmt::skip]. В Rust 1.31 мы стабилизировали нечто подобное: "инструментальные проверки качества кода" ("tool lints"), такие как #[allow(clippy::bool_comparison)]. Это позволяет задавать пространства имен для проверок, чтобы стало понятнее, из каких инструментов они берутся.

Если вы ранее использовали проверки Clippy, вы можете выполнить миграцию следующим образом:

// было
#![cfg_attr(feature = "cargo-clippy", allow(bool_comparison))]

// стало
#![allow(clippy::bool_comparison)]

Вам больше не нужен cfg_attr! Вам также теперь будут выдаваться предупреждения, которые помогут перейти на использование нового стиля.

Документация

В Rustdoc было несколько улучшений в этом году, и была выпущена полностью переписанная книга "The Rust Programming Language". Вы можете купить бумажную копию от No Starch Press [19]!

Раньше ее называли "вторым изданием" книги, но, так как она стала первым печатным изданием, то это вызвало путаницу. Ведь и печатное издание планируется периодически обновлять. В конце концов, после множества дискуссий с No Starch, было решено обновлять книгу на веб-сайте вместе с каждым выпуском, а No Starch будет периодически забирать изменения и печатать их. Книга довольно хорошо продается и собирает деньги для Black Girls Code [20].

Вы можете найти новую версию книги здесь [21].

Предметные рабочие группы

В этом году мы объявили о создании четырех рабочих групп:

  • Сетевые сервисы
  • Приложения командной строки
  • WebAssembly
  • Встроенные устройства

Группы очень усердно работали, чтобы сделать Rust лучше в каждой из этих областей. Вот некоторые достижения:

  • В сетевых сервисах переработали интерфейс для Futures, а сверх этого еще и async/await. Эти улучшения еще не выпущены, но мы уже близки к этому!
  • Команда CLI работала над библиотеками и документацией, чтобы сделать приложения командной строки лучше.
  • Группа WebAssembly выпустила множество инструментов мирового уровня для использования Rust с wasm.
  • Для встроенных устройств появилась возможность вести разработку ARM на стабильном Rust!

Обо всем этом подробнее можно узнать на нашем новом сайте!

Новый веб-сайт

На прошлой неделе [22] мы анонсировали новую версию нашего веб-сайта. Теперь она стала официальной версией rust-lang.org!

Для ее создания потребовался год работы многих людей. И хотя до полного завершения еще многое нужно сделать, мы гордимся проделанной работой.

Стабилизация стандартной библиотеки

Были добавлены новые реализации From:

  • u8 теперь реализует From<NonZeroU8>, аналогично и для других числовых типов и их NonZero эквивалентов
  • Option<&T> реализует From<&Option<T>>, аналогично и для &mut

Также были стабилизированы следующие функции:

Подробности смотрите в примечаниях к выпуску [2].

Улучшения в 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 для использования в вашем коде.

Подробности смотрите в примечаниях к выпуску [2].

Разработчики 1.31.0

Обычно в конце обзора мы благодарим людей, которые внесли свой вклад в подготовку выпуска [26]. Но в этот раз, в отличии от прошлых, этот список не полностью охватывает всех тех людей, которые помогали, и все то количество работы, которая была проделана. Каждый обычный выпуск — это результат шестинедельной работы, но данный выпуск — это кульминация трех лет усилий, отраженных в несметном числе репозиториев, сделанных огромным количеством людей. Нам было приятно со всеми вами работать, и мы с нетерпением ожидаем продолжения развития Rust в течении следующих трех лет.

От переводчика: выражаю отдельную благодарность участникам сообщества Rustycrate и лично ozkriff [27], humbug [28] и mvlabat [29] за помощь с переводом и вычиткой.

Автор: freecoder_xx

Источник [30]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/301700

Ссылки в тексте:

[1] установить его: https://www.rust-lang.org/tools/install

[2] подробными примечаниями к выпуску Rust 1.31.0: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1310-2018-12-06

[3] впервые в марте: https://blog.rust-lang.org/2018/03/12/roadmap.html

[4] в июле: https://blog.rust-lang.org/2018/07/27/what-is-rust-2018.html

[5] в посте на Mozilla Hacks: https://hacks.mozilla.org/2018/12/rust-2018-is-here/

[6] перевод: https://habr.com/post/432564/

[7] руководство по редакциям: https://doc.rust-lang.org/edition-guide

[8] руководству по редакциям: https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html

[9] в справочнике: https://doc.rust-lang.org/reference/items/functions.html#const-functions

[10] clippy: https://github.com/rust-lang/rust-clippy/

[11] Rustfmt: https://github.com/rust-lang/rustfmt

[12] официальному стилю Rust: https://github.com/rust-lang/rfcs/blob/master/style-guide/README.md

[13] Visual Studio Code: https://marketplace.visualstudio.com/items?itemName=rust-lang.rust

[14] IntelliJ: https://plugins.jetbrains.com/plugin/8182-rust

[15] Atom: https://github.com/rust-lang-nursery/atom-ide-rust

[16] Sublime Text 3: https://github.com/rust-lang/rust-enhanced

[17] Eclipse: https://www.eclipse.org/downloads/packages/release/photon/r/eclipse-ide-rust-developers-includes-incubating-components

[18] Rust 1.30: https://blog.rust-lang.org/2018/10/25/Rust-1.30.0.html

[19] бумажную копию от No Starch Press: https://nostarch.com/rust

[20] Black Girls Code: http://www.blackgirlscode.com/

[21] здесь: https://doc.rust-lang.org/beta/book/

[22] На прошлой неделе: https://blog.rust-lang.org/2018/11/29/a-new-look-for-rust-lang-org.html

[23] slice::align_to: https://doc.rust-lang.org/std/primitive.slice.html#method.align_to

[24] slice::chunks_exact: https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact

[25] slice::rchunks_exact_mut: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut

[26] людей, которые внесли свой вклад в подготовку выпуска: https://thanks.rust-lang.org/rust/1.31.0

[27] ozkriff: https://habr.com/users/ozkriff/

[28] humbug: https://habr.com/users/humbug/

[29] mvlabat: https://habr.com/users/mvlabat/

[30] Источник: https://habr.com/post/432640/?utm_campaign=432640