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


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


$ rustup update stable

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


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


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


Новые возможности констант


Новый выпуск включает в себя несколько крупных расширений возможностей кода, работающего в константных контекстах. Это касается всего кода, который должен быть определён к моменту компиляции: начальное значение const и static элементов, длины массивов, значения дискриминанта перечисления, а также константные универсальные аргументы и функции, вызываемые из таких контекстов (const fn).


Ссылки на значения static. До сих пор константным контекстам (за исключением выражения инициализатора static элемента) было запрещено ссылаться на static элементы. Теперь это ограничение снято:


static S: i32 = 25;
const C: &i32 = &S;

Обратите внимание, что чтение значения изменяемой или внутренней изменяемой статической переменной по-прежнему не допускается в контекстах const. Более того, конечное значение константы не может ссылаться на любую изменяемую или внутреннюю изменяемую статику:


static mut S: i32 = 0;

const C1: i32 = unsafe { S };
// ошибка: доступ из константного контекста к глобальной изменяемой памяти

const C2: &i32 = unsafe { &S };
// ошибка: ссылка на изменяемую память в `const`

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


При этом константе разрешено вычисляться как raw-указатель, указывающий на изменяемый или внутренний изменяемый статический объект:


static mut S: i32 = 64;
const C: *mut i32 = &raw mut S;

Изменяемые ссылки и указатели. Теперь можно использовать изменяемые ссылки в константных контекстах:


const fn inc(x: &mut i32) {
    *x += 1;
}

const C: i32 = {
    let mut c = 41;
    inc(&mut c);
    c
};

Также поддерживаются изменяемые сырые указатели и внутренняя изменяемость:


use std::cell::UnsafeCell;

const C: i32 = {
    let c = UnsafeCell::new(41);
    unsafe { *c.get() += 1 };
    c.into_inner()
};

Однако изменяемые ссылки и указатели могут использоваться только внутри вычисления константы и не могут стать частью её конечного значения:


const C: &mut i32 = &mut 4;
// ошибка[E0764]: изменяемые ссылки недопустимы в конечном значении констант

Этот выпуск также поставляется с целым пакетом новых функций, которые теперь стабильны в константных контекстах (см. конец раздела «Стабилизированные API»).


Эти новые возможности и стабилизированные API открывают возможность выполнения целой новой категории кода внутри константных контекстов, и мы с нетерпением ждём, как экосистема Rust воспользуется этим!


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



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



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


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


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


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

Комментарии (5)


  1. domix32
    02.12.2024 09:55

    А кто-нибудь знает откуда взялась конструкция &raw mut . Кто-то криво лайфтайм написал или новое ключевое слово завезли?


    1. unC0Rr
      02.12.2024 09:55

      Это замена макросу addr_of, позволяет создавать указатели без промежуточной ссылки (reference), что позволяет избежать UB, возникающее при создании ссылки на выражение, которое не выровнено в памяти (not aligned) или не инициализировано.


  1. kuqmua
    02.12.2024 09:55

    "Теперь можно использовать изменяемые ссылки в константных контекстах". Чем это отличается от OnceCell и lazy_static? Просто интересно


    1. orekh
      02.12.2024 09:55

      OnceCell и lazy_static вычисляются один раз, но при выполнении программы, когда происходит первый раз доступ к ним. const как бы тоже вычисляется один раз, но при компиляции программы, и служит не как какое-то конкретное значение, а как текстовый шаблон для подстановки в разных местах программы, так можно написать const v = const { Vec::new() } и в любом месте, где напишешь v будет подставлен свой вектор, а не один заранее вычисленный, на которой будут ссылаться все v. Так можно написать let a = [Vec::new(); 2] и компилятор забракует этот код, т.к ты пытаешься размножить вектор в каждую ячейку массива, а если написать a = [const { Vec::new() }; 2], то все будет норм, как будто ты просто руками написал [Vec::new(), Vec::new()], или будто это тривиально копируемое значение


      1. kuqmua
        02.12.2024 09:55

        А разве нельзя было раньше просто запихнуть мутабельную логику в макрос и результат в виде токен стрима подставлять к const? Вроде как по сути тоже самое.