LINUX.ORG.RU

Rust 1.31.0 (2018)

 ,


5

10

Команда 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.

Подробный список изменений можно посмотреть здесь.

>>> Подробности

★★★★★

Проверено: Shaman007 ()

Ответ на: комментарий от xDShot

Он на это и не притендовал. Да и вообще, нет языков где в рантайме нет ошибок, например: забыл в Java обработать исключение? RIP.
Но есть же разница между «паникой» в Rust, которая приводит к разматыванию стека, и UB в C++.

dearAmomynous ()
Ответ на: комментарий от spoonbob

Ты обладаешь иной точкой зрения

...скорее, еще кое что помню из истории. Вот в 1980-х на свет появилось всего несколько языков без GC, которые более-менее широко использовались: Ada, C++, Objective-C, ObjectPascal. Ну и сюда же можно, наверное, добавить Modula-2 из конца 1970-х.

Остальное, что вспоминается из тех времен, было с GC. Вот навскидку: SmallTalk, Eiffel, Common Lisp, Erlang, Perl, Python. Причем это были далеко не первые языки с GC.

Широкому распространению языков с GC препятствовало вовсе не то, что «лучшие умы от разработки ЯП» еще не разобрались как правильно. А в то, что машины тогда были на порядки более дохлыми и памяти там было всего ничего. Что как бы не помогало работе GC.

Своему успеху Java и C# обязаны, прежде всего, невероятно быстрому росту мощности вычислительной техники, который наблюдался где-то с конца 1980-х до конца 2000-х. Если бы не это и если бы сейчас машина с процессором на 25MHz и 16Mb RAM считалась бы очень мощной, стоила бы десятка полтора килобаксов, то никаких Java и C# в мейнстриме не было бы.

eao197 ★★★★★ ()
Последнее исправление: eao197 (всего исправлений: 1)
Ответ на: комментарий от spoonbob

For now, this reference is a best-effort document. We strive for validity and completeness, but are not yet there. In the future, the docs and lang teams will work together to figure out how best to do this. Until then, this is a best-effort attempt. If you find something wrong or missing, file an issue or send in a pull request.

Полуркай получше, где-то было про то что я написал. Не сам же я это придумал, в конце то концов!

dearAmomynous ()
Ответ на: комментарий от dearAmomynous

Сам луркай. Переменная оно или нет — это вопрос терминологии. В официальном документе по синтаксису раста говорится про мутабельные и иммутабельные переменые

spoonbob ()
Ответ на: комментарий от spoonbob

https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html Но это уже не та книга, что была в 2016, потому и отличия. Хотя если ты внимательно будешь читать, то не один раз встретишь «value bound to name».

dearAmomynous ()
Последнее исправление: dearAmomynous (всего исправлений: 1)
Ответ на: комментарий от dearAmomynous

const int x = 4;

const в си - это костыль, который легко снимается приведением к не-конст. В си без препроцессора нет понятия биндинга. Попробуй снять неконстантность дефайна. Только не надо развивать тему про ущербность препроцессора, который придуман раньше чем я. Но в препроцессоре есть понятие биндинга, в си без препроцесора - нет.

anonymous ()
Ответ на: комментарий от anonymous

В Rust (вроде как) тоже можно снять константность с let x = 4; через unsafe + std::mem::transmute, но в доках чёрным по белому написано что делать из не-mut mut - это всегда UB. Сознательный выстрел в ногу. А const X: i32 = 4; - это как раз сродня #define X 4, потому как изменить нельзя вобще никак (Нет адреса), к тому же как и дефайн - инлайнится.

dearAmomynous ()
Ответ на: комментарий от eao197

Если бы не это и если бы сейчас машина с процессором на 25MHz и 16Mb RAM считалась бы очень мощной, стоила бы десятка полтора килобаксов, то никаких Java и C# в мейнстриме не было бы

Сейчас в кармане у каждого машина в 100 раз мощнее, но приложения с GC все-равно безбожно тормозят:) А GC завоевал сердечки разработчиков задолго до того, как машины стали нормально его переваривать. Видать разработчикам оочень не хотелось делать free() вручную, а заставить делать это компилятор в те времена никому не удалось (хотя в статье про Ada упоминается про некие access types, которые, по описанию, делают именно это)

spoonbob ()
Ответ на: комментарий от spoonbob

Во времена жавы и шарпа, лучшие умы от разработки ЯП таки разобрались как правильно сделать GC

Сейчас в кармане у каждого машина в 100 раз мощнее, но приложения с GC все-равно безбожно тормозят

Вы уже свою альтернативную одаренность продемонстрировали, зачем же ее демонстрировать еще раз?

eao197 ★★★★★ ()
Ответ на: комментарий от anonymous

Ни разу. Код ниже показывает что тебе нужно явно сказать компилятору что ты идиот и хочешь сделать глупость. Rust спасает от UB по дефолту, но если ты самоуверен и очень-очень хочешь пальнуть себе в ногу - то это твоё личное дело, он не будет тебе это совсем запрещать.

dearAmomynous ()
Ответ на: комментарий от anonymous

И вобще std::mem::transmute - это одна из самых «опасных» функций, аналог каста из C без всяких проверок. Можно менять мутабельность, стирать лайфтаймы, пихать переменные большего размера в переменные меньшего размера и т.д.

dearAmomynous ()
Последнее исправление: dearAmomynous (всего исправлений: 1)
Ответ на: комментарий от eao197

Ты зацепился за одно мое расплывчатое утверждение, чтобы блестнуть знанием истории ЯП и снять напряжение. Но по сществу ничего так и не ответил. Раз не можешь в нормальную дискуссию, иди лучше накати да в танки партийку отыграй

spoonbob ()
Ответ на: комментарий от anonymous

И? Что в этом плохого? Ну взял ты адрес - и что? Арифметические операции с адресом недоступны, изменить объект по ссылке - тоже нельзя. В чем проблема то? При попытке let x = 4; let y = &mut x; получишь ошибку компиляции. Ссылки живут только на стеке, кстати.

dearAmomynous ()
Ответ на: комментарий от spoonbob

чтобы блестнуть

Нет, просто искренне рад тому, что для людей с вашими мозгами придумывают Java, C#, Go и вот сейчас Rust. Раз уж вы оказались в профессии, то лучше, чтобы вы программировали на Rust-е, а не на C++ или, недайбох, на чистом C.

eao197 ★★★★★ ()
Ответ на: комментарий от dearAmomynous

Дальше с тобой спорить не буду, потому что мне не интересно развивать эту тему, а ты упорно стоишь на своем, что биндинги - это почти переменные в си. Я свою точку зрения высказал, что еще один си c его UB с полученем адреса у биндинга не нужен.

anonymous ()
Ответ на: комментарий от eao197

Спасибо. Мои мозги действительно не способны работать с кучей на Си. Как-то два дня не вылезал из valgrinda, разбираясь почему падает програмка в 300 строк, наполненная структурами с динамическими массивами

spoonbob ()
Ответ на: комментарий от dearAmomynous

Слив засчитан.

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

anonymous ()
Ответ на: комментарий от O02eg

настоящие™ программисты на С

По поводу «настоящих программистов на С» — это вам к Iron_Bug.

А вот тот факт, что персонажи, которые не могут найти ошибку в программе на 300 строк, сейчас в профессии весьма прискорбен. И раз уж так случилось, пусть уж лучше за такими персонажами компилятор Rust-а сопли подтирает.

eao197 ★★★★★ ()
Ответ на: комментарий от anonymous

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

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

tailgunner ★★★★★ ()
Ответ на: комментарий от anonymous

Я агрюсь лишь потому что ты говоришь что «еще один си c его UB с полученем адреса у биндинга не нужен». Но где там UB? В unsafe? Ты правда не видишь разницы, между Rust, где малая доля кода потенциально «опасна» (Компилятор не может проверить корректность), и C (Где компилятор предоставляет тебя самому себе, почти не делая никаких проверок)?

dearAmomynous ()
Последнее исправление: dearAmomynous (всего исправлений: 2)
Ответ на: комментарий от tailgunner

Чтобы объяснять, нужен одинаковый набор понятий у собеседников. Иначе это будет комедия и фарс, как с твоим «ссылка или цикл». Я знаю, у нас они разные, потому ничего объяснять не буду. Это будет слишком смешно, чем полезно. И судя по тому как сагрились остальные, то я не хочу выступать в роли «шута» для привилегированных «членов» системы, который собрались на представление.

anonymous ()
Ответ на: комментарий от tailgunner

А настоящие программисты в этом не нуждаются, ага.

Нормальные программисты в состоянии это сами сделать. Им это, конечно, может надоесть и они с удовольствием воспользуются более удобным и безопасным инструментом.

Но это принципиально отличается от программистов, которые в принципе сами себе сопли утереть не могут.

Печалька в том, что таких все больше.

Ты хочешь с ними работать над общим кодом? Пусть даже в Rust-е?

Iron_Bug, перелогинься.

Ты бы это, за базаром следил.

eao197 ★★★★★ ()
Ответ на: комментарий от anonymous

Чтобы объяснять, нужен одинаковый набор понятий у собеседников. Иначе это будет комедия и фарс

Раньше ты оправдывался тем, что ответы стирают. Рад, что это не так.

комедия и фарс, как с твоим «ссылка или цикл»

О чем ты? Напомни.

tailgunner ★★★★★ ()