Анонс Rust 1.16

Разработка /
Разработка: Анонс Rust 1.16
Команда Rust рада представить новую версию Rust 1.16.0. Rust это язык системного программирования, нацеленный на безопасность, скорость, и параллелизм.

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

$ rustup update stable 

Если у вас его нет, вы можете использовать rustup с соответствующей страницы нашего сайта, и ознакомиться с подробными заметками к выпуску для 1.16.0 на GitHub.

Что вошло в 1.16.0 stable


Самое большое дополнение в Rust 1.16 это cargo check. Это новая подкоманда должна ускорить процесс разработки во многих случаях.

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

  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
<snip>

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

Оказывается, этот второй шаг занимает много времени. И большую часть времени это не обязательно. То есть, когда вы работаете над некоторым кодом Rust, многие разработчики войдут в рабочий процесс следующим образом:
1. Написать некоторый код.
2. Запустить cargo build чтобы убедиться что код скомпилируется.
3. Повторить 1-2 если необходимо.
4. Запустить cargo test чтобы убедиться, что тесты пройдены
5. GOTO 1.

На втором этапе вы никогда не запускаете свой код. Вы ищете обратную связь от компилятора, а не запускаете двоичный код. cargo check предназначен именно для этого: он выполняет все проверки компилятора, но не создает окончательный двоичный код.
Так сколько времени вы экономите в итоге? Как и большинство вопросов, связанных с производительностью, ответ «по-разному». Вот некоторые очень ненаучные сравнительные тесты:

initial build initial check speedup secondary build secondary check speedup
thanks 134.75s 50.88s 2.648 15.97s 2.9s 5.506
cargo 236.78s 148.52s 1.594 64.34s 9.29s 6.925
diesel 15.27s 12.81s 0.015 13.54s 12.3s 1.100

'Initial' категории — это первая сборка после клонирования проекта. 'secondary' включали добавление одной пустой строки в начало src\lib.rs и повторное выполнение команды. Вот почему initial более существенные; они также включают это для всех зависимостей, так же как и сам контейнер(crate). Как вы можете видеть, большие проекты со многими зависимостями получат большое улучшение, но меньшие увидят гораздо более скромную выгоду.

Мы все еще работаем над улучшением времени компиляции, хотя в настоящее время нам нечего особо выделять.

Другие улучшения
В поддержку cargo check, rustc научился генерировать новый тип файла: .rmeta. Этот файл будет содержать только метаданные об определенном контейнере(crate). cargo check требует этого для ваших зависимостей, чтобы позволить компилятору проверять типы и т.п. Это также полезно для Rust Language Server и, возможно, для будущих инструментов.

Еще одно большое изменение — это удаление продолжительной диагностики: "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 })
    }
}

Здесь Rust не уверен что делать с временем жизни; как написано, код не гарантирует, что s будет жить также долго как Name, что требуется для того, чтобы Name был действительным. Попробуем скомпилировать этот код с Rust 1.15.1:

> 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

Компилятор объясняет проблему и дает полезное предложение. Поэтому давайте попробуем: измените код, добавив 'a, и скомпилируйте еще раз:

> 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
   |
<snip>
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
<snip>
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name<'a>, ()>
  --> .\foo.rs:10:5

… это то, что у нас уже есть, компилятор!

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

Кстати: вышеупомянутая реализация невозможна; Name должно использовать String, а не &str.

В других диагностических изменениях, предыдущие версии 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`?

Однако это может произойти только при определенных обстоятельствах: иногда в локальных переменных и для полей в структурах. Это происходит почти повсеместно. В сочетании с некоторыми другими соответствующими улучшениями это приводит к значительному улучшению этих видов диагностики.

См. Подробные примечания к выпуску.

Стабилизация библиотек
21 API был стабилизирован в этом выпуске:

Кроме того, был осуществлен ряд небольших улучшений существующих функций. Например, 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 для создания и документирования каждого контейнера(crate) в рабочем окружении с помощью одной команды.

Cargo теперь имеет --version --verbose флаг, повторяя rustc.

Crates.io теперь может демонстрировать значки TravisCI или AppVeyor на странице вашего контейнера(crate).

В дополнение, оба Cargo и crates.io получили категории. В отличие от ключевых слов, которые являются свободной формой, категории курируются. Кроме того, ключевые слова используются для поиска, а категории — нет. Другими словами, категории предназначены для удобства просмотра, а ключевые слова предназначены для поиска.

Здесь вы можете просматривать контейнеры(crate) по категориям.
См. Подробные примечания к выпуску.

Разработчики 1.16.0


В последнем выпуске мы представили thanks.rust-lang.org. Мы выполняем некоторые закулисные работы по рефакторингу, чтобы разрешить больше проектов, чем только сам Rust; Мы надеемся представить это в следующем выпуске.

В Rust 1.16 участвовали 137 человек. Большое спасибо!

Оригинал: https://blog.rust-lang.org/2017/03/16/Rust-1.16.html
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.