LINUX.ORG.RU

Rust 1.31.0 (2018)

 ,


5

9

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

Спрошу тут, чтобы далеко не ходить

Подскажите, как запускать «cargo build», чтобы он линковал с помощью lld? lld в системе стоит, но cargo мне пишет «linker `cc` not found»

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

Там по контексту у vertexua следовало, что «Typed Python» должен защищать от «ошибок типов в рантайме». Но mypy от них не защищает, по-крайней мере не полностью. Просто эдакий развитый линтер.

На мой взгляд, mypy вообще убог и ни разу не python-way. Но есть более вменяемые альтернативы. Пока видел только черновики. Может в Python 4 что-нибудь будет. Хотя это всё оффтопик под этой новостью.

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

Вам всем сразу «любых ошибок». О любых ошибках легко говорить потому что никто не говорит о каких конкретно. Значит где-то поджидает такая страшная ошибка что мы все можем только дрожать и догадываться о ней. В качестве бонуса для тебя, ты будешь гордиться своим чуством правоты.

Реально же Typed Python - работает там где типи прописали. Не прописали - не работает. Но там где прописали - там лучше с ними чем без них. Напиши их по всем проекту и будет тебе счастье. То что это линтер - да это линтер, но алгоритм в нем скорее всего такой же как в каком-то компиляторе. Оформлено в виде линтера просто потому что мы хотим делать это один раз на CI-сервере вместе с тестами, а не при каждом запуске скрипта. Интерпретатор научили просто работать как раньше и игнорировать сигнатуры типов

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

Еще раз, типы лучше чем без типов. Если их где-то нету, то и раньше не было, так что ситуация не стала хуже, только лучше. Зато множество проблем будет решено в логике самого проекта и это круто

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

В пистоне есть типы, как и во всех (почти) языках. Ты говоришь про статические проверки, а для них mypy как и любой gradual-typing мало пригоден. Статическая типизация должна быть изначально, ее не бэкпортировать, так как любой динамический язык допускает unsound код в любой даже самой продвинутой системе типов.

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

Так и раньше допускал. Для статических типов сразу как раз и есть другие языки. Но если компания дико завязана на Python, то всем собраться, сказать «Хватит это терпеть» и начать добавлять везде типы - адекватное решение. Не будет 100% гарантии, но раньше было 0% гарантии. Если сейчас станет 70%, то это уже ценность для бизнеса в том числе.

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

«Хватит это терпеть» и начать добавлять везде типы - адекватное решение.

В случае пистонов по трудоемкости это равносильно написанию огромного количества тесткейсов, что обычно и предпочитают линтерам. Проблема даже не в том, чтобы расставить аннотации, а в том, чтобы примерить потенциально unsound код с системой типов. Все равно половина аннотаций будет дырявой, в духе String -> Any.

Ты что, никогда не видел плохой код на js/python, там всюду ад из-за отсутствия самодисциплины, присущей людям, привычным к статике.

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

Ты сам придумал называть mypy «Typed Python»? Потому что типы в питоне есть и без mypy. А mypy обеспечивает статические проверки аннотаций. Что ты в аннотациях напишешь, то и будет проверяться. И их всегда нужно прописывать ручками.

Но ок, твой поинт я понял. Typed Python sucks, but sucks less.

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

Если проект приходит к пониманию, что ему нужен статический анализ, значит пришло время выкидывать питон. Для истиных же питонщиков и рубистов писать типы это зашквар: «зачем мне писать лишний код, если питон делает всё за меня»

Я помню на реддите задавал попрос и в нем был кусок кода с типами. Вот они на меня набросились. Каждый так и норовил выразить свое Фи в тактичной европейской манере

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

Ты что, никогда не видел плохой код на js/python, там всюду ад из-за отсутствия самодисциплины, присущей людям, привычным к статике

Немного позанудствую, но всё не так. Приставка само- у тебя как раз лишняя. К дисциплине в статике принуждает компилятор, бьёт по рукам. И чем сильнее бьёт, тем лучше дисциплина.

А само-дисциплина как раз нужна в «либеральных» языках вроде Python. Без самодисциплины получается слишком говно.

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

Они используют https://doc.rust-lang.org/std/macro.thread_local.html чтобы получать доступ к ивент-лупу неявно. При этом паника случается только при попытке припарковать таск, что в нашем случае произошло при запуске миграции, которая переполнила мейлбокс.

Не зря их за unsafe ругали.

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

Да, с крабом. Jim Blandy & Jason Orendorff. Отличная книга! Иллюстрации великолепные и содержание замечательное.

Язык не так и сильно изменился с издания книги. Ну, там &dyn, use crate и прочие вещи появились позже, но с ними можно освоиться и потом.

Не знал, что на русский уже перевели. Хорошая новость.

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

Птичий язык, не нужно!

а птица та - с красным гребешком?
а если серьёзно, то из новости видно, что разработчики адекватны и стремятся минимизировать обилие :';>

liberty1 ()

Не планируют ли они - отказаться от верхнего регистра в стандартной либе - отказаться от ключевых слов let и fn - сделать по умолчанию mut и выкинуть это ключевое слово.оставив const ?

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

как rust для быстрого прототипирования нынче?

Если уже освоился с языком и боров-чекер не напрягает, то нормально. Мне было даже удобнее прототипчик писать на Rust вместо Python, так как компилятор проверял соответствие типов и в дополнение к этому небольшие тесты набросать в Rust всегда крайне просто. Можно начинать писать все в одном файле, а потом быстро выносить куски кода в отдельные модули при разрастании прототипа. Собственные типы сначала вводишь просто как unit-like структуры, без полей. И типажи с unimplemented! методами. Если нужно указать тип, но пока не решил, каким он будет - просто пишешь там `()` и позже рефакторишь. Все это давало кучу фана и уверенности в корректности работы кода на каждой итерации.

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

Не планируют ли они - отказаться от верхнего регистра в стандартной либе - отказаться от ключевых слов let и fn - сделать по умолчанию mut и выкинуть это ключевое слово.оставив const ?

Нифигасе заява. Разумеется, это нереально.

При изучении нового языка надо задумываться - зачем это сделано, а не удовлетворяться простым объяснением, что авторы языка дураки и сделали просто так. В ваших примерах сделано не просто так.

Поняв, зачем это сделано, можно более успешно этим пользоваться.

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

а в оригинале как пожарная машина стоит

Удивлен, что книга, написанная ради быстрого сруба бабла, стоит дорого? Покупать книгу по сырой двухнедельной быстроразвивающейся технологии это надо быть знатным любителем копрофилии.

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

А сколько тебе надо? Инженеров и учёных должно быть достаточно, а не больше чем маркетологов. Их достаточно.

Это понятно, что инженеров и учёных достаточно. Непонятно, нахрена столько маркетологов. Боятся, что без агрессивного маркетинга раст никто не купит?

anonymous ()

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

и даже учить ничего не надо!

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

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

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

Еще и тип фиксируется. И в локальном контексте объявляется. Ужас одним словом. Другое дело js

function foo() {
  name = 'Vanya';
}

Удобно, если переменная понадобится где-то в другом месте. Например, в другой функции

function bar() {
  old_name = name;
  name = 0xbeadbeef;
}

Удобно, в общем. Забыл как называется этот паттерн. Надо Александреску перечитать

spoonbob ()

руст это очередной язык который должен убить Си++? (до него это пытались Джава и Шарп). Есть хоть бенчи какие-нить где реализованы какие-нить сравнения, чей выхлоп работает быстрее? Причем добросовестно реализованы, максимально используя возможности языков, а не с целью превознести один язык над другим.

Просто встречал такие тесты, в наример на ++ так делали (int i=0; i<v.size(); ++i) - что само по себе уже занижение производительности в купе с глупой надеждой на оптимизацию кода компилятором.

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

руст это очередной язык который должен убить Си++? (до него это пытались Джава и Шарп)

Во времена жавы и шарпа, лучшие умы от разработки ЯП таки разобрались как правильно сделать GC и пошла штамповка языков с GC. А сейчас щупают теорию ЯП на предмет автоматического управления памятю без GC. Отсюда вытекли rust и swift. C++ в этом плане догоняющий старичок. Не особо успешно догоняющий

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

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

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

eao197 ★★★★★ ()