Выпуск Rust 1.34.0
Команда разработчиков Rust рада сообщить о выпуске новой версии Rust, 1.34.0. Rust — это язык программирования, который даёт возможность каждому создавать надёжное и эффективное программное обеспечение.
Если у вас установлена предыдущая версия Rust с помощью rustup, то для обновления Rust до версии 1.34.0 вам достаточно выполнить:
1 | $ 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
) или быть в директории пакета.
1 2 | [registries] my-registry = { index = "https://my-intranet:8080/git/index" } |
Добавить зависимость из альтернативного реестра легко.
Когда вы указываете зависимость в Cargo.toml
, используйте ключ
registry
чтобы Cargo знал что вы хотите получать крейт из альтернативного реестра:
1 2 | [dependencies] other-crate = { version = "1.0", registry = "my-registry" } |
Как автор крейта, если вы хотите публиковать ваш крейт в
альтернативном реестре, первым делом вам надо сохранить
аутентификационный токен в ~/.cargo/credentials
при помощи команды
cargo login
:
1 | cargo login --registry=my-registry
|
Далее вы можете использовать флаг --registry
для указания реестра,
в который будет публиковаться крейт:
1 | cargo publish --registry=my-registry
|
О том, как вы можете запустить свой собственный реестр, вы можете найти в документации.
?
в документационных тестах
В RFC 1937 было предложено добавить поддержку использования оператора
?
в fn main()
, #[test]
функциях и документационных тестах, позволяя
им вернуть Option<T>
или Result<T, E>
где вариант с ошибкой приводит
к ненулевому коду завершения в случае fn main()
или упавшему тесту в случае тестов.
Поддержка в fn main()
и #[test]
была реализована достаточно давно.
Однако поддержка в документационных тестах была ограничена тестами,
в которых явно присутствовал fn main()
.
В этом выпуске добавлена полная поддержка ?
в документационных тестах.
Теперь вы можете написать в ваших документационных тестах такое:
1 2 3 4 5 6 7 | /// ```rust /// use std::io; /// let mut input = String::new(); /// io::stdin().read_line(&mut input)?; /// # Ok::<(), io:Error>(()) /// ``` fn my_func() {} |
Внизу документационного теста вам всё равно надо указывать тип ошибки, который будет использован.
Поддержка произвольного потока токенов в пользовательских атрибутах
Процедурные макросы в Rust могут определять пользовательские атрибуты, которые они используют. До текущего момента эти атрибуты были ограничены деревьями путей и литералами в соответствии со следующим синтаксисом:
1 2 3 4 5 | #[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()
.
1 | 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:
- Any: type_id
- Error: type_id
- slice: sort_by_cached_key
- str: escape_debug
- str: escape_default
- str: escape_unicode
- str: split_ascii_whitespace
- Instant: checked_add
- Instant: checked_sub
- SystemTime: checked_add
- SystemTime: checked_sub
Для подробной информации смотрите подробные примечания к выпуску