Команда Rust рада сообщить о выпуске новой версии, 1.41.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если вы установили предыдущую версию Rust средствами rustup
, то для обновления до версии 1.41.0 вам достаточно выполнить следующую команду:
rustup update stable
Если у вас ещё не установлен rustup
, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.
Что вошло в стабильную версию 1.41.0
Основными новшествами Rust 1.41.0 являются ослабление ограничений на реализацию типажей, улучшения cargo install
, новый формат файла Cargo.lock
более дружелюбный для работы с git
, и новые гарантии для Box<T>
, связанные с FFI. Смотрите подробности выпуска для дополнительной информации.
Ослабление ограничений при реализации типажей
Для предотвращения поломок в экосистеме, когда зависимость добавляет новые реализации типажа, Rust использует правило сироты (orphan rule). Суть в том, что реализация типажа допустима только если типаж или тип, который его реализует, является локальным, т.е. определённым в текущем крейте. Однако это достаточно сложно, когда используются обобщения.
До версии 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, но они часто были громоздкими или даже невозможными в некоторых случаях.
Хотя From
и Vec
всё ещё остаются чужими, типаж (в данном случае From
) параметризован локальным типом. Поэтому, Rust 1.41.0 позволяет этот impl
.
Для более подробной информации читайте отчёт о стабилизации и предложение RFC.
cargo install
обновляет пакеты если они устарели
При помощи cargo install
вы можете установить в систему исполняемый крейт. Эта команда часто используется для установки популярных CLI-инструментов, созданных комьюнити и написанных на Rust.
Начиная с Rust 1.41.0, cargo install
также может обновлять установленные крейты, если с момента установки появился новый релиз. До этого выпуска единственным возможным вариантом было использование флага --force
, который позволял переустановить исполняемый крейт даже если он не нуждался в обновлении.
Менее конфликтный формат Cargo.lock
Для обеспечения консистентных сборок, Cargo использует файл с названием Cargo.lock
, который содержит версии зависимостей и контрольные суммы. К сожалению, формат организации данных в нём мог привести к ненужным конфликтам слияния при изменении зависимостей в отдельных ветках.
Rust 1.41.0 представляет новый формат для этого файла, разработанный специально для уменьшения конфликтов. Новый формат будет использоваться для всех новых lock
-файлов, в то время как существующие файлы будут использовать предыдущий формат. Узнать больше о вариантах, которые привели к новому формату, вы можете в PR, в котором его добавили.
Больше гарантий при использовании 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>
.
Изменения в библиотеке
В версии Rust 1.41.0, мы сделали следующие изменения в стандартной библиотеке:
Методы
Result::map_or
иResult::map_or_else
теперь стабилизированы.
Подобно
Option::map_or
иOption::map_or_else
, эти методы являются упрощением кода.map(|val| process(val)).unwrap_or(default)
.
NonZero*
числа теперь реализуютFrom<NonZero*>
если их числовая длина меньше. Например,NonZeroU16
теперь реализуетFrom<NonZeroU8>
.
Стабилизированы методы
weak_count
иstrong_count
структурыWeak
.
std::rc::Weak::weak_count
std::rc::Weak::strong_count
std::sync::Weak::weak_count
std::sync::Weak::strong_count
Эти методы возвращают количество слабых (
rc::Weak<T>
иsync::Weak<T>
) или сильных (Rc<T>
иArc<T>
) указателей на область памяти.
MaybeUninit<T>
теперь реализуетfmt::Debug
.
Сокращение поддержки 32-битной целевой платформы Apple
Rust 1.41.0 будет последним выпуском с текущим уровнем поддержки 32-битных платформ Apple, включая i686-apple-darwin
. Начиная с Rust 1.42.0 эти платформы будут понижены до самого низкого уровня поддержки.
Узнать об этом больше вы можете в соответствующей записи в блоге.
Другие изменения
Синтаксис, пакетный менеджер Cargo и анализатор Clippy также претерпели некоторые изменения. Мы также приступили к внедрению оптимизаций MIR, которые должны ускорить компиляцию: вы можете узнать о них в блоге "Inside Rust".
Участники 1.41.0
Множество людей собрались вместе, чтобы создать Rust 1.41.0. Мы не смогли бы сделать это без всех вас, спасибо!
От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов.
Данную статью совместными усилиями перевели andreevlex, blandger, funkill, P0lunin и nlinker.
ozkriff
В официальном посте почему-то про это не написали, но 1.41 наконец-то стабилизировал очень ожидаемую многими разработчиками чего-то интерактивного штуку: "profile overrides". TLDR: позволяет выборочно использовать разные профили сборки для основного кода и зависимостей.
Т.е., например, теперь можно собирать отладочную сборку с оптимизированными зависимостями:
Это очень в тему, например, при разработке игр, потому что ты получаешь вменяемое количество кадров в секунду на оптимизированном движке и мат библиотеках, но при этом непосредственно твой код игры быстро собирается и нормально отлаживается.
Еще оно может быть полезно, например, для выключения оптимизаций для build-time зависимостей (типа syn), что для некоторых проектов может чуть ли не в два раза уменьшить время полной release сборки.
grossws
О да, крайне полезная фича когда нужно крутить небольшой кусок кода сути в dev profile, а остальное эффективно в release.
Также крайне приятно, что в этом релизе таки заехали ослабленные orphan rules, раньше это было несколько болезненно.