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

Rust 1.85.0 и Rust 2024

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

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


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


$ rustup update stable

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


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


Что входит в стабильную версию 1.85.0?


Rust 2024


Мы рады сообщить, что редакция Rust 2024 теперь стабильна! Редакции — это наш механизм для внесения крупных изменений в язык, которые могут привести к нарушению обратной совместимости. Смотрите руководство по редакциям для общей информации о том, как это работает, и получения подробных инструкций по переносу.


Это самая крупная редакция, которую мы когда-либо выпускали. Подробная информация обо всех изменениях содержится в руководстве по редакциям, а здесь мы предоставим краткую выдержку:



Переход на редакцию 2024


Руководство содержит инструкции по переносу всех новых функций и в целом по переводу существующего проекта в новую редакцию. Во многих случаях cargo fix позволяет автоматизировать необходимые изменения. Возможно, вы даже обнаружите, что для перехода на редакцию 2024 вообще не потребуется вносить никаких изменений в ваш код!


Обратите внимание, что автоматические исправления с помощью cargo fix очень консервативны и будут избегать изменения семантики вашего кода. Во многих случаях вы захотите сохранить свой код прежним, используя при этом новую семантику Rust 2024. Например, продолжая использовать средство сопоставления макросов expr и игнорируя преобразования условных выражений, потому что вам нужна новая семантика порядка выполнения Drop. Результат cargo fix не следует рассматривать как рекомендацию, это просто консервативное преобразование, которое сохраняет поведение.


Над созданием этого издания работало множество людей. Мы хотели бы поблагодарить их всех за усердную работу!


async closures


Rust теперь поддерживает асинхронные замыкания, такие как async ||{}, которые при вызове возвращают футуры. Они работают подобно async fn, которые также могут захватывать значения из локальной среды. Разница между ними точно такая же, как между обычными замыканиями и функциями. Эта функциональность также включает в себя 3 аналогичных трейта в прелюдии стандартной библиотеки: AsyncFn, AsyncFnMut и AsyncFnOnce.


В некоторых случаях вы могли создать нечто подобное с помощью обычного замыкания и асинхронного блока, например || async {} — но футура, возвращаемая таким внутренним блоком, не может быть заимствована из перехватов замыкания. Однако это работает с async-замыканиями:


let mut vec: Vec<String> = vec![];

let closure = async || {
    vec.push(ready(String::from("")).await);
};

Также было невозможно правильно выразить сигнатуры функций более высокого ранга с помощью трейтов Fn, возвращающих Future. Впрочем, вы могли сделать это с помощью трейтов AsyncFn:


use core::future::Future;
async fn f<Fut>(_: impl for<'a> Fn(&'a u8) -> Fut)
where
    Fut: Future<Output = ()>,
{ todo!() }

async fn f2(_: impl for<'a> AsyncFn(&'a u8))
{ todo!() }

async fn main() {
    async fn g(_: &u8) { todo!() }
    f(g).await;
    //~^ ERROR mismatched types
    //~| ERROR one type is more general than the other

    f2(g).await; // ok!
}

Таким образом, async-замыкания предоставляют первоклассные решения для обеих этих проблем! Более подробную информацию смотрите в RFC 3668 и в отчёте о стабилизации.


Скрытие реализаций трейтов от диагностики


Новый атрибут #[diagnostic::do_not_recommend] является подсказкой компилятору не показывать аннотированную реализацию трейта как часть диагностического сообщения. Для авторов библиотек это способ уберечь компилятор от внесения предложений, которые могут оказаться бесполезными или вводящими в заблуждение. Например:


pub trait Foo {}
pub trait Bar {}

impl<T: Foo> Bar for T {}

struct MyType;

fn main() {
    let _object: &dyn Bar = &MyType;
}

error[E0277]: the trait bound `MyType: Bar` is not satisfied
 --> src/main.rs:9:29
  |
9 |     let _object: &dyn Bar = &MyType;
  |                             ^^^^ the trait `Foo` is not implemented for `MyType`
  |
note: required for `MyType` to implement `Bar`
 --> src/main.rs:4:14
  |
4 | impl<T: Foo> Bar for T {}
  |         ---  ^^^     ^
  |         |
  |         unsatisfied trait bound introduced here
  = note: required for the cast from `&MyType` to `&dyn Bar`

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


#[diagnostic::do_not_recommend]
impl<T: Foo> Bar for T {}

error[E0277]: the trait bound `MyType: Bar` is not satisfied
  --> src/main.rs:10:29
   |
10 |     let _object: &dyn Bar = &MyType;
   |                             ^^^^ the trait `Bar` is not implemented for `MyType`
   |
   = note: required for the cast from `&MyType` to `&dyn Bar`

Смотрите RFC 2397, чтобы узнать первоначальную мотивацию изменения и текущий reference для получения более подробных деталей.


FromIterator и Extend для кортежей


В более ранних версиях Rust были реализованы удобные функции для итераторов из пар кортежей (T, U), которые вели себя как Iterator::unzip, с Extend в версии 1.56 и FromIterator в версии 1.79. Теперь они были расширены для большего количества кортежей, начиная с одноэлементного (T,) и заканчивая кортежами длиной в 12 элементов, (T1, T2, .., T11, T12). Например, теперь вы можете использовать collect() для создания нескольких коллекций одновременно:


use std::collections::{LinkedList, VecDeque};
fn main() {
    let (squares, cubes, tesseracts): (Vec<_>, VecDeque<_>, LinkedList<_>) =
        (0i32..10).map(|i| (i * i, i.pow(3), i.pow(4))).collect();
    println!("{squares:?}");
    println!("{cubes:?}");
    println!("{tesseracts:?}");
}

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
[0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561]

Обновления в std::env::home_dir()


std::env::home_dir() уже много лет считается устаревшим, поскольку может давать неожиданные результаты в некоторых конфигурациях Windows, когда установлена переменная среды HOME (что не является ситуацией по умолчанию). Ранее мы избегали изменений этой функции из-за вопросов совместимости с кодом, зависящим от этой нестандартной конфигурации. Но, учитывая, как долго эта функция была устаревшей, мы сейчас обновляем её поведение заодно с исправлением других ошибок, так что в следующих выпусках она больше не будет помечена устаревшей.


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



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



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


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


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


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


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


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

Теги:
Хабы:
Всего голосов 17: ↑16 и ↓1+17
Комментарии11

Публикации

Работа

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

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