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

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-5223 | Medium | Некорректная обработка symlink внутри tarball-пакетов crate | Пользователей сторонних registry |
| CVE-2026-5222 | Low | Проблема аутентификации при нормализации 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 под будущие изменения диапазонов.