Rust 1.83.0 Release

Добавлены новые возможности для константных контекстов

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

static S: i32 = 25;
const C: &i32 = &S;
fn main() { println!("Значение константы: {}", C); }

но не будет работать так

static mut S: i32 =0;
const C: &i32 = &S

так как нельзя ссылаться на мутабельную переменную в константе


Появилась возможность использовать мутабельные ссылки и указатели в контексте констант, что значительно расширяет возможности работы с const fn и другими вычислениями на этапе компиляции.

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

const fn inc(x: &mut i32) {
    *x += 1;
}
const fn make_mutable_reference() -> i32 {
    let mut val = 41;
    inc(&mut val);
    val
}
const C: i32 = make_mutable_reference();
fn main() {
    println!("Значение константы C: {}", C);
}

не нужно путать с примеров выше!!!

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

const C: &mut i32 = &mut 4; // Ошибка: mutable references are not allowed in the final value of constants

мутабельный указатель в константном контексте

use std::cell::UnsafeCell;
const fn modify_with_raw_pointer() -> i32 {
    let c = UnsafeCell::new(41);
    unsafe { *c.get() += 1 };
    c.into_inner()
}
const C: i32 = modify_with_raw_pointer();
fn main() {
    println!("Значение константы C: {}", C);
}

Но это все еще с ограничениями для обеспечения безопастности типов и предотвращения небезопасных операций.


Стабилизация новых методов для коллекций

Option::unwrap_unchecked

Option::replace

расширяют возможности обработки значений, что делает код более выразительным и удобным.

Изменения касается стабилизации методов для работы с сырыми указателями и мутабельными ячейками, что указывает на улучшения для низкоуровневых операций и работы с памятью.


Новые ошибки в ErrorKind улучшают поддержку работы с файловыми системами, что делает работу с низкоуровневыми операциями более безопасной и предсказуемой.

Оптимизированна работа

ptr::replace

ptr::slice_from_raw_parts_mut

для работы с сырыми указателями для модификации данных в массивах или срезах без необходимости копировать их.


Исправлены

slice::from_mut

slice::from_raw_parts_mut

для работы с мутабельными срезами, позволяющие изменять данные в массивах или срезах без необходимости копировать их.

//выглядит теперь это так
use std::ptr;

fn main() {
    let mut arr = [1, 2, 3, 4, 5];
    let ptr = arr.as_mut_ptr();
    unsafe {
        let slice = std::slice::from_raw_parts_mut(ptr, arr.len());
        slice[0] = 10;
        slice[4] = 20;
        println!("Изменённый массив: {:?}", arr); 
        // Выведет: [10, 2, 3, 4, 20]
    }
}

Обратите внимание что этот код находится внутри небезопастного блока unsafe,по скольку работа с сырыми указателями требует явного размешения на безопастный код.


Эти методы позволяют безопасно получать мутабельные ссылки на первый и последний элементы среза или массива. пример как теперь это работает

fn main() {
    let mut arr = [1, 2, 3, 4, 5];
    if let Some(first) = arr.first_mut() {
        *first = 10;
    }
    println!("Изменённый массив: {:?}", arr); 
    // Выведет: [10, 2, 3, 4, 5]
}

Option::get_or_insert_default

Теперь позволяет вставить значение по умолчанию в Option, если оно ещё не инициализировано (то есть если Option является None).

Эта функция полезна, например, при работе с кэшами, коллекциями или в ситуациях, где вы хотите гарантировать, что значение существует, и при необходимости инициализировать его значением по умолчанию.

use std::collections::HashMap;
fn main() {
    let mut cache: Option<HashMap<String, i32>> = None;
    cache.get_or_insert_default().insert("apple".to_string(), 5);
    cache.get_or_insert_default().insert("banana".to_string(), 7);
    if let Some(map) = cache {
        println!("Кэш: {:?}", map);
    }
}

//пример работы с вектором
fn main() {
    let mut nums: Option<Vec<i32>> = None;
    nums.get_or_insert_default().push(10);
    nums.get_or_insert_default().push(20);
    if let Some(vec) = nums {
        println!("Вектор: {:?}", vec);
    }
}

Методы для работы с числами и строками:

char::MIN:

Минимальный символ, доступный в языке.

{float}::classify

{float}::is_finite

{float}::is_infinite

и другие:

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


str::as_mut_ptr str::from_utf8_unchecked_mut

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

как теперь это работает в 1.83.0

f32::classify и f64::classify`

fn main() {
    let numbers = [3.14, 0.0, f32::INFINITY, f32::NEG_INFINITY, f32::NAN];

    for &num in &numbers {
        match num.classify() {
            std::num::FpCategory::Normal => println!("Число {:?} нормальное", num),
            std::num::FpCategory::Subnormal => println!("Число {:?} поднормальное", num),
            std::num::FpCategory::Zero => println!("Число {:?} равно нулю", num),
            std::num::FpCategory::Infinite => println!("Число {:?} бесконечность", num),
            std::num::FpCategory::Nan => println!("Число {:?} NaN", num),
        }
    }
}
//Число 3.14 нормальное
//Число 0.0 равно нулю
//Число inf бесконечность
//Число -inf бесконечность
//Число NaN NaN

f32::is_finite и f64::is_finite`

Метод is_finite проверяет, является ли число конечным (не бесконечностью или NaN).

fn main() {
    let numbers = [3.14, 0.0, f32::INFINITY, f32::NEG_INFINITY, f32::NAN];

    for &num in &numbers {
        if num.is_finite() {
            println!("Число {:?} конечное", num);
        } else {
            println!("Число {:?} не конечное", num);
        }
    }
}
//Число 3.14 конечное
//Число 0.0 конечное
//Число inf не конечное
//Число -inf не конечное
//Число NaN не конечное

f32::is_infinite и f64::is_infinite`

Метод is_infinite проверяет, является ли число бесконечностью (положительной или отрицательной).

fn main() {
    let numbers = [3.14, 0.0, f32::INFINITY, f32::NEG_INFINITY, f32::NAN];

    for &num in &numbers {
        if num.is_infinite() {
            println!("Число {:?} бесконечность", num);
        } else {
            println!("Число {:?} не бесконечность", num);
        }
    }
}
//Число 3.14 не бесконечность
//Число 0.0 не бесконечность
//Число inf бесконечность
//Число -inf бесконечность
//Число NaN не бесконечность