LINUX.ORG.RU

Rust 1.16

 ,


2

7

Представлен релиз Rust 1.16 — системного языка программирования, нацеленного на безопасную работу с ресурсами, скорость и параллельное выполнение кода. В этот релиз вошли 1364 патча от 137 разработчиков.

Если у вас уже установлена предыдущая версия Rust, то обновиться до Rust 1.16 очень легко:

$ rustup update stable

Самое крупное нововведение в Rust 1.16 — новая субкоманда cargo check направленная на ускорение процесса разработки.

Что она делает? Давайте рассмотрим как rustc компилирует код. Компиляция происходит в несколько проходов, шагов от исходного кода до исполняемого файла. Все эти шаги (и затраченные на них ресурсы) можно увидеть, передав компилятору ночной ветки -Z time-passes

rustc .\hello.rs -Z time-passes
time: 0.003; rss: 16MB  parsing
time: 0.000; rss: 16MB  recursion limit
time: 0.000; rss: 16MB  crate injection
time: 0.000; rss: 16MB  plugin loading
time: 0.000; rss: 16MB  plugin registration
time: 0.049; rss: 34MB  expansion
Мысленно эти шаги можно разбить на два больших: сначала rustc совершает все проверки безопасности, убеждается в корректности синтаксиса, и всё такое, а после он выполняет оптимизации и генерирует бинарный код.

Последний шаг занимает очень много времени. К тому же, он не всегда нужен. Типичный процесс разработки выглядит как-то так:

  • Пишем немного кода.
  • Запускаем cargo build, чтобы проверить, что код компилируется.
  • Повторяем предыдущие шаги N раз.
  • Запускаем cargo test, чтобы убедиться, что все тесты проходят успешно.
  • Возвращаемся в начало.

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

Другие улучшения

Для работы cargo check компилятор научился генерировать новый формат файлов: .rmeta. Такие файлы содержат метаданные о каком-либо одном крейте. cargo check использует эти данные для анализа зависимостей проекта и позволяет компилятору сделать проверки типов из сторонних библиотек.

Удалена диагностика consider using an explicit lifetime parameter, появляющаяся если в коде были использованы неправильные аннотации времени жизни. Рассмотрим пример:

use std::str::FromStr;

pub struct Name<'a> {
    name: &'a str,
}

impl<'a> FromStr for Name<'a> {
    type Err = ();

    fn from_str(s: &str) -> Result<Name, ()> {
        Ok(Name { name: s })
    }
}
Здесь компилятор не уверен, что делать с временем жизни: код не гарантирует что s проживет столько же, сколько Name, как того требуется. Компилятор Rust 1.15 выведет:
> rustc +1.15.1 foo.rs --crate-type=lib
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
  --> .\foo.rs:10:5
   |
10 |       fn from_str(s: &str) -> Result<Name, ()> {
   |  _____^ starting here...
11 | |         Ok(Name { name: s })
12 | |     }
   | |_____^ ...ending here
   |
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name, ()>
  --> .\foo.rs:10:5
   |
10 |       fn from_str(s: &str) -> Result<Name, ()> {
   |  _____^ starting here...
11 | |         Ok(Name { name: s })
12 | |     }
   | |_____^ ...ending here
Компилятор описывает проблему и дает рекомендации по исправлению. Модифицируем код согласно им и пробуем снова:
> rustc +1.15.1 .\foo.rs --crate-type=lib
error[E0308]: method not compatible with trait
  --> .\foo.rs:10:5
   |
10 |       fn from_str(s: &'a str) -> Result<Name, ()> {
   |  _____^ starting here...
11 | |         Ok(Name { name: s })
12 | |     }
   | |_____^ ...ending here: lifetime mismatch
   |

help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name<'a>, ()>
  --> .\foo.rs:10:5
   |
10 |       fn from_str(s: &'a str) -> Result<Name, ()> {
   |  _____^ starting here...
11 | |         Ok(Name { name: s })
12 | |     }
   | |_____^ ...ending here
Всё ещё не работает. Предлагается добавить еще одно время жизни, на этот раз для Name
> rustc +1.15.1 .\foo.rs --crate-type=lib

help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name<'a>, ()>
  --> .\foo.rs:10:5
...и наконец код скомпилировался.

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

Есть и другие изменения, касающиеся диагностик. Предыдущая версия Rust уже научилась предлагать исправления опечаток:

let foo = 5;

println!("{}", ffo)
error[E0425]: cannot find value `ffo` in this scope
 --> foo.rs:4:20
  |
4 |     println!("{}", ffo);
  |                    ^^^ did you mean `foo`?
Но это происходило только для опечаток в локальных переменных и полей в структурах. Сейчас Rust предлагает исправления опечаток почти везде.

Стабилизация библиотек

Также стабилизированы некоторые мелкие улучшения:

  • writeln! теперь можно вызывать без аргументов, как println!, для перевода строки.
  • Все структуры в стандартной библиотеке теперь реализуют Debug

Улучшен формат ошибок при получении среза &str. Например:

&"abcαβγ"[..4]
Этот код содержит ошибку:
thread 'str::test_slice_fail_boundary_1' panicked at 'byte index 4 is not
a char boundary; it is inside 'α' (bytes 3..5) of `abcαβγ`
Часть после ; — новая.

Возможности Cargo

Дополнительно к cargo check, Cargo и crates.io получили пару новых возможностей.

  • cargo build и cargo doc теперь принимают флаг --all для сборки и документации всех крейтов в рабочем пространстве одной командой.
  • Cargo теперь принимает флаги --version --verbose, по образу rustc.
  • Crates.io может отображать значки AppVeyor и TravicCI на странице крейта.
  • В Cargo и crates.io появились категории. В отличие от ключевых слов, категории модерируются. Ключевые слова используются для поиска, категории — нет. Другими словами, ключевые слова помогают искать крейты, а категории — просматривать.
  • На crates.io теперь можно просматривать крейты по категориям.

Больше информации можно узнать в развернутых release notes.

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

Если у вас уже установлена предыдущая версия Rust, то обновиться до Rust 1.16 очень легко

блин, исправьте пожалуйста на «разработчики, которым необходимы возможности новой версии, и любители Bleeding Edge могут установить новую версию командой...»

а то такая фраза прям призывает «на кол пакетный менеджер дистра, даешь зоопарк!».

p.s. да, у меня опять бомбит от этого, уже 4 новости о расте подряд. а то будет блин как с Go - версия в репах давно протухла, а народ все обновляется и обновляется, даже не понимая нахрена им оно надо

upcFrost ★★★★★ ()
Последнее исправление: upcFrost (всего исправлений: 1)

...и наконец код скомпилировался.

Наглая ложь, этот код не может скомпилироваться потому что `error[E0308]: method not compatible with trait`, цитата из оригинала:

An aside: the above implementation is not possible; Name would need to use String, not &str.

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

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

Вы это авторам напишите. Крики на лоре погоды не сделают.

как раз на лоре сделают. и на слешдоте/реддите. смысл не в том что у разрабов есть менеджер обновлений, это просто хорошо упрощает жизнь тем кому реально нужна новая версия (мало ли, вдруг в Go дженерики завезут). а вот юзерам надо вбивать в голову что этот механизм обновки нужен только любителям Bleeding Edge и тем, кому действительно необходима самая распоследняя версия

вот скажем взять ruby. для него есть rvm, и когда реально 100% нужна новая версия, которую в шапку/центось никто не завозил - можно заюзать его. а в остальных случая юзать штатный пакет

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

Даже тем пользователям которые используют nightly? Или тем у кого в репозиториях прошлогодняя stable на которой уже ничего не собирается, потому что все разработчики используют новые фичи языка?

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

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

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

Пользователям rustup вообще не нужен.

от пользователя зависит, если нужен софт который сильно выигрывает (или вообще невозможно сделать иначе) от новой версии - то им он тоже нужен.

хотя разрабам имхо тоже надо вбивать в голову что не следует бездумно забивать на совместимость.

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

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

вот потому я и стреляю пуканом. из этих разрабов новые фичи нужны от силы 5%. ну вот на кой бес они ломают совместимость, заставляя людей юзать зоопарк менеджеров

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

а то такая фраза прям призывает «на кол пакетный менеджер дистра, даешь зоопарк!»

Rustup живёт целиком в $HOME, он позволяет держать зоопарк различных версий (и платформ) и его можно научить подхватывать и системную версию.
Так что не вижу особых проблем.

quantum-troll ★★★★★ ()

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

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

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

Это проблемы дистров.

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

Ну вот зачем пользователю nightly сборка компилятора?

Ну например затем чтобы писать код под STM32

Это проблемы дистров.

Для решения которых придумали rustup

pftBest ★★ ()
Последнее исправление: pftBest (всего исправлений: 1)

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

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

Ну вот зачем пользователю nightly сборка компилятора?

Ну например затем чтобы писать код под STM32

Видимо мы вкладываем разный смысл в слово «пользователь».

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

Это пример, показывающий концептуальную проблему, а не боевой код.

Этот пример неправильно переведен с английского. Вместо

...и наконец код скомпилировался.

Должно быть

Все равно не компилируется, и рекомендует поставить значок 'a там где он уже стоит.

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

Видимо мы вкладываем разный смысл в слово «пользователь».

Пользователь компилятора использует компилятор чтобы компилировать код. Какая разница кто написал этот код?

pftBest ★★ ()
Ответ на: комментарий от quantum-troll

Rustup живёт целиком в $HOME ... его можно научить
Так что не вижу особых проблем.

это и есть проблема. Сама инфраструктура жить в хомяке не должна. Rustup может жить в хомяке как менеджер версий, но надо на каждом запуске раза 3-4 предупредить разраба/юзера что лучше бы он юзал версию из реп дистрибутива, обеспечивая тем самым стабильность и совместимость.

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

Ну например затем чтобы писать код под STM32

пользователь (обычный юзер) код под STM32 писать точно не будет. разраб будет, это да. и для него rustup вполне нужен, правда без прописывания новой версии куда бы то ни было, чтоб в основной системе стояла основная версия.

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

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

 ___________________________________
/ error[E0495]: cannot infer an     \
| appropriate lifetime for lifetime |
| parameter in generic type due to  |
\ conflicting requirements          /
 -----------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     || .\foo.rs
anonymous ()
Ответ на: комментарий от RazrFalcon

Пользователь вообще ничего не компилирует. Компилирует разраб

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

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

стабильность и совместимость.

В ubuntu lts в репозиториях сейчас версия 1.7. Ни один нормальный разработчик не будет ее сейчас использовать, она слишком неудобна по сравнению с текущей. И большинство библиотек требуют версию не ниже 1.12. Так что такого

3-4 предупредить что лучше бы он юзал версию из реп дистрибутива

точно не будет.

pftBest ★★ ()

Если у вас уже установлена предыдущая версия Rust, то обновиться до Rust 1.16 очень легко:
$ rustup update stable

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

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

В ubuntu lts в репозиториях сейчас версия 1.7. Ни один нормальный разработчик не будет ее сейчас использовать, она слишком неудобна по сравнению с текущей. И большинство библиотек требуют версию не ниже 1.12. Так что такого

Вот зачем нужна lts если толком ею нельзя пользоваться? Захотел поставить раст - проблемы, захотел ещё что-то - опять проблемы. Либо ставь в обход пакетного менеджера или используй комп только музыку смотреть и фильмы слушать...

NextGenenration ()

Привер со строками меня убил. Очевидно, что это ужасно: если человек делает срез строки, он хочет получить символы с соответствующими номерами, а вовсе не байты. В третьем Питоне и D всё сделано правильно: там элементами строки являются символы. Поэтому результат не зависит от кодировки. Здесь же всё сделано с помощью древних костылей.

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

Как раз всё правильно сделано. В Rust не могли сделать как в питоне, потому что это не скриптовый язык, который может позволить себе хранить по 4 байта на каждый юникодовый символ. В Rust строки всегда в UTF-8, и чтобы найти границы символов, нужно идти по строке циклом, для этого есть .chars()

Вот здесь хорошее объяснение от одного из разработчиков: https://www.reddit.com/r/rust/comments/5zrzkf/announcing_rust_116/df14g4g/

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

Раньше был посимвольный слайсинг, но потом убрали. Причина: так как строки юникодные, размер одного символа нефиксирован, следовательно индексация по строке происходит за O(n), где n — начальный байт символа.
Слишком неочевидный способ получить просадку производительности на ровном месте. Python и D на это насрать, в областях применения Rust это может быть критичным (особенно с индусскими кодерами).

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

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

Кстати, для строк из кириллицы разница уже не 4 раза, а 2. А уж если писать на китайском...

И Qt почему-то может себе такое позволить, хоть он сделан на отнюдь не скриптовом C++.

hobbit ★★★★★ ()
Последнее исправление: hobbit (всего исправлений: 3)