Как стать автором
Обновить

Rust 1.86.0: преобразование в родительский трейт, поддержка изменяемой индексации для HashMap и срезов

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров1.1K
Автор оригинала: The Rust Release Team

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


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


$ rustup update stable

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


Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать канал beta (rustup default beta) или nightly (rustup default nightly). Пожалуйста, сообщайте обо всех встреченных вами ошибках.


Что стабилизировано в 1.86.0


Преобразование в родительский трейт


В этом выпуске появилась долгожданная функция — возможность приводить объекты трейта к родительскому. Если у трейта есть супертрейт, вы можете привести ссылку на указанный трейт-объект к ссылке на трейт-объект супертрейта:


trait Trait: Supertrait {}
trait Supertrait {}

fn upcast(x: &dyn Trait) -> &dyn Supertrait {
    x
}

То же самое будет работать с любым другим типом (умного) указателя, например Arc<dyn Trait> -> Arc<dyn Supertrait> или *const dyn Trait -> *const dyn Supertrait.


Раньше это потребовало бы обходного пути в виде метода upcast в самом Trait, например fn as_supertrait(&self) -> &dyn Supertrait — и это работало бы только для одного вида ссылки/указателя. Такие обходные пути больше не нужны.


Обратите внимание, что это означает, что необработанные указатели на трейт-объекты содержат нетривиальный инвариант: "утёкший" в безопасный код необработанный указатель на трейт-объект с недопустимой виртуальной таблицей может привести к неопределённому поведению. Пока нет уверенности в том, приведёт ли временное создание такого необработанного указателя в хорошо контролируемых обстоятельствах к немедленному неопределённому поведению или нет, поэтому в коде нужно воздержаться от создания таких указателей при любых условиях (и Miri обеспечивает это).


Преобразование к родительскому трейту может быть особенно полезно при использовании трейта Any, поскольку он позволяет преобразовать ваш трейт-объект в dyn Any для вызова Any::downcast без добавления к трейту каких-либо методов или использования внешних крейтов.


use std::any::Any;

trait MyAny: Any {}

impl dyn MyAny {
    fn downcast_ref<T>(&self) -> Option<&T> {
        (self as &dyn Any).downcast_ref()
    }
}

Дополнительную информацию о преобразовании типов можно найти в Rust reference.


HashMap и срезы теперь поддерживают изменяемую индексацию нескольких элементов


Анализатор заимствований предотвращает одновременное использование ссылок, полученных в результате повторных вызовов методов get_mut. Для безопасной поддержки этого шаблона стандартная библиотека теперь предоставляет метод get_disjoint_mut для срезов и HashMap для одновременного извлечения изменяемых ссылок на несколько элементов. Вы можете изучить следующий пример, взятый из документации API для slice::get_disjoint_mut:


let v = &mut [1, 2, 3];
if let Ok([a, b]) = v.get_disjoint_mut([0, 2]) {
    *a = 413;
    *b = 612;
}
assert_eq!(v, &[413, 2, 612]);

if let Ok([a, b]) = v.get_disjoint_mut([0..1, 1..3]) {
    a[0] = 8;
    b[0] = 88;
    b[1] = 888;
}
assert_eq!(v, &[8, 88, 888]);

if let Ok([a, b]) = v.get_disjoint_mut([1..=2, 0..=0]) {
    a[0] = 11;
    a[1] = 111;
    b[0] = 1;
}
assert_eq!(v, &[1, 11, 111]);

Разрешено помечать безопасные функции атрибутом #[target_feature]


Ранее только unsafe функции могли быть помечены атрибутом #[target_feature], поскольку такие функции нецелесообразно вызывать без включения целевой функции. Этот релиз стабилизирует функцию target_feature_11, позволяя помечать безопасные функции атрибутом #[target_feature].


Безопасные функции, отмеченные атрибутом #[target_feature], могут быть безопасно вызваны только из других функций, отмеченных атрибутом #[target_feature]. Однако их нельзя передать функциям, принимающим обобщения, ограниченные чертами Fn*. Также они поддерживают только приведение к указателям функций внутри функций, отмеченных атрибутом target_feature.


Внутри функций, не отмеченных атрибутом целевой функции, они могут быть вызваны внутри unsafe блока, однако вызывающая сторона несёт ответственность за обеспечение доступности целевой функции.


#[target_feature(enable = "avx2")]
fn requires_avx2() {
    // ... snip
}

#[target_feature(enable = "avx2")]
fn safe_callsite() {
    // Здесь вызов `requires_avx2` безопасен, так как  `safe_callsite`
    // сама требует `avx2`.
    requires_avx2();
}

fn unsafe_callsite() {
    // Здесь вызов `requires_avx2` не безопасен, и мы сначала
    // должны удостовериться, что `avx2` доступен.
    if is_x86_feature_detected!("avx2") {
        unsafe { requires_avx2() };
    }
}

Более подробную информацию можно найти в RFC target_features_11.


Отладка утверждений о том, что указатели не равны нулю, когда это необходимо для корректности


Компилятор теперь будет вставлять отладочные проверки о том, что указатель не равен null, при выполнении операций чтения и записи ненулевого размера, а также при повторном преобразовании указателя в ссылку. Например, следующий код теперь будет генерировать панику без размотки, когда включены отладочные утверждения:


let _x = *std::ptr::null::<u8>();
let _x = &*std::ptr::null::<u8>();

Такие тривиальные примеры, как этот, вызывали предупреждение, начиная с Rust 1.53.0. Новая же проверка во время выполнения обнаружит такие сценарии независимо от их сложности.


Эти проверки выполняются только тогда, когда включены отладочные проверки. Это означает, что на их надёжность не следует полагаться, а также что зависимости, которые были скомпилированы с отключёнными отладочными проверками (например, стандартная библиотека), не будут запускать проверки, даже если они вызываются кодом с включёнными отладочными проверками.


missing_abi по умолчанию генерирует предупреждение


Пропуск ABI в extern-блоках и функциях (например, extern {} и extern fn) теперь приведёт к появлению предупреждения (через проверку missing_abi). Пропуск ABI после ключевого слова extern всегда неявно приводил к включению ABI "C". Теперь рекомендуется явно указывать "C" ABI (например, extern "C" {} и extern "C" fn).


Более подробную информацию можно найти в документе RFC «Explicit Extern ABIs».


Предупреждение об устаревании таргета для 1.87.0


tier-2 i586-pc-windows-msvc будет удалён в следующей версии Rust 1.87.0. Его отличие от гораздо более популярного i686-pc-windows-msvc заключается в том, что он не требует поддержки инструкций SSE2, но Windows 10 — минимально необходимая версия ОС для всех целевых объектов windows (кроме целевых объектов win7) — сама требует инструкций SSE2.


Всем пользователям, которые в настоящее время используют i586-pc-windows-msvc, следует перейти на i686-pc-windows-msvc до выхода версии 1.87.0.


Более подробную информацию можно найти в Предложении о крупных изменениях.


Стабилизированные API



Следующие API теперь можно использовать в контексте const:



Прочие изменения


Проверьте всё, что изменилось в Rust, Cargo и Clippy.


Кто работал над 1.86.0


Многие люди собрались вместе, чтобы создать Rust 1.86.0. Без вас мы бы не справились. Спасибо!


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


С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков.

Теги:
Хабы:
+14
Комментарии22

Публикации

Истории

Работа

Rust разработчик
7 вакансий

Ближайшие события

8 апреля
Конференция TEAMLY WORK MANAGEMENT 2025
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань
20 – 22 июня
Летняя айти-тусовка Summer Merge
Ульяновская область