- PVSM.RU - https://www.pvsm.ru -

Выпуск Rust 1.41.0: новые гарантии для Box<T> в FFI, улучшения в cargo install, ослабление ограничений для типажей

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

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

rustup update stable

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

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

Основными новшествами Rust 1.41.0 являются ослабление ограничений на реализацию типажей, улучшения cargo install, новый формат файла Cargo.lock более дружелюбный для работы с git, и новые гарантии для Box<T>, связанные с FFI. Смотрите подробности выпуска [2] для дополнительной информации.

Ослабление ограничений при реализации типажей

Для предотвращения поломок в экосистеме, когда зависимость добавляет новые реализации типажа, Rust использует правило сироты (orphan rule) [3]. Суть в том, что реализация типажа допустима только если типаж или тип, который его реализует, является локальным, т.е. определённым в текущем крейте. Однако это достаточно сложно [4], когда используются обобщения.

До версии Rust 1.41.0 это правило было слишком строгим, мешая композиции. Например, предположим что ваш пакет реализует структуру BetterVec<T>, и вы хотите иметь возможность конвертации его в Vec<T> из стандартной библиотеки. Вы бы написали следующий код:

impl<T> From<BetterVec<T>> for Vec<T> {
    // ...
}

… который является примером паттерна:

impl<T> ForeignTrait<LocalType> for ForeignType<T> {
    // ...
}

В версии Rust 1.40.0 этот impl был запрещён правилом сироты, так как From и Vec определены в стандартной библиотеке, которая является чужим крейтом по отношению к текущему крейту. Были способы обойти это ограничение, такие как шаблон newtype [5], но они часто были громоздкими или даже невозможными в некоторых случаях.

Хотя From и Vec всё ещё остаются чужими, типаж (в данном случае From) параметризован локальным типом. Поэтому, Rust 1.41.0 позволяет этот impl.

Для более подробной информации читайте отчёт о стабилизации [6] и предложение RFC [7].

cargo install обновляет пакеты если они устарели

При помощи cargo install вы можете установить в систему исполняемый крейт. Эта команда часто используется для установки популярных CLI-инструментов, созданных комьюнити и написанных на Rust.

Начиная с Rust 1.41.0, cargo install также может обновлять установленные крейты, если с момента установки появился новый релиз. До этого выпуска единственным возможным вариантом было использование флага --force, который позволял переустановить исполняемый крейт даже если он не нуждался в обновлении.

Менее конфликтный формат Cargo.lock

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

Rust 1.41.0 представляет новый формат для этого файла, разработанный специально для уменьшения конфликтов. Новый формат будет использоваться для всех новых lock-файлов, в то время как существующие файлы будут использовать предыдущий формат. Узнать больше о вариантах, которые привели к новому формату, вы можете в PR, в котором его добавили [8].

Больше гарантий при использовании Box<T> в FFI

Начиная с Rust 1.41.0, мы заявляем, что Box<T>, когда T: Sized, теперь совместим по ABI с типами указателей в C (T*). Таким образом, если вы определяете функцию extern "C" в Rust и вызываете её из C, ваша функция в Rust теперь может использовать Box<T> для какого-то T, и использовать T* в соответствующей функции на C. В качестве примера, на стороне C вы можете иметь:

// C header */

// Возвращаем владение в вызывающий код
struct Foo* foo_new(void);

// Принимает владение из вызывающего кода; no-op если передан NULL.
void foo_delete(struct Foo*);

… а на стороне Rust у вас будет:

#[repr(C)]
pub struct Foo;

#[no_mangle]
pub extern "C" fn foo_new() -> Box<Foo> {
    Box::new(Foo)
}

// Возможность принимать NULL реализуется с помощью `Option<_>`.
#[no_mangle]
pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}

Заметим однако, что не смотря на то, что Box<T> и T* имеют одинаковое представление и ABI, Box<T> обязательно должен быть не-null, выровнен и быть готовым для деаллокации глобальным аллокатором. Чтобы обеспечить эти требования, самое лучшее — это использовать такие Box'ы, которые порождаются глобальным аллокатором.

Важно: По крайней мере в настоящее время вы должны избегать использования типов Box<T> для функций, которые определены в C, но вызываются из Rust. В этих случаях вы должны отразить типы как можно ближе к определению в C. Использование типов наподобие Box<T>, когда определение в C использует просто T* может привести к неопределённому поведению.

Чтобы узнать больше, обратитесь к документации Box<T> [9].

Изменения в библиотеке

В версии Rust 1.41.0, мы сделали следующие изменения в стандартной библиотеке:

Сокращение поддержки 32-битной целевой платформы Apple

Rust 1.41.0 будет последним выпуском с текущим уровнем поддержки 32-битных платформ Apple, включая i686-apple-darwin. Начиная с Rust 1.42.0 эти платформы будут понижены до самого низкого уровня поддержки.

Узнать об этом больше вы можете в соответствующей записи в блоге [20].

Другие изменения

Синтаксис [2], пакетный менеджер Cargo [21] и анализатор Clippy [22] также претерпели некоторые изменения. Мы также приступили к внедрению оптимизаций MIR, которые должны ускорить компиляцию: вы можете узнать о них в блоге "Inside Rust" [23].

Участники 1.41.0

Множество людей собрались вместе, чтобы создать Rust 1.41.0. Мы не смогли бы сделать это без всех вас, спасибо [24]!

От переводчиков

С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате [25] или же в аналогичном чате для новичковых вопросов [26].

Данную статью совместными усилиями перевели andreevlex [27], blandger [28], funkill [29], P0lunin [30] и nlinker [31].

Автор: RustLangRu

Источник [32]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/345255

Ссылки в тексте:

[1] установить его: https://www.rust-lang.org/install.html

[2] подробные примечания к выпуску: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1410-2020-01-30

[3] правило сироты (orphan rule): https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type

[4] Однако это достаточно сложно: https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence

[5] шаблон newtype: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types

[6] отчёт о стабилизации: https://github.com/rust-lang/rust/issues/63599

[7] предложение RFC: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html

[8] в PR, в котором его добавили: https://github.com/rust-lang/cargo/pull/7070

[9] обратитесь к документации Box<T>: https://doc.rust-lang.org/std/boxed/index.html

[10] Result::map_or: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or

[11] Result::map_or_else: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else

[12] Option::map_or: https://doc.rust-lang.org/std/option/enum.Option.html#method.map_or

[13] Option::map_or_else: https://doc.rust-lang.org/std/option/enum.Option.html#method.map_or_else

[14] NonZero* числа теперь реализуют From<NonZero*>: https://github.com/rust-lang/rust/pull/66277

[15] std::rc::Weak::weak_count: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.weak_count

[16] std::rc::Weak::strong_count: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.strong_count

[17] std::sync::Weak::weak_count: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.weak_count

[18] std::sync::Weak::strong_count: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.strong_count

[19] MaybeUninit<T> теперь реализует fmt::Debug.: https://github.com/rust-lang/rust/pull/65013

[20] в соответствующей записи в блоге: https://blog.rust-lang.org/2020/01/03/reducing-support-for-32-bit-apple-targets.html

[21] пакетный менеджер Cargo: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-141-2020-01-30

[22] анализатор Clippy: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-141

[23] "Inside Rust": https://blog.rust-lang.org/inside-rust/2019/12/02/const-prop-on-by-default.html

[24] спасибо: https://thanks.rust-lang.org/rust/1.41.0/

[25] русскоязычном Телеграм-чате: https://t.me/rustlang_ru

[26] чате для новичковых вопросов: https://t.me/rust_beginners_ru

[27] andreevlex: https://habr.com/ru/users/andreevlex/

[28] blandger: https://habr.com/ru/users/blandger/

[29] funkill: https://habr.com/ru/users/funkill/

[30] P0lunin: https://habr.com/ru/users/p0lunin/

[31] nlinker: https://habr.com/ru/users/nlinker/

[32] Источник: https://habr.com/ru/post/486268/?utm_source=habrahabr&utm_medium=rss&utm_campaign=486268