Rust 1.96.0 — новый релиз укрепляет стандартную библиотеку, WebAssembly и безопасность Cargo

Команда Rust выпустила Rust 1.96.0 — стабильное обновление языка и инструментов, опубликованное 28 мая 2026 года. Главные изменения касаются новых типов диапазонов в стандартной библиотеке, макросов для проверки шаблонов, более строгой линковки WebAssembly и исправлений безопасности в Cargo.

Rust 1.96.0 — новый релиз укрепляет стандартную библиотеку
Rust 1.96.0 — новый релиз укрепляет стандартную библиотеку

Rust 1.96.0 стал стабильной версией для обновления через rustup

Rust 1.96.0 вышел как очередной стабильный релиз языка программирования Rust. Обновление уже доступно через стандартный инструмент управления версиями rustup:

rustup update stable

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

Официальный анонс опубликован в блоге Rust 28 мая 2026 года. В нём команда Rust отдельно подчёркивает несколько изменений, которые важны не только для авторов библиотек, но и для тех, кто собирает проекты под WebAssembly или использует приватные registry для зависимостей.

Новые Range-типы делают диапазоны удобнее для библиотек

Одно из центральных изменений Rust 1.96.0 — стабилизация новых типов диапазонов в модуле core::range. Речь идёт о таких типах, как:

  • core::range::Range;
  • core::range::RangeFrom;
  • core::range::RangeInclusive;
  • связанные с ними итераторы.

На первый взгляд это выглядит как внутреннее изменение стандартной библиотеки, но смысл у него практический. В Rust привычные диапазоны вроде 0..10 исторически сами реализуют Iterator. Из-за этого они не являются Copy, то есть их нельзя просто копировать как маленькое значение без перемещения.

Новые типы устроены иначе: они реализуют IntoIterator, а не Iterator напрямую. Это открывает дорогу к диапазонам, которые могут быть Copy. Например, становится проще хранить границы среза внутри компактной структуры и безопасно копировать такую структуру без ручного разделения start и end.

use core::range::Range;

#[derive(Clone, Copy)]
pub struct Span(Range<usize>);

impl Span {
    pub fn of(self, s: &str) -> &str {
        &s[self.0]
    }
}

Для обычного пользователя Rust это не значит, что привычный синтаксис 0..1 сразу поменял поведение. В текущем релизе он всё ещё создаёт старые типы диапазонов. Но направление уже видно: в будущей редакции Rust новые диапазоны должны стать более естественной основой для работы с подобными конструкциями.

Для авторов публичных API важная рекомендация — по возможности принимать не конкретный тип диапазона, а impl RangeBounds. Такой подход делает библиотеку совместимой и со старыми, и с новыми диапазонами.

assert_matches! упрощает диагностику ошибок в тестах

В Rust 1.96.0 стабилизированы макросы assert_matches! и debug_assert_matches!. Они позволяют проверить, что значение соответствует заданному шаблону.

Похожий результат можно было получить через assert!(matches!(...)), но новый вариант удобнее при падении проверки: он показывает значение через Debug, что помогает быстрее понять причину ошибки.

Пример из официального анонса:

use core::assert_matches;

/// Random Number
fn get_random_number() -> u32 {
    4
}

fn main() {
    assert_matches!(get_random_number(), 1..=6);
}

Для разработчиков это особенно полезно в тестах, парсерах, обработке enum-типов и ситуациях, где нужно не просто проверить true или false, а убедиться, что значение имеет конкретную форму.

Есть важная деталь: эти макросы не добавлены в стандартный prelude. Иными словами, они не подключаются автоматически в каждый файл. Их нужно импортировать вручную из core или std, потому что в экосистеме уже есть популярные сторонние crates с макросами под такими же именами.

WebAssembly-сборки стали строже к неопределённым символам

Rust 1.96.0 меняет поведение WebAssembly-таргетов при линковке. Теперь Rust больше не передаёт линкеру флаг --allow-undefined по умолчанию.

Проще говоря, если при сборке WebAssembly-модуля остаётся неопределённый символ, это теперь ошибка линковки, а не автоматическое превращение такого символа в импорт из модуля "env".

Это изменение может проявиться в проектах, которые собирают Rust-код в WebAssembly и полагаются на старое поведение. Но логика обновления понятна: неопределённые символы часто указывают на ошибку сборки, неправильную конфигурацию или несовпадение имён. Лучше поймать такую проблему на этапе сборки, чем получить странное поведение уже в рантайме.

Если старое поведение действительно нужно, его можно вернуть явно:

RUSTFLAGS=-Clink-arg=--allow-undefined

Также можно указать импортируемый модуль через атрибут #[link(wasm_import_module = "env")] в исходном коде. Но для большинства проектов правильнее сначала проверить, почему символы вообще остались неопределёнными.

Cargo получил исправления для сторонних registry

В релиз вошли исправления двух уязвимостей Cargo, которые важны прежде всего для пользователей сторонних registry:

УязвимостьСерьёзностьКраткое описаниеКого затрагивает
CVE-2026-5223MediumНекорректная обработка symlink внутри tarball-пакетов crateПользователей сторонних registry
CVE-2026-5222LowПроблема аутентификации при нормализации URLПользователей сторонних registry

В официальном advisory по CVE-2026-5223 команда Rust объяснила, что Cargo некорректно обрабатывал символические ссылки внутри tarball-архивов crate, загружаемых из сторонних registry. В определённых условиях вредоносный пакет мог повлиять на кэш другого пакета из того же registry.

Пользователей crates.io эта проблема не затрагивает: официальный registry уже запрещает загрузку crate с символическими ссылками. Но для компаний и команд, которые используют внутренние или альтернативные registry, обновление до Rust 1.96.0 выглядит особенно желательным.

В Rust 1.96.0 Cargo начинает отклонять извлечение любых symlink внутри tarball-пакетов crate. Если обновиться сразу нельзя, разумный временный шаг — проверить содержимое собственного registry и запретить загрузку пакетов с symlink на стороне инфраструктуры.

Rustdoc и Cargo получили менее заметные, но полезные доработки

Помимо крупных изменений, в Rust 1.96.0 есть несколько улучшений инструментов.

Cargo теперь позволяет зависимости одновременно указывать git-репозиторий и альтернативный registry. Локально будет использоваться git-репозиторий, а при публикации — версия из registry. Это может быть удобно для команд, которые разрабатывают пакеты во внутренней инфраструктуре и хотят точнее контролировать путь зависимости от разработки до публикации.

Также добавлена поддержка target.'cfg(..)'.rustdocflags в конфигурации. Это полезно для проектов, где документация должна собираться с разными флагами под разные целевые условия.

В Rustdoc изменилось отображение заметок о deprecated-элементах. Теперь такие заметки рендерятся более предсказуемо, как обычная документация. У этого есть побочный эффект: некоторые многострочные deprecation notes могут отображаться одной строкой. Если разрыв строки нужен явно, его можно задать стандартным Markdown-способом — двумя пробелами перед переносом строки.

Совместимость требует внимания у WebAssembly, AVR и нестандартных сборок

Rust 1.96.0 не выглядит как релиз, который массово ломает обычные проекты. Но есть зоны, где обновление стоит проверять внимательнее.

WebAssembly-проекты могут столкнуться с ошибками линковки из-за отказа от автоматического --allow-undefined. Для таких проектов перед обновлением лучше прогнать CI и убедиться, что все импортируемые функции и символы описаны явно.

Для AVR-таргетов есть breaking change: тип c_double теперь приведён к f32, потому что в C для AVR double по умолчанию имеет 32-битный размер. Это изменение нужно для корректного соответствия Rust и C, но оно может повлиять на низкоуровневый embedded-код.

Также в release notes перечислены дополнительные compatibility notes: изменения в проверке const generic arguments, поведении некоторых атрибутов вроде export_name, link_name и link_section, обновление минимального внешнего LLVM до версии 21 и другие детали. Большинство обычных приложений их не заметит, но для компиляторной, embedded- и инфраструктурной разработки такие пункты стоит прочитать отдельно перед обновлением.

Обновление стоит начинать с тестов и проверки цепочки сборки

Практический сценарий обновления до Rust 1.96.0 простой:

rustup update stable
cargo test
cargo clippy
cargo build --release

Если проект собирается под WebAssembly, стоит отдельно проверить wasm-сборку. Если команда использует сторонний registry, приоритетом становится обновление Cargo и аудит пакетов на стороне registry.

Для библиотек полезно посмотреть на публичные API, где используются диапазоны. Если API должен принимать разные виды диапазонов, лучше ориентироваться на RangeBounds, а не жёстко завязываться на конкретную реализацию.

Rust 1.96.0 готовит язык к аккуратным изменениям

Rust 1.96.0 — не революционный, а инфраструктурный релиз. Он улучшает стандартную библиотеку, делает проверки в тестах удобнее, усиливает безопасность Cargo и заранее подводит экосистему к более аккуратной модели диапазонов.

Главный практический вывод простой: большинству разработчиков стоит обновиться через rustup, прогнать тесты и отдельно проверить WebAssembly-сборки или проекты со сторонними registry. Для авторов библиотек этот релиз особенно интересен как сигнал к подготовке API под будущие изменения диапазонов.

При использовании материалов сайта необходимо указывать ссылку на TGLand.ru. Если вы копируете фрагменты текста в интернете, прямая гиперссылка, доступная для индексации поисковыми системами, должна быть размещена в начале материала.

Вам также может понравиться