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.

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

★★★★★

Проверено: Shaman007 ()
Последнее исправление: mersinvald (всего исправлений: 6)
Ответ на: комментарий от hobbit

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

Язык системного программирования - не может. Точнее, стандартная библиотека языка системного программирования не может.

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

Потому, что скриптовый и так медленный, хуже уже не будет.

Не знаю что в Python, но в Qt - UTF-16, и это тоже не всем нравится.

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

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

Если учесть, что unicode допускает до 6-и байт на символ, то всё намного сложнее.

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

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

В том что пользователь ЯП - программист, логика своеобразная есть.

Loki13 ★★★★★
()

byte index 4 is not

a char boundary; it is inside 'α' (bytes 3..5) of `abcαβγ`

Sweet. Внесите saahriktu!

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

Ради выигрыша в тех редких случиев, когда строки будут чисто ascii, библиотека сделана крайне не удобно. Теперь вместо пары скобок придётся целую функцию набирать. Такое впечатление что создатели rust любили нажимать на клавиши.

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

Ради выигрыша в тех редких случиев, когда строки будут чисто ascii, библиотека сделана крайне не удобно. Теперь вместо пары скобок придётся целую функцию набирать.

О чем ты? Я могу сказать как системный программист: строки приходится хранить, конкатенировать и выдавать на печать. Объясни, в чем крайнее неудобство.

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

И большинство библиотек требуют версию не ниже 1.12.

в репозиториях сейчас версия 1.7

Вот, это то о чем я говорю. Начать никогда не поздно кстати

Просто блин, надо либо версии реже штамповать, либо как-то ещё этот вопрос решать с дистрами. Но не так как сейчас

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

Просто блин, надо либо версии реже штамповать

Не надо. Чем чаще релизы, тем больше точечного фидбека от пользователей, и тем гибче процесс разработки.
Чесслово, в 2017 году не думал что это надо будет объяснять на айтишном форуме

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

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

Причины исторические, когда-то считалось, что 65 тысяч символов должно хватить всем. Во время разработки раста стало очевидно другое: utf16 строки с индексацией по 2 байта приводят к написанию некорректного кода. Если же работать с текстом правильно, то эти же алгоритмы подходят и для utf8, и тогда «зачем платить больше».

А вообще, не то что побайтовая, даже посимвольная работа с юникодом невозможна: для rtl письменностей в юникод добавлен bidi алгоритм, который не только арабщину и иврит разворачивает, но и меняет направление нейтральных символов, например скобки заменяет на обратные. Направление нейтральных символов зависит от соседства с направленными (в том числе и невидимыми) и от окружения специальными тегами форсирования направления, так что вырезание подстрок даже по символам может всё поломать.

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

Чем чаще релизы, тем больше точечного фидбека от пользователей, и тем гибче процесс разработки. Чесслово, в 2017 году не думал что это надо будет объяснять на айтишном форуме

Это что, очередная околоайтишная религия? Я уже со счета сбился, чесслово

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

Fire and motion - зло. Единственное его назначение - чтобы конкуренты не успевали клепать фичи в свои языки.

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

Просто блин, надо либо версии реже штамповать,

Зачем? Чтобы подстраиваться под ленивых мейтейнеров, которые даже версию вовремя обновить не могут?

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

Алсо, нахрена Agile при разработке ЯП?

Не уж то требования «заказчика» меняются каждую неделю?

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

Ознакомьтесь с понятием Agile и что в него входит.

Алсо, нахрена Agile при разработке ЯП?

Быстрый фидбек от пользователей, быстрая доставка багфиксов и фич пользователю.

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

Ради выигрыша в тех редких случиев, когда строки будут чисто ascii, библиотека сделана крайне не удобно. Теперь вместо пары скобок придётся целую функцию набирать. Такое впечатление что создатели rust любили нажимать на клавиши.

Нет, они просто следуют правильным принципам. UTF-8 — современный стандарт, и правильный способ работать с ним — именно такой, как в Rust'е.

http://utf8everywhere.org

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

Это путь в никуда!

Следствием подобных шагов бывает формирование визгливо-брехливого сообщества из нитакихкакфсе, кототрое является аттрактором для нитакихкакфсе со всего интернета.

Постоянный приток нитакихкакфсе дает постоянные фичреквесты, временами взаимоисключаюшие...

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

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

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

То есть, «демократичный» и «гибкий» процесс разработки закономерно приводит к НИНУЖНО на выходе.

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

Следствием подобных шагов бывает формирование визгливо-брехливого сообщества из нитакихкакфсе, кототрое является аттрактором для нитакихкакфсе со всего интернета.

Аттрактором не знающих, но ценное мнение имеющих анонимов на ЛОР? Вполне возможно.

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

Ну, ты бы хоть поинтересовался, как там фичи лепятся. RFC-proposal + обоснования и все такое. Или ты очередно ни чорта не знающий, но гордый «такойкакфсе» жабоскриптдиз-лефтпадисто-похапист?

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

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

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

Как насчет рассмотрения нескольких альтернатив?

Какая альтернатива выигрывает?

Случайно не та, за которую проголосовало большинство, которое на самом деле агрессивное меньшинство?

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

Всё гарантировано только для ascii.

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

срали на всех остальных

А что по твоему должно произойти (кроме ошибки), когда кто-то хочет поделить строку не границе символа?

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

Ради выигрыша в тех редких случиев, когда строки будут чисто ascii

Хранить по 4 байта на символ не выгодно даже для русских и китайских букв, не только для ascii. А если хранить по 2 байта на символ (UTF-16), то интерфейс придется делать такой же как для UTF-8 (с вызовом функций) плюс оверхед по памяти для ascii, так что в двойне не выгодно.

Ну и конечно не выгодно конвертировать все строки туда сюда. Автор ripgrep недавно добавил поддержку UTF-16 для виндузятников, и так получается что на конвертацию кодировки уходит больше времени чем на сам поиск подстроки.

что произойдёт если попытаться взять срез строки

Срез строки берется в байтах. Если попытаться поделить строку на границе символа то произойдет panic. Но на деле всегда легко получить смещение в байтах для подстроки или нужного символа. Еще можно самому проверить границу если очень нужно.

вместо пары скобок придётся целую функцию набирать.

А в ассемблере все эти функции полностью инлайнятся, так что код получается очень эффективный.

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

В нормальных языках срезать «посреди символа» и невозможно, потому что работа будет идти не с тупо байтами, а с символами aka codepoints. Но поскольку разработчики раста строят конкурента динозавру C, имеем что имеем.

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

Работа с символами в utf-8 имеет вычислительную сложность O(n) а не O(1), так что накладно по процессору, а в UTF-32 накладно и по памяти и на конвертацию тратить ресурсы.

конкурента динозавру C, имеем что имеем.

Если принимать решения которые не позволяют получить производительность на уровне C, то его никогда не победить.

нормальных языках срезать «посреди символа» невозможно

Покажи мне эти «нормальные» языки, из всех что я видел только python3 не портит символы, а всякие там Java, JavaScript, Go, и прочие, все лажают на сурогатах.

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

Где и зачем вы собрались побеждать Со, наполеоны хреновы?

Ниша Си сокращается с каждым годом!

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

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

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

Каждый язык ищет свою золотую середину между стоимостью хранения строк в памяти\на диске и скоростью посимвольной итерации. Для скриптового языка стоимость храния неважна (на скриптовых языках не пишут базы данных), ему важна скорость посимвольной итерации. А для языка системного программирования, на котором как раз пишут базы данных, важна стоимость хранения, и менее важна скорость обработки.

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

По поводу примера

&"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αβγ`
Часть после ; — новая.

Источник: https://www.ibm.com/developerworks/ru/library/x-utf8/
В UTF-8 вы всегда знаете, где находитесь – т. е. по отдельному байту вы сразу можете определить, является ли он однобайтным символом, первым байтом двухбайтного символа, вторым байтом двухбайтного символа либо вторым, третьим или четвертым байтом трех- или четырехбайтного символа.

Т.е. получается, в примере они взяли 4-й байт строки, по нему самому определили, что это 2-й байт 3х-байтного символа, потом взяли от него встроке левый и правый байты, и получили целый 3х-байтный символ.

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

Все правильно я говорю. Питон уверенно идет к успеху. Уже есть несколько реализаций под микроконтроллеры, про numpy для научных и инженерных расчетов только ленивый не знает.

Для Си остается легаси и роль целевой платформы при генерации кода из высокоуровневых языков (привет matlab, scilab, matiec, nim, lisp, Haskell и пр.).

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

Это что, очередная околоайтишная религия?

«Очередная»? Опенсорс испокон веков на «release early, release often» стоит.

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

В нормальных языках срезать «посреди символа» и невозможно, потому что работа будет идти не с тупо байтами, а с символами aka codepoints.

От работы с codepoints профита 0. Т.к. остаётся возможность отрезать диакритические знаки или попасть внутрь состоящего из нескольких codepoint-ов иероглифа.

В нормальных языках работа идёт с grapheme clusters. Но, очевидно, что такая стратегия неприемлема для языка системного программирования.

anonymous
()

не могу поставить rust ((

curl -sSf https://static.rust-lang.org/rustup.sh | sh
sh: 1: Syntax error: "(" unexpected

придется собирать ручками, пичалька...

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

Я даже не стал пробовать так ставить. Скачал сразу готовый бинарник

# wget https://static.rust-lang.org/rustup/dist/x86_64-unknown-freebsd/rustup-init
И дальше им уже ставил. Потом добавил в крон:
# crontab -l
05 01 * * * /root/rustup.sh
# cat /root/rustup.sh
#!/usr/local/bin/bash
/root/.cargo/bin/rustup --verbose update &> /var/log/rustup.log
И вполне счастлив, т.к. система автоматически обновляет стабильную и ночную сборку. Лог получаю типа такого:
# cat /var/log/rustup.log
verbose: read metadata version: '12'
verbose: updating existing install for 'stable-x86_64-unknown-freebsd'
verbose: toolchain directory: '/root/.rustup/toolchains/stable-x86_64-unknown-freebsd'
info: syncing channel updates for 'stable-x86_64-unknown-freebsd'
verbose: creating temp file: /root/.rustup/tmp/baurhsv40hs4zmhm_file
verbose: downloading file from: 'https://static.rust-lang.org/dist/channel-rust-stable.toml.sha256'
verbose: downloading with curl
verbose: deleted temp file: /root/.rustup/tmp/baurhsv40hs4zmhm_file
verbose: toolchain is already up to date
verbose: updating existing install for 'nightly-x86_64-unknown-freebsd'
verbose: toolchain directory: '/root/.rustup/toolchains/nightly-x86_64-unknown-freebsd'
info: syncing channel updates for 'nightly-x86_64-unknown-freebsd'
verbose: deleted temp file: /root/.rustup/tmp/y_8suicxxu1uvhm6_file
/root/.rustup/tmp/dg4va6o0rt3z05x6_file
verbose: toolchain 'nightly-x86_64-unknown-freebsd' installed
info: checking for self-updates

  stable-x86_64-unknown-freebsd unchanged - rustc 1.16.0 (30cf806ef 2017-03-10)
   nightly-x86_64-unknown-freebsd updated - rustc 1.17.0-nightly (a559452b0 2017-03-17)


microbash
()

Пойду еще один хеловорд напишу, и закину до следующего релиза.

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

Вы не поверите, но таки да.

Agile — the most special word used by morons. Rather than releasing software once a year or so, companies now have a rapid release cycle, and they supposedly adhere to this agile model, to distinguish themselves from the would-be legacy dinosaurs. This leads to a quick increment in versions numbers and much reduced quality. But that's the thing - having lots of versions creates an impression of ACTIVITY.
Of course, the agile model does not really work for 90% of companies, because they think it's about speed. They forget the fine details like assigning their best people to work on these products, the need for self-discipline, a high level of autonomy, and of course, being able to create software products with reasonable milestones. But as long as they are agile, they are untouchable. Because they are agile. Agile, you hear!

anonymous
()

В этот релиз вошли 1364 патча от 137 разработчиков.

Всегда встаёт закономерный вопрос: а что же компилятор представлял из себя ДО этих патчей?! Громадную кучу костылей и багов?
Патч (в моём понимании) - это правка ошибок, мелкие исправления существующего кода.
Возможно, корректнее новость преподносить как «исправлено 100 ошибок, введено 200 фич»?

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

Патч (в моём понимании) - это правка ошибок, мелкие исправления существующего кода.

Именно, что в Вашем понимании :)
Патч — автоматизированно наложенное изменение на кодовую базу (или файл). Коммиты в гите — цепочка последовательных патчей.
А исправления и фичи описаны ниже

mersinvald ★★★★★
() автор топика
Последнее исправление: mersinvald (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.