Rust 1.64.0: rust-analyzer в rustup, IntoFuture, ffi-типы в core и alloc, улучшения в Cargo

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

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


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


rustup update stable

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


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


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


Улучшение .await с помощью IntoFuture


В Rust 1.64 стабилизирован трейт IntoFuture. Он похож на трейт IntoIterator, но вместо поддержки циклов for ... in ..., IntoFuture изменяет поведение .await. С IntoFuture ключевое слово .await может применяться не только на футурах, но и на всём, что может быть преобразовано в Future при помощи IntoFuture, что сделает ваше API более простым для использования!


Возьмём, к примеру, билдер, который создаёт запрос к некоторому сетевому хранилищу:


pub struct Error { ... }
pub struct StorageResponse { ... }:
pub struct StorageRequest(bool);

impl StorageRequest {
    /// Создать новый экземпляр `StorageRequest`.
    pub fn new() -> Self { ... }
    /// Решить, будет ли включён отладочный режим.
    pub fn set_debug(self, b: bool) -> Self { ... }
    /// Отправить запрос и получить ответ.
    pub async fn send(self) -> Result<StorageResponse, Error> { ... }
}

Типичное использование, вероятно, будет выглядеть так:


let response = StorageRequest::new()  // 1. Создать экземпляр
    .set_debug(true)                  // 2. Установить некоторые настройки
    .send()                           // 3. Сконструировать Future
    .await?;                          // 4. Запустить Future + пробросить ошибки

Это уже неплохо, но мы можем сделать лучше. Используя IntoFuture, мы можем сделать за один шаг "создание футуры" (строка 3) и "запуск футуры" (строка 4):


let response = StorageRequest::new()  // 1. Создать экземпляр
    .set_debug(true)                  // 2. Установить некоторые настройки
    .await?;                          // 3. Сконструировать + запустить Future + пробросить ошибки

Мы можем сделать это, реализовав IntoFuture для StorageRequest. IntoFuture требует от нас наличия именованной футуры, которую мы возвращаем. Её мы можем создать упакованной и объявить для неё псевдоним:


// Сначала мы должны импортировать в область видимости несколько новых типов.
use std::pin::Pin;
use std::future::{Future, IntoFuture};

pub struct Error { ... }
pub struct StorageResponse { ... }
pub struct StorageRequest(bool);

impl StorageRequest {
    /// Создадим новый экземпляр `StorageRequest`.
    pub fn new() -> Self { ... }
    /// Решим, следует ли включить режим отладки.
    pub fn set_debug(self, b: bool) -> Self { ... }
    /// Отправим запрос и получим ответ
    pub async fn send(self) -> Result<StorageResponse, Error> { ... }
}

// Новая имплементация
// 1. Создадим новый именованный тип футуры
// 2. Имплементируем `IntoFuture` для `StorageRequest`
pub type StorageRequestFuture = Pin<Box<dyn Future<Output = Result<StorageResponse, Error> + Send + 'static>>
impl IntoFuture for StorageRequest {
    type IntoFuture = StorageRequestFuture;
    type Output = <StorageRequestFuture as Future>::Output;
    fn into_future(self) -> Self::IntoFuture {
        Box::pin(self.send())
    }
}

Это требует немного больше кода для реализации, но предоставляет более простой API для пользователей.


Мы надеемся, что в будущем Rust Async WG упростит создание новой именованной футуры при помощи impl Trait в type ("Type Alias Impl Trait" или TAIT). Это должно облегчить реализацию IntoFuture за счёт упрощения сигнатуры псевдонима и улучшить производительность за счёт удаления из псевдонима упаковки (Box).


C-совместимые типы FFI в core и alloc


Вызывая или будучи вызванным C ABI, код Rust может использовать псевдонимы типов, такие как c_uint или c_ulong для сопоставления соответствующих типов из C на любой целевой сборке, не требуя специализированного кода или условий.


Раньше эти псевдонимы типов были доступны только в std, поэтому код, написанный для встроенных систем и других сценариев, которые могли использовать только core или alloc, не мог использовать эти типы.


Rust 1.64 теперь предоставляет все псевдонимы типа c_* в core::ffi, а также core::ffi::CStr для работы со строками C. Rust 1.64 также предоставляет alloc::ffi::CString для работы с собственными строками C, используя только крейт alloc, а не полную библиотеку std.


Rust-analyzer теперь доступен через rustup


Rust-analyzer теперь входит в набор инструментов, включённых в Rust. Это упрощает загрузку и доступ к rust-analyzer, а также делает его доступным на большем количестве платформ. Он доступен как компонент rustup, который можно установить с помощью:


rustup component add rust-analyzer

В настоящее время, чтобы запустить версию, установленную rustup, вам нужно вызвать её следующим образом:


rustup run stable rust-analyzer

В следующем выпуске rustup предоставит встроенный прокси-сервер, так что при запуске исполняемого файла rust-analyzer будет запускаться соответствующая версия.


Большинству пользователей следует продолжать использовать выпуски, предоставленные командой rust-analyzer, которые публикуются чаще. Они доступны на странице выпусков rust-analyzer. Это не затрагивает пользователей официального расширения VSCode, поскольку оно автоматически загружает и обновляет выпуски в фоновом режиме.


Улучшения Cargo: наследование рабочего пространства и многоцелевые сборки


Теперь при работе с коллекциями связанных библиотек или бинарных крейтов в одном рабочем пространстве Cargo, вы можете избежать дублирования общих значений полей между крейтами, таких как общие номера версий, URL-адреса репозитория или rust-version. Это также помогает синхронизировать эти значения между крейтами при их обновлении. Дополнительные сведения см. в workspace.package, workspace.dependencies и "наследование зависимости от рабочего пространства".


При сборке для нескольких целей вы сможете передать несколько опций --target в cargo build, чтобы собрать их все одновременно. Вы также можете установить для build.target массив из нескольких целей в .cargo/config.toml, чтобы по умолчанию выполнять сборку для нескольких целей.


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


Стабилизированы следующие методы и реализации трейтов:


  • future::IntoFuture
  • num::NonZero*::checked_mul
  • num::NonZero*::checked_pow
  • num::NonZero*::saturating_mul
  • num::NonZero*::saturating_pow
  • num::NonZeroI*::abs
  • num::NonZeroI*::checked_abs
  • num::NonZeroI*::overflowing_abs
  • num::NonZeroI*::saturating_abs
  • num::NonZeroI*::unsigned_abs
  • num::NonZeroI*::wrapping_abs
  • num::NonZeroU*::checked_add
  • num::NonZeroU*::checked_next_power_of_two
  • num::NonZeroU*::saturating_add
  • os::unix::process::CommandExt::process_group
  • os::windows::fs::FileTypeExt::is_symlink_dir
  • os::windows::fs::FileTypeExt::is_symlink_file

Типы, ранее стабилизированные в std::ffi и теперь доступные в core и alloc:


  • core::ffi::CStr
  • core::ffi::FromBytesWithNulError
  • alloc::ffi::CString
  • alloc::ffi::FromVecWithNulError
  • alloc::ffi::IntoStringError
  • alloc::ffi::NulError

Типы, ранее стабилизированные в std::os::raw и теперь доступные в core::ffi и std::ffi:


  • ffi::c_char
  • ffi::c_double
  • ffi::c_float
  • ffi::c_int
  • ffi::c_long
  • ffi::c_longlong
  • ffi::c_schar
  • ffi::c_short
  • ffi::c_uchar
  • ffi::c_uint
  • ffi::c_ulong
  • ffi::c_ulonglong
  • ffi::c_ushort

Были стабилизированы несколько вспомогательных функций, которые используются с Poll, низкоуровневой реализацией футур:


  • future::poll_fn
  • task::ready!

Мы надеемся, что в будущем сможем предоставить более простое API, которое будет требовать меньше использования низкоуровневых деталей, таких как Poll и Pin. Но сейчас данные вспомогательные функции упростят написание такого кода.


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


  • slice::from_raw_parts

Замечания о совместимости


  • Как было ранее анонсировано, для компиляции целей linux потребуется ядро Linux 3.2 и выше (за исключением тех целей, которые уже требуют более новое ядро). Также цели linux-gnu теперь требуют glibc 2.17 (за исключением тех, которые уже требуют более новую glibc).
  • Rust 1.64.0 изменяет структуру размещения в памяти Ipv4Addr, Ipv6Addr, SocketAddrV4 и SocketAddrV6, чтобы сделать её более компактной и эффективной. Это внутреннее представление никогда не раскрывалось, но некоторые крейты всё равно полагались на него, используя std::mem::transmute, что приводило к недопустимым обращениям к памяти. Такие детали внутренней реализации стандартной библиотеки никогда не считаются стабильным интерфейсом. Чтобы ограничить ущерб, мы работали с авторами всех ещё поддерживаемых крейтов, чтобы выпустить исправленные версии, которые отсутствовали более года. Подавляющее большинство затронутых пользователей будут иметь возможность смягчить последствия с помощью cargo update.
  • В рамках прекращения поддержки RLS это также последний выпуск, содержащий копию RLS. Начиная с Rust 1.65.0, RLS будет заменён небольшим сервером LSP, показывающим предупреждение об устаревании.

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


Выпуск Rust 1.64 включает и другие изменения:


  • Компилятор Rust для Windows теперь собирается с PGO, что даёт прирост производительности при компилировании кода на 10-20%.
  • Если вы объявляли структуру, содержащую поле, которое никогда не используется, то rustc об этом предупреждал. Теперь вы можете включить проверку unused_tuple_struct_fields, чтобы получить аналогичное предупреждение о неиспользуемых полях в кортежных структурах. В будущих версиях мы планируем включить эту проверку по умолчанию. Для полей единичного типа (()) такое предупреждение не будет генерироваться для облегчения миграции существующего кода без изменения индексов кортежа.

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


Участники 1.64.0


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


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


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


Данную статью совместными усилиями перевели andreevlex TelegaOvoshey и funkill.

Источник: https://habr.com/ru/post/689876/


Интересные статьи

Интересные статьи

Команда Rust рада сообщить о выпуске новой версии — 1.53.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение. Если вы устано...
Последний год я собирал различные клавиатуры, что включает в себя и написание прошивок под различные управляющие схемы.Первоначально, я писал их на Rust, но несмотря на г...
Google Stadia, Geforce Now — крупнейшие игроки на рынке активно осваивают новый сегмент гейминга. Облачные игровые потоковые сервисы предлагают мгновенный доступ к играм без необходимости загружа...
Rust становится первоклассным языком в самых разных областях. Мы в Discord успешно используем его и на серверной, и на клиентской стороне. Например, на стороне клиента в конвейере кодирования...
В 1С-Битрикс: Управление сайтом (как и в Битрикс24) десятки, если не сотни настраиваемых типов данных (или сущностей): инфоблоки, пользователи, заказы, склады, форумы, блоги и т.д. Стр...