12 Октября 2017 • оригинал: The Rust Core Team • перевод: ozkriff • новости • поддержите на Patreon

Команда Rust рада представить выпуск Rust 1.21.0. Rust — это системный язык программирования, нацеленный на скорость, безопасность и параллельное выполнение кода.

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

1 $ rustup update stable

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

Что вошло в стабильную версию 1.21.0

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

Первое изменение касается литералов. Рассмотрим код:

1 let x = & 5 ;

В Rust он аналогичен следующему:

1 2 let _x = 5 ; let x = & _x ;

То есть 5 будет положено в стек или возможно в регистры, а x будет ссылкой на него.

Однако, учитывая, что речь идёт о целочисленном литерале, нет причин делать значение таким локальным. Представьте, что у нас есть функция, принимающая 'static аргумент вроде std::thread::spawn . Тогда вы бы могли использовать x так:

1 2 3 4 5 6 7 8 9 use std :: thread ; fn main () { let x = & 5 ; thread :: spawn ( move || { println! ( "{}" , x ); }); }

Этот код не соберётся в прошлых версиях Rust’а:

1 2 3 4 5 6 7 8 9 10 error[E0597]: borrowed value does not live long enough --> src/main.rs:4:14 | 4 | let x = &5; | ^ does not live long enough ... 10 | } | - temporary value only lives until here | = note: borrowed value must be valid for the static lifetime...

Из-за локальности 5 , ссылка на него тоже живёт слишком мало, чтобы удовлетворить требованиям spawn .

Но если вы соберёте это с Rust 1.21, оно заработает. Почему? Если что-то, на что создана ссылка, можно положить в static , мы могли бы «обессахарить» let x = &5; в нечто вроде:

1 2 3 static FIVE : i32 = 5 ; let x = & FIVE ;

И раз FIVE является static , то x является &'static i32 . Так Rust теперь и будет работать в подобных случаях. Подробности смотрите в RFC 1414, который был принят в январе 2017, но начинался ещё в декабре 2015!

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

RLS теперь может быть установлен через rustup вызовом rustup component add rls-preview . Много полезных инструментов, таких как RLS, Clippy и rustfmt , все ещё требуют ночной Rust, но это первый шаг к их работе на стабильном канале. Ожидайте дальнейших улучшений в будущем, а пока взгляните на предварительную версию

Теперь об улучшениях документации. Первое: если вы посмотрите на документацию модуля std::os , содержащего функционал работы с операционными системами, вы увидите не только Linux — платформу, на которой документация была собрана. Нас долго расстраивало, что официальная документация была только для Linux. Это первый шаг к исправлению ситуации, хотя пока что это доступно только для стандартной библиотеки, а не для любого пакета (crate). Мы надеемся исправить это в будущем.

Далее, документация Cargo переезжает! Исторически документация Cargo была размещена на doc.crates.io, что не следовало модели выпусков (release train model), хотя сам Cargo следовал. Это приводило к ситуациям, когда какой-то функционал скоро должен был «влиться» в ночной Cargo, документация обновлялась, и в течение следующих 12 недель пользователи думали, что все работает, хотя это ещё не было правдой. https://doc.rust-lang.org/cargo будет новым домом для документации Cargo, хотя сейчас этот адрес просто перенаправляет на doc.crates.io. Будущие выпуски переместят настоящую документацию Cargo, и тогда уже doc.crates.io будет перенаправлять на doc.rust-lang.org/cargo. Документация Cargo уже давно нуждается в обновлении, так что ожидайте ещё новостей о ней в скором будущем!

Наконец, до этого выпуска у rustdoc не было документации. Теперь это исправлено: добавлена новая книга « rustdoc Book», доступная по адресу https://doc.rust-lang.org/rustdoc. Сейчас эта документация очень примитивна, но со временем она улучшится.

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

Стабилизации в стандартной библиотеке

В этом выпуске не так много стабилизаций, но есть кое-что, очень упрощающее жизнь: из-за отсутствия обобщения относительно целых чисел (type-level integers), массивы поддерживали типажи только до размера 32. Теперь это исправлено для типажа Clone . Кстати, это же вызывало много ICE (внутренних ошибок компилятора), когда тип реализовывал только Copy , но не Clone . Для других типажей недавно был принят RFC об обобщении относительно целых чисел, который должен исправить ситуацию. Это изменение ещё не реализовано, но подготовительные работы уже ведутся.

Затем был стабилизирован Iterator::for_each , дующий возможность поглощать итератор ради побочных эффектов без for цикла:

1 2 3 4 5 6 7 // старый способ for i in 0 .. 10 { println! ( "{}" , i ); } // новый способ ( 0 .. 10 ) .for_each (| i | println! ( "{}" , i ));

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

1 2 3 4 5 6 7 8 9 10 // старый способ for i in ( 0 .. 100 ) .map (| x | x + 1 ) .filter (| x | x % 2 == 0 ) { println! ( "{}" , i ); } // новый способ ( 0 .. 100 ) .map (| x | x + 1 ) .filter (| x | x % 2 == 0 ) .for_each (| i | println! ( "{}" , i ));

Rc<T> и Arc<T> теперь реализуют From<&[T]> where T: Clone , From<str> , From<String> , From<Box<T>> where T: ?Sized , и From<Vec<T>> .

Стабилизированы функции max и min типажа Ord .

Стабилизирована встроенная функция (intrinsic) needs_drop .

Наконец, был стабилизирован std::mem::discriminant , позволяющий вам узнать активный вариант перечисления без использования match оператора.

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

Функционал Cargo

Помимо вышеупомянутых изменений документации Cargo в этом выпуске получает большое обновление: [patch] . Разработанная в RFC 1969, секция [patch] вашего Cargo.toml может быть использована, когда вы хотите заменить части вашего графа зависимостей. Это можно было сделать и раньше, посредством [replace] . Если коротко, то [patch] это новый и более удобный [replace] . И хотя у нас нет планов убирать или объявлять устаревшим [replace] , вам скорее всего стоит использовать именно [patch] .

Как же работает [patch] ? Допустим, у нас есть такой Cargo.toml :

1 2 [dependencies] foo = "1.2.3"

Так же наш пакет (crate) foo зависит от пакета bar , и мы нашли ошибку в bar . Чтобы проверить это, мы скачиваем исходный код bar и обновляем наш Cargo.toml :

1 2 3 4 5 [dependencies] foo = "1.2.3" [patch.crates-io] bar = { path = '/path/to/bar' }

Теперь при выполнении cargo build будет использована наша локальная версия bar , а не версия из crates.io , от которой на самом деле зависит foo .

Подробности смотрите в документации.

Также:

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

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

Множество людей участвовало в разработке Rust 1.19. Мы не смогли бы этого добиться без участия каждого из вас. Спасибо!