Написать пост

Вышел Rust 1.28

Аватар Сергей Бугаев

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

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

Глобальные аллокаторы

В Rust 1.28 была добавлена поддержка настройки глобальных аллокаторов. Для выделения памяти Rust обращается к аллокатору; в предыдущих версиях Rust не позволял настроить, какой аллокатор используется — всегда использовался или jemalloc, или системный аллокатор (функции malloc()/realloc()/free() из libc), в зависимости от платформы. В Rust 1.28 была стабилизирована поддержка кастомных аллокаторов в качестве глобального аллокатора. Для этого нужно реализовать unsafe-типаж GlobalAlloc и пометить экземпляр аллокатора атрибутом #[global_allocator]:

			use std::alloc::{GlobalAlloc, Layout, alloc};
use std::ptr::null_mut;

struct MyAllocator;

// Простейший аллокатор, который всегда возвращает null
unsafe impl GlobalAlloc for MyAllocator {
    unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}

#[global_allocator]
static A: MyAllocator = MyAllocator;

fn main() {
    let u32_layout = Layout::new::<u32>();
    let p: *mut u32 = unsafe {
        alloc(u32_layout) as *mut u32
    };
    assert!(p.is_null());
}
		

Похожим образом можно и явно использовать системный аллокатор (вместо jemalloc), воспользовавшись экземпляром типа std::alloc::System:

			use std::alloc::System;

#[global_allocator]
static GLOBAL: System = System;

fn main() {
    let mut v = Vec::new();
    // Память для вектора здесь будет выделена
    // с использованием системного аллокатора
    v.push(1);
}
		

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

Улучшенные сообщения об ошибках при форматировании строк

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

			format!("{_foo}", _foo = 6usize);
		

В прошлых версиях была бы выдана такая ошибка:

			error: invalid format string: expected `'}'`, found `'_'`
  |
2 |     format!("{_foo}", _foo = 6usize);
  |             ^^^^^^^^
		

Rust 1.28 выдаёт гораздо более понятное сообщение об ошибке, указывающее на проблемную подстановку, а не на всю шаблонную строку, и описывающее конкретную проблему:

			error: invalid format string: invalid argument name `_foo`
  |
2 |     format!("{_foo}", _foo = 6usize);
  |               ^^^^ invalid argument name in format string
  |
  = note: argument names cannot start with an underscore
		

NonZero

В дополнение к типу NonNull, появившемуся в версии 1.25, в Rust 1.28 были добавлены типы NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128 и NonZeroUsize. Эти типы описывают положительные (ненулевые) беззнаковые целые числа различной длины; как и к NonNull, к ним применима так называемая оптимизация нулевого значения, позволяющая Option и другим типам использовать нулевое значение в качестве дискриминанта, не занимая дополнительного места в памяти:

			use std::mem;
use std::num::NonZeroU8;

struct Key(NonZeroU8);

struct Door {
    key: Key,
}

fn main() {
    assert_eq!(mem::size_of::<Door>(), 1);
    assert_eq!(mem::size_of::<Option<Door>>(), 1);
}
		

Прочее

Кроме того, в Rust 1.28 были дезрезервированы бывшие ключевые слова pure, sizeof, alignof и offsetof (теперь их можно использовать в качестве идентификаторов), была стабилизирована поддержка атрибута #[repr(transparent)], позволяющего гарантировать совпадение бинарного представления типа и оборачиваемого им значения, и добавлен явный способ использовать синтаксис времён жизни (lifetimes) внутри декларативных макросов. В стандартную библиотеку было добавлено несколько функций и реализаций типажей.

С подробным списком изменений можно ознакомиться в GitHub-репозитории проекта.

Предыдущая версия языка, Rust 1.27, вышла в июне 2018 года. В неё были добавлены: поддержка явного использования SIMD, нового синтаксиса для типов объектов типажей и новые функции в стандартную библиотеку.

Следите за новыми постами
Следите за новыми постами по любимым темам
781 открытий781 показов