Open source
Programming
System Programming
Compilers
Rust
April 16

Выпуск Rust 1.34

From Sandbox

Привет, Хабр! Представляю вашему вниманию перевод статьи "The Rust Release Team "Announcing Rust 1.34.0".


Команда разработчиков Rust рада сообщить о выпуске новой версии Rust, 1.34.0. Rust — это язык программирования, который даёт возможность каждому создавать надёжное и эффективное программное обеспечение.


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


$ rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта.


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


Основное улучшение этого выпуска это поддержка альтернативных cargo-реестров. Релиз также включает поддержку ? в документационных тестах, некоторые улучшения в #[attribute(...)] и стабилизацию TryFrom. Читайте далее о ключевых вещах или можете посмотреть подробные примечания к выпуску для дополнительной информации.


Альтернативные cargo реестры


Ещё до версии 1.0 у Rust был публичный реестр, crates.io. Люди публиковали крейты при помощи cargo publish и легко подключали эти крейты в секции [dependencies] в Cargo.toml.


Однако не все хотят публиковать свои крейты на crates.io. Люди, поддерживающие проекты с закрытым исходным кодом, не могли использовать crates.io, и вместо этого им приходилось указывать git или path в зависимостях. Здесь нет ничего такого для небольших проектов, но если в вашей большой организации есть много крейтов с закрытым кодом, вы теряете преимущества поддержки версионирования, которое есть в crates.io.


Начиная с этого выпуска, Cargo может поддерживать альтернативные реестры. Эти реестры сосуществуют с crates.io, так что вы можете писать программы, которые зависят и от crates.io, и от вашего реестра. Однако крейты на crates.io не могут зависеть от внешнего реестра.


Для использования альтернативных реестров, вы должны добавить следующие строки в .cargo/config. Этот файл может быть в вашей домашней директории (~/.cargo/config) или быть в директории пакета.


[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }

Добавить зависимость из альтернативного реестра легко. Когда вы указываете зависимость в Cargo.toml, используйте ключ registry чтобы Cargo знал что вы хотите получать крейт из альтернативного реестра:


[dependencies]
other-crate = { version = "1.0", registry = "my-registry" }

Как автор крейта, если вы хотите публиковать ваш крейт в альтернативном реестре, первым делом вам надо сохранить аутентификационный токен в ~/.cargo/credentials при помощи команды cargo login:


cargo login --registry=my-registry

Далее вы можете использовать флаг --registry для указания реестра, в который будет публиковаться крейт:


cargo publish --registry=my-registry

О том, как вы можете запустить свой собственный реестр, вы можете найти в документации.


? в документационных тестах


В RFC 1937 было предложено добавить поддержку использования оператора ? в fn main(), #[test] функциях и документационных тестах, позволяя им вернуть Option<T> или Result<T, E> где вариант с ошибкой приводит к ненулевому коду завершения в случае fn main() или упавшему тесту в случае тестов.


Поддержка в fn main() и #[test] была реализована достаточно давно. Однако поддержка в документационных тестах была ограничена тестами, в которых явно присутствовал fn main().


В этом выпуске добавлена полная поддержка ? в документационных тестах. Теперь вы можете написать в ваших документационных тестах такое:


/// ```rust
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io:Error>(())
/// ```
fn my_func() {}

Внизу документационного теста вам всё равно надо указывать тип ошибки, который будет использован.


Поддержка произвольного потока токенов в пользовательских атрибутах


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


#[foo(bar)]
#[foo = "bar"]
#[foo = 0]
#[foo(bar = true)]
#[foo(bar, baz(quux, foo = "bar"))]

В отличии от процедурных макросов, эти вспомогательные атрибуты не могли принимать произвольный поток токенов в разделителе, из-за чего вы не могли написать #[range(0..10)] или #[bound(T: MyTrait)]. Крейты процедурных макросов вместо этого использовали строки для синтаксиса, подобного такому, например #[range("0..10")].


С этим выпуском, пользовательские атрибуты #[attr($tokens)] позволяют использовать произвольные токены в $tokens, приводя их в соответствии с макросами. Если вы автор крейта процедурного макроса, пожалуйста проверьте используются ли строки в синтаксисе ваших пользовательских атрибутах и можно ли их заменить на поток токенов.


TryFrom и TryInto


Трейты TryFrom и TryInto были стабилизированы для поддержки ошибок при преобразовании типов.


Например, from_be_bytes и связанные методы целочисленных типов получают массив, но данные часто читаются через слайсы. Ручное преобразование между слайсами и массивами утомительно. С новыми трейтами это возможно сделать в одну строку с .try_into().


let num = u32::from_be_bytes(slice.try_into()?);

Для преобразований, которые не могут завершиться с ошибкой, таких как u8 в u32, добавлен тип Infallible. За счёт этого TryFrom автоматически реализуется для всего, что реализует трейт From. В будущем, мы надеемся сделать Infallible псевдонимом для типа ! (never).


fn before_exec устарела в пользу unsafe fn pre_exec


В Unix-подобных системах функция CommandExt::before_exec позволяла вам запланировать выполнение замыкания до вызова exec.


Данное замыкание выполнялось в контексте дочернего процесса после форка. Это означает, что ресурсы, такие как файловые дескрипторы и области памяти, могли быть продублированы. Другими словами, вы могли получить копию значения не Copy типа в разных процессах, в то время как оригинал оставался бы в родительском. Это могло привести к неопределённому поведению и сломать библиотеки, предполагающие отсутствие дублирования.


Следовательно, функция before_exec должна быть помечена unsafe. В этом выпуске мы пометили fn before_exec устаревшей в пользу unsafe fn pre_exec. При вызове CommandExt::pre_exec вам необходимо убедиться, что замыкание не нарушает инварианты библиотеки создавая не валидные дубликаты. Если вы предоставляете библиотеку, которая находится в подобной before_exec ситуации, подумайте об устаревании и предоставьте альтернативу с unsafe.


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


В 1.34.0 расширен набор стабильных атомарных целочисленных знаковых и беззнаковых типов, начиная с 8 битных (AtomicU8) и заканчивая 64 битными.


Ранее были стабилизированы ненулевые беззнаковые целые числа, такие как NonZeroU8. Благодаря этому Option<NonZeroU8> имеет такой же размер, как и u8. В этом выпуске стабилизированы знаковые версии, например NonZeroI8.


Стабилизированы функции iter::from_fn и iter::successors. Первая позволяет создать итератор из FnMut() -> Option<T>. Чтобы итеративно получать элементы из вектора, вы теперь можете написать from_fn(|| vec.pop()). Тем временем вторая функция создаёт новый итератор, где каждый следующий элемент вычисляется на основе предыдущего.


Дополнительно, были стабилизированы следующие API:



Для подробной информации смотрите подробные примечания к выпуску.

+60
5.9k 23
Comments 14
Top of the day