Состоялся релиз языка системного программирования Rust 1.30, развиваемого проектом Mozilla. Язык сфокусирован на безопасной работе с памятью, обеспечивает автоматическое управление памятью и предоставляет средства для достижения высокого параллелизма выполнения заданий, при этом обходясь без использования сборщика мусора и runtime.
Автоматическое управление памятью в Rust избавляет разработчика от манипулирования указателями и защищает от проблем, возникающих из-за низкоуровневой работы с памятью, таких как обращение к области памяти после её освобождения, разыменование нулевых указателей, выход за границы буфера и т.п. Для распространения библиотек, обеспечения сборки и управления зависимостями проектом развивается пакетный менеджер Cargo, позволяющий получить нужные для программы библиотеки в один клик. Для размещения библиотек поддерживается репозиторий crates.io.
В подготовке нового выпуска приняли участие 178 разработчиков. Основные новшества:
- Добавлена поддержка двух новых видов процедурных макросов: макросы похожие на атрибуты и макросы похожие на функции. Атрибутоподобные макросы напоминают ранее доступные произвольные макросы на базе механизма «derive», но кроме генерации кода только для атрибута «#[derive]» позволяют создавать собственные произвольные атрибуты, а также не ограничены работой только со структурами и перечислениями (enums). Макросы похожие на функции дают возможность определить макрос в форме вызова функции (например, «let sql = sql!(SELECT * FROM posts WHERE id=1);»).
- Добавлена возможность выноса макроса в текущую область видимости (scope) по аналогии функциями при помощи ключевого слова «use», без использования специальной аннотации «#[macro_use]»;
- Стабилизирован пакет (crate) proc_macro, предоставляющий API для упрощения создания макросов. В proc_macro также значительно расширен API для обработки ошибок, который уже задействован в пакетах подобных syn и quote;
- Началась работа по упрощению системы создания модулей. Добавлена возможность использования ключевого слова «crate» в пути для отсылки к корню иерархии модулей, например, «crate::foo» ссылается на модуль «foo», размещённый в «src/lib.rs». При использовании внешних пакетов отныне не требуется указание префикса «::», например, вместо «json = ::serde_json::from_str(foo);» теперь можно писать «let json = serde_json::from_str(foo);». Логика разбора пути «a::b::c» выглядит следующим образом: если «a» является именем пакета, то в этом пакете осуществляется поиск «b::c»; если в «a» указано ключевое слово «crate», то поиск «b::c» осуществляется относительно корня иерархии модулей; иначе
«a::b::c» извлекается из текущей позиции в иерархии модулей; - Добавлена возможность использования ключевых слов в качестве идентификаторов. Например, для создания локальной переменной с именем «for» можно указать «let r#for = true;», а для создания функции с именем «for» — «fn r#for() {«. При вызове подобной функции следует использовать признак raw-идентификатора — «r#for();»;
- Добавлен атрибут «#[panic_handler]», предоставляющий возможность определения функции для обработки сбоев (panic) в Rust runtime. Подобное может оказаться полезным для сборки приложения без стандартной библиотеки, используя режим no_std;
- Реализована возможность определения в макросах видимости ключевых слов, таких как «pub», используя спецификатор «vis»;
- Стабилизированы атрибуты для инструментов Rust, таких как rustfmt и clippy. Например, «#[rustfmt::skip]» может применяться отключения форматирования следующего элемента;
- В разряд стабильных переведена новая порция API, в том числе
Ipv4Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}, Ipv6Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}, Iterator::find_map;
- Из-за неверной трактовки в функциях «trim_*» понятий «лево» и «право» для RTL-языков, данные функции переименованы: trim_left в trim_start, trim_right в trim_end, trim_left_matches в trim_start_matches, trim_right_matches в trim_end_matches;
- В пакетный менеджер Cargo добавлен индикатор прогресса выполнения операций.