Команда Rust рада сообщить о новой версии языка — 1.80.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если у вас есть предыдущая версия Rust, установленная через rustup
, то для обновления до версии 1.80.0 вам достаточно выполнить команду:
$ rustup update stable
Если у вас ещё не установлен rustup
, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть подробные примечания к выпуску на GitHub.
Если вы хотите помочь нам протестировать будущие выпуски, вы можете использовать канал beta (rustup default beta
) или nightly (rustup default nightly
). Пожалуйста, сообщайте обо всех встреченных вами ошибках.
Что стабилизировано в 1.80.0
LazyCell
и LazyLock
Это «ленивые» типы, которые откладывают инициализацию своих данных до первого обращения к ним. Они похожи на типы OnceCell
и OnceLock
, стабилизированные в 1.70, но с функцией инициализации, включённой в тип. Это завершает стабилизацию в стандартной библиотеке адаптированной функциональности популярных крейтов lazy_static
и once_cell
.
LazyLock
— потокобезопасный вариант, подходящий для таких мест, как значения static
. Так, в примере ниже и поток, ответвившийся с помощью spawn
, и основной поток (scope
) увидят в точности одну и ту же длительность, поскольку LAZY_TIME
будет инициализироваться один раз, в зависимости от того, кто первым получит доступ к статическому значению. При этом ни один из вариантов не требует знать, как именно его инициализировать, как в случае с OnceLock::get_or_init
.
use std::sync::LazyLock;
use std::time::Instant;
static LAZY_TIME: LazyLock<Instant> = LazyLock::new(Instant::now);
fn main() {
let start = Instant::now();
std::thread::scope(|s| {
s.spawn(|| {
println!("Thread lazy time is {:?}", LAZY_TIME.duration_since(start));
});
println!("Main lazy time is {:?}", LAZY_TIME.duration_since(start));
});
}
LazyCell
делает то же самое без синхронизации потоков, поэтому он не реализует Sync
, необходимый для static
, но его можно использовать в статиках thread_local!
(с отдельной инициализацией для каждого потока). Любой из этих типов может использоваться и в других структурах данных, в зависимости от потребностей в безопасности потоков, так что ленивая инициализация доступна везде!
Проверяемые имена и значения cfg
В 1.79 rustc
стабилизировал флаг --check-cfg
, и теперь Cargo 1.80 включает эти проверки для всех известных ему имён cfg
(в дополнение ко встроенным в rustc
). Сюда входят имена фич из Cargo.toml
, а также новый вывод cargo::rustc-check-cfg
из скриптов сборки.
О неожиданных конфигурациях сообщает линт unexpected_cfgs
, который предназначен для выявления опечаток или других ошибок. Например, в проекте с необязательной зависимостью rayon
этот код настроен на неправильное значение:
fn main() {
println!("Hello, world!");
#[cfg(feature = "crayon")]
rayon::join(
|| println!("Hello, Thing One!"),
|| println!("Hello, Thing Two!"),
);
}
warning: unexpected `cfg` condition value: `crayon`
--> src/main.rs:4:11
|
4 | #[cfg(feature = "crayon")]
| ^^^^^^^^^^--------
| |
| help: there is a expected value with a similar name: `"rayon"`
|
= note: expected values for `feature` are: `rayon`
= help: consider adding `crayon` as a feature in `Cargo.toml`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
Это предупреждение выдаётся независимо от того, включена или нет фича rayon
.
Таблица [lints]
в Cargo.toml
также может использоваться для расширения списка известных имён и значений для пользовательских cfg
. rustc
автоматически предоставляет синтаксис для использования их в предупреждениях.
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(foo, values("bar"))'] }
Вы можете прочитать больше об этой функциональности в предыдущей статье блога, анонсирующей эту функциональность в nightly.
Эксклюзивные диапазоны в шаблонах
В шаблонах диапазонов Rust теперь могут использоваться диапазоны с исключённой конечной точкой («эксклюзивные»), записываемые как a..b
или ..b
, аналогично типам выражений Range
и RangeTo
. Например, в следующих шаблонах теперь можно использовать одни и те же константы для конца одного шаблона и начала следующего:
pub fn size_prefix(n: u32) -> &'static str {
const K: u32 = 10u32.pow(3);
const M: u32 = 10u32.pow(6);
const G: u32 = 10u32.pow(9);
match n {
..K => "",
K..M => "k",
M..G => "M",
G.. => "G",
}
}
Раньше в шаблонах допускались только диапазоны, включающие конечную точку («инклюзивные» — a..=b
или ..=b
), или открытые (a..
) диапазоны. Поэтому код вроде приведённого выше требовал вводить отдельные константы, такие как K - 1
для конечных точек.
Эксклюзивные диапазоны были реализованы в качестве нестабильной фичи уже давно, но стабилизации мешали опасения, что они могут внести путаницу и увеличить вероятность ошибок в шаблонах. В связи с этим были улучшены проверки исчерпывающего сопоставления с шаблоном, чтобы лучше обнаруживать пробелы в сопоставлении, а новые линты non_contiguous_range_endpoints
и overlapping_range_endpoints
помогут обнаружить случаи, когда вы хотели бы поменять эксклюзивные шаблоны-диапазоны на инклюзивные или наоборот.
Стабилизированные API
impl Default для Rc<CStr>
impl Default для Rc<str>
impl Default для Rc<[T]>
impl Default для Arc<str>
impl Default для Arc<CStr>
impl Default для Arc<[T]>
impl IntoIterator для Box<[T]>
impl FromIterator<String> для Box<str>
impl FromIterator<char> для Box<str>
LazyCell
LazyLock
Duration::div_duration_f32
Duration::div_duration_f64
Option::take_if
Seek::seek_relative
BinaryHeap::as_slice
NonNull::offset
NonNull::byte_offset
NonNull::add
NonNull::byte_add
NonNull::sub
NonNull::byte_sub
NonNull::offset_from
NonNull::byte_offset_from
NonNull::read
NonNull::read_volatile
NonNull::read_unaligned
NonNull::write
NonNull::write_volatile
NonNull::write_unaligned
NonNull::write_bytes
NonNull::copy_to
NonNull::copy_to_nonoverlapping
NonNull::copy_from
NonNull::copy_from_nonoverlapping
NonNull::replace
NonNull::swap
NonNull::drop_in_place
NonNull::align_offset
<[T]>::split_at_checked
<[T]>::split_at_mut_checked
str::split_at_checked
str::split_at_mut_checked
str::trim_ascii
str::trim_ascii_start
str::trim_ascii_end
<[u8]>::trim_ascii
<[u8]>::trim_ascii_start
<[u8]>::trim_ascii_end
Ipv4Addr::BITS
Ipv4Addr::to_bits
Ipv4Addr::from_bits
Ipv6Addr::BITS
Ipv6Addr::to_bits
Ipv6Addr::from_bits
Vec::<[T; N]>::into_flattened
<[[T; N]]>::as_flattened
<[[T; N]]>::as_flattened_mut
Следующие API теперь можно использовать в контексте const
:
Прочие изменения
Проверьте всё, что изменилось в Rust, Cargo и Clippy.
Кто работал над 1.80.0
Многие люди собрались вместе, чтобы создать Rust 1.80.0. Без вас мы бы не справились. Спасибо!
От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков.
Данную статью совместными усилиями перевели andreevlex, TelegaOvoshey, Browning и funkill.
Комментарии (2)
Apoheliy
28.07.2024 13:06Поберегите читателей. Уберите "Системное программирование" - нет тут такого.
kozlov_de
Для лиги душноты:
Это не новинки языка, а библиотеки std