Представлен релиз 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`?
Стабилизация библиотек
- VecDeque::truncate
- VecDeque::resize
- String::insert_str
- Duration::checked_add
- Duration::checked_sub
- Duration::checked_div
- Duration::checked_mul
- str::replacen
- str::repeat
- SocketAddr::is_ipv4
- SocketAddr::is_ipv6
- IpAddr::is_ipv4
- IpAddr::is_ipv6
- Vec::dedup_by
- Vec::dedup_by_key
- Result::unwrap_or_default
- <*const T>::wrapping_offset
- <*mut T>::wrapping_offset
- CommandExt::creation_flags
- File::set_permissions
- String::split_off
Также стабилизированы некоторые мелкие улучшения:
-
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.
>>> Подробности