Команда 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
BufRead::skip_until
ControlFlow::break_value
ControlFlow::continue_value
ControlFlow::map_break
ControlFlow::map_continue
DebugList::finish_non_exhaustive
DebugMap::finish_non_exhaustive
DebugSet::finish_non_exhaustive
DebugTuple::finish_non_exhaustive
ErrorKind::ArgumentListTooLong
ErrorKind::Deadlock
ErrorKind::DirectoryNotEmpty
ErrorKind::ExecutableFileBusy
ErrorKind::FileTooLarge
ErrorKind::HostUnreachable
ErrorKind::IsADirectory
ErrorKind::NetworkDown
ErrorKind::NetworkUnreachable
ErrorKind::NotADirectory
ErrorKind::NotSeekable
ErrorKind::ReadOnlyFilesystem
ErrorKind::ResourceBusy
ErrorKind::StaleNetworkFileHandle
ErrorKind::StorageFull
ErrorKind::TooManyLinks
Option::get_or_insert_default
Waker::data
Waker::new
Waker::vtable
char::MIN
hash_map::Entry::insert_entry
hash_map::VacantEntry::insert_entry
Следующие API теперь можно использовать в контексте const
:
Cell::into_inner
Duration::as_secs_f32
Duration::as_secs_f64
Duration::div_duration_f32
Duration::div_duration_f64
MaybeUninit::as_mut_ptr
NonNull::as_mut
NonNull::copy_from
NonNull::copy_from_nonoverlapping
NonNull::copy_to
NonNull::copy_to_nonoverlapping
NonNull::slice_from_raw_parts
NonNull::write
NonNull::write_bytes
NonNull::write_unaligned
OnceCell::into_inner
Option::as_mut
Option::expect
Option::replace
Option::take
Option::unwrap
Option::unwrap_unchecked
Option::<&_>::copied
Option::<&mut _>::copied
Option::<Option<_>>::flatten
Option::<Result<_, _>>::transpose
RefCell::into_inner
Result::as_mut
Result::<&_, _>::copied
Result::<&mut _, _>::copied
Result::<Option<_>, _>::transpose
UnsafeCell::get_mut
UnsafeCell::into_inner
array::from_mut
char::encode_utf8
{float}::classify
{float}::is_finite
{float}::is_infinite
{float}::is_nan
{float}::is_normal
{float}::is_sign_negative
{float}::is_sign_positive
{float}::is_subnormal
{float}::from_bits
{float}::from_be_bytes
{float}::from_le_bytes
{float}::from_ne_bytes
{float}::to_bits
{float}::to_be_bytes
{float}::to_le_bytes
{float}::to_ne_bytes
mem::replace
ptr::replace
ptr::slice_from_raw_parts_mut
ptr::write
ptr::write_unaligned
<*const _>::copy_to
<*const _>::copy_to_nonoverlapping
<*mut _>::copy_from
<*mut _>::copy_from_nonoverlapping
<*mut _>::copy_to
<*mut _>::copy_to_nonoverlapping
<*mut _>::write
<*mut _>::write_bytes
<*mut _>::write_unaligned
slice::from_mut
slice::from_raw_parts_mut
<[_]>::first_mut
<[_]>::last_mut
<[_]>::first_chunk_mut
<[_]>::last_chunk_mut
<[_]>::split_at_mut
<[_]>::split_at_mut_checked
<[_]>::split_at_mut_unchecked
<[_]>::split_first_mut
<[_]>::split_last_mut
<[_]>::split_first_chunk_mut
<[_]>::split_last_chunk_mut
str::as_bytes_mut
str::as_mut_ptr
str::from_utf8_unchecked_mut
Прочие изменения
Проверьте всё, что изменилось в Rust, Cargo и Clippy.
Кто работал над 1.83.0
Многие люди собрались вместе, чтобы создать Rust 1.83.0. Без вас мы бы не справились. Спасибо!
Комментарии (5)
kuqmua
02.12.2024 09:55"Теперь можно использовать изменяемые ссылки в константных контекстах". Чем это отличается от OnceCell и lazy_static? Просто интересно
orekh
02.12.2024 09:55OnceCell и lazy_static вычисляются один раз, но при выполнении программы, когда происходит первый раз доступ к ним. const как бы тоже вычисляется один раз, но при компиляции программы, и служит не как какое-то конкретное значение, а как текстовый шаблон для подстановки в разных местах программы, так можно написать const v = const { Vec::new() } и в любом месте, где напишешь v будет подставлен свой вектор, а не один заранее вычисленный, на которой будут ссылаться все v. Так можно написать let a = [Vec::new(); 2] и компилятор забракует этот код, т.к ты пытаешься размножить вектор в каждую ячейку массива, а если написать a = [const { Vec::new() }; 2], то все будет норм, как будто ты просто руками написал [Vec::new(), Vec::new()], или будто это тривиально копируемое значение
kuqmua
02.12.2024 09:55А разве нельзя было раньше просто запихнуть мутабельную логику в макрос и результат в виде токен стрима подставлять к const? Вроде как по сути тоже самое.
domix32
А кто-нибудь знает откуда взялась конструкция
&raw mut
. Кто-то криво лайфтайм написал или новое ключевое слово завезли?unC0Rr
Это замена макросу addr_of, позволяет создавать указатели без промежуточной ссылки (reference), что позволяет избежать UB, возникающее при создании ссылки на выражение, которое не выровнено в памяти (not aligned) или не инициализировано.