LINUX.ORG.RU

Rust 1.31.0 (2018)

 , rust2018


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 ()
Последнее исправление: Deleted (всего исправлений: 5)

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

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

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

и теперь в дополнение к mut появился const. умора.
и уж какой великий смысл в больших буквах в стандартной либе?

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

выпилять большие буквы из абихода, все можно писать маленькими буквами.

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

Не планирую ли в C внедрить GC?


в тем виде, в каком оно в раст? есть же шаблоны всякие, и буст - уродство.
rust их переплюнул в этом деле. <Rc<Box<Option<

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

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

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

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

Вон в лисе уже пол ляма строк на расте.

Говорят что лиса скоро того...

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

Конечно. Но начинать новые проекты на C/C++, если это не суровый энтерпрайз, - как минимум странно.

Поддержу здесь анонима. А на чем писать, если это не бэкенд, скажем?

В пользу C/C++ говорит то, что довольно много удачных проектов, написанных на этих двух языках, как ни странно, очень долго живет. Если закладываться на перспективу, то и сейчас C++ мне кажется очень интересным вариантом. Чтобы через 15 лет не пришлось переписывать кодовую базу.

Rust мне очень нравится, но мне тоже, как и уже другому товарищу, кто отписался выше, будущее его кажется туманным. Язык прекрасен, инфраструктура тоже, сообщество хорошее, но обычно нишу занимает не тот, кто самый лучший, а тот, кто оказался первым самым приспособленным, кто удачно оказался в нужном месте и в нужное время. Таким был C++ безусловно.

Хотя вот сдается мне, что подрастающее поколение не очень-то умеет программировать на «сложных» языках, а главное, что не хочет. И да, тут Rust перспективен в нише языков системного программирования, потому что на мой взгляд на Rust писать в разы проще, чем на C++. Вот, перечитываю Страуструпа - это ж кошмар, сколько там деталей, тогда как Rust прост и понятен.

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

потому что на мой взгляд на Rust писать в разы проще, чем на C++

На нем сложнее писать плохой код, это его недостаток.

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

Поинт был в покупании того, что уже устарело. Зачем? В руст 2019 еще и синтаксис перелопатят.

Deleted
()

предлагаю ввести в обиход «растовчанин» и «растовчанка», тк хипстер звучит обидно

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

код которых читать затруднительно даже в случае его хорошего знания

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

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

Мне нужно понять философию языка и получить системные знания, каковые может дать только книга. Для остального есть документация.

perl5_guy ★★★★★
()
Ответ на: комментарий от anonymous
fn main() {
    let mut x = 10u8;
    unsafe { 
        *std::mem::transmute::<_, &mut u64>(&mut x) = 512u64; 
    }
}
Deleted
()
Ответ на: комментарий от dinama

Это был бессмысленный жирный вброс с моей стороны, соответствующий уровню чуши автора.
Переплюнул в чём? В уродстве? Нет, совершенно нет.

make_shared<unique_ptr<optional<T>>>(make_unique<optional<T>>(optional<T>(value))
vs
Rc::new(Box::new(Some(value)))
. Это ещё не говоря о том, что Rc<Box<Option<T>>> - это какой-то «особый» случай без всякого смысла.

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

Ах да, в расте же move-by-default. Улучшим вариант на C++.

make_shared<unique_ptr<optional<T>>>(make_unique<optional<T>>(optional<T>(move(value)))
vs
Rc::new(Box::new(Some(value)))


Или, если всё же нужно именно копирование:
Rc::new(Box::new(Some(value.clone())))

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

Ну хорошо, ты меня уделал. Но это всё равно ничем не лучше того что в расте (Это не к тому что хуже, а к тому что раст не более кошмарный чем C++).

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

не последний аргумент и не сноба. А делёжка опытом. Я поизучал много тем в программировании и в частности много языков ( Rust только начал изучать из любопытства, но назначение let, mut и fn понял, потому что задумался - зачем они в языке, призванном заменять C/C++, на которых я программировал. Задумался как раз из своего опыта - что надо понять назначение синтаксиса) . По моему опыту, при изучении нового языка программирования полезно понять назначение особенностей его синтаксиса. Кто вместо этого сразу начинает считать авторов языка дураками, тому трудно понять синтаксис, а значит весь язык.

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

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

Столько же, сколько и в Rc<Box<Option<T>>> - 0. Но автор сказал про эту конструкцию, поэтому именно её аналог и был приведён.

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

перечитываю Страуструпа - это ж кошмар, сколько там деталей

+inf

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

когда Страуструп решил его запилить, ему это ЕМНИП нужно было для исследований в области распределенных систем

В те времена не было особого выбора ЯП для прототипирования, даже перл еще не появился, а вычислительные ресурсы все еще были в дефеците

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

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

Правда текущие поделки пока все равно на сях, потому что в расте инфраструктура библиотек еще мясом не обросла. Но это все «до первого столба». То что интересует лично меня (GUI и т.п.), дозреет за 1-2 года скорее всего.

Я не большой фанат скакать по новым языкам за фичами. Просто у сей и плюсов ситуация дошла до стадии «все что угодно будет лучше». Так в свое время похапе просрал полимеры.

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

Я вполне успешно в питоне «взаимодействовал» с сишным наследием, не написав ни строчки на си. Благо встроенный ffi это позволяет. Тут главное не поддаться соблазну и самому ничего не накалякать на си. Не раскачивать лодку, так сказать)

Deleted
()

Я прочитал половину книжки по расту.

Читать дальше или забить? Кресты не знаю от слова совсем.

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

Если декларировать структуры данных не в коде, а где-нибудь в отдельных json/yaml файлах и не пользоваться макросами, то нормально читается. А, и главное tokio не юзать. Код с tokio вообще не читабелен

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

Отличие Rust в том, что там на уровне языка ... приняты меры для того, чтобы он был безопасным, и он безопасен _по умолчанию_

Конечно, особенно когда идет вызов FFI в С/С++ или новичок на проекте пишет unsafe код. Уберите эти два механизма из Раста потом только утверждайте так громогласно что " он безопасен _по умолчанию_".

Замечательно. То есть претензии предъявляются к тому, что

  • Вызов из Rust кода на другом языке является принципиально небезопасным.
  • Указание компилятору «Я хочу отключить некоторые твои проверки, которые позволяют тебе называться безопасным ЯП» позволяет писать потенциально небезопасный код.

?

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

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

<Rc<Box<Option<

Зачем у тебя Box в Rc?<

О, да! Поймал товарища.

Нет, не поймал. Не думаете же вы, что он знает Rust? Просто нашлепал словечек пострашнее из тех, что часто мелькают.

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

«Промисы». Цепочки из лямбд. Они и в js то не читабельны, а тут вообще. Но это так, фигня. Скоро же async. Больше претензий к String::from(«porn») (оно же «porn».to_owned()). Из-за чего структуры данных определять в расте противно. Казалось бы, почему не добавить сахарку (например d"porn")

Еще матиматика выглядит забавно. Как лишп наоборот:

let d = ((p1.x - p2.x).abs().powi(2) + (p1.y - p2.y).abs().powi(2)).sqrt();

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

Ну это уже не мне решать как лучше. Факт в том, что в нынешнем состоянии оно причиняет боль. Далеко ходить не надо, можо глянуть как serde-json пытается изгаляться, но так ничего удобного и не придумал

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

Ответить на твои вопросы, однако, нетрудно:

отказаться от ключевых слов let и fn

Эти ключевые слова значительно упрощают синтаксический разбор, чтобы не было как в С++.

сделать по умолчанию mut

Очевидное вредительство. Неизменяемые привязки встречаются куда чаще, и в отличие от const, mut нельзя забыть — так что язык способствует правильному использованию изменяемости.
Хорошо разработанный язык способствует хорошим практикам, а не антипаттернам.

отказаться от верхнего регистра

Регистр указывает чем является конкретное имя — переменной, типом или константой.

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

Futures ещё не готовы. Когда будут готовы, тогда не будет цепочек из лямбд (комбинаторов), а будет await как у белых людей.
Что-то не ясно почему противно.

"porn".into()

Только у тебя. Делаешь свои трейты / Перегружаешь операторы => Получаешь математику для людей:
let distance = (p1 - p2).length();
let distance = p1.distance_to(p2);

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

нифигасе зачем ты заимствуешь чужой код в unsafe блоки? пиши свой! там фанбои выше писали, что если напилить свой unsafe код то растишка все растаманам гарантирует гыгыгы

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

если чо. эт стандартная в расте ситуация тащить в язык новые фичи. пипл захочет то затащат. ты не расстраивайся, подстраивайся

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

учи матьегоматику! ты что глупец не знаешь что отрицательное число в квадрате равно ... отрицательному? а вдруг? это раст тут может быть любая фигня любой подвох. верить низзя никому

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

можо глянуть как serde-json пытается изгаляться, но так ничего удобного и не придумал

А покажи, где придумали удобно.

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

Чтоб тебе всю жизнь писать на Аде, и только в Ravenscar profile.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.