Атрибуты
Syntax
InnerAttribute → # ! [ Attr ]
OuterAttribute → # [ Attr ]
Attr →
SimplePath AttrInput?
| unsafe ( SimplePath AttrInput? )
Атрибут — это общие метаданные произвольной формы, которые интерпретируются в соответствии с именем, соглашениями, языком и версией компилятора. Атрибуты основаны на атрибутах из ECMA-335, а синтаксис заимствован из ECMA-334 (C#).
Внутренние атрибуты, записываемые с восклицательным знаком (!) после решётки (#), применяются к форме, внутри которой объявлен атрибут.
Example
#![allow(unused)] fn main() { // Общие метаданные, применяемые к окружающему модулю или крейту. #![crate_type = "lib"] // Внутренний атрибут применяется ко всей функции. fn some_unused_variables() { #![allow(unused_variables)] let x = (); let y = (); let z = (); } }
Внешние атрибуты, записываемые без восклицательного знака после решётки, применяются к форме, следующей за атрибутом.
Example
#![allow(unused)] fn main() { // Функция, помеченная как модульный тест #[test] fn test_foo() { /* ... */ } // Условно компилируемый модуль #[cfg(target_os = "linux")] mod bar { /* ... */ } // Атрибут для подавления предупреждения/ошибки #[allow(non_camel_case_types)] type int8_t = i8; }
Атрибут состоит из пути к атрибуту, за которым следует необязательное дерево токенов-разделителей, интерпретация которого определяется атрибутом. Атрибуты, отличные от атрибутов-макросов, также позволяют вводу быть знаком равенства (=), за которым следует выражение. Для получения более подробной информации см. синтаксис метаэлементов ниже.
Применение атрибута может быть небезопасным. Чтобы избежать неопределённого поведения при использовании этих атрибутов, должны быть выполнены определённые обязательства, которые компилятор не может проверить. Чтобы утверждать, что они выполнены, атрибут оборачивается в unsafe(..), например #[unsafe(no_mangle)].
Следующие атрибуты являются небезопасными:
Атрибуты можно классифицировать на следующие виды:
- Встроенные атрибуты
- Атрибуты-макросы процедур
- Вспомогательные атрибуты макросов-производных
- Инструментальные атрибуты
Атрибуты могут применяться ко многим формам в языке:
- Все объявления элементов принимают внешние атрибуты, в то время как внешние блоки, функции, реализации и модули принимают внутренние атрибуты.
- Большинство операторов принимают внешние атрибуты (см. Атрибуты выражений для ограничений на операторы выражений).
- Блочные выражения принимают внешние и внутренние атрибуты, но только когда они являются внешним выражением оператора выражения или конечным выражением другого блочного выражения.
- Варианты перечислений и поля структур и объединений принимают внешние атрибуты.
- Ветви выражений сопоставления принимают внешние атрибуты.
- Параметры обобщённого времени жизни или типа принимают внешние атрибуты.
- Выражения принимают внешние атрибуты в ограниченных ситуациях, см. Атрибуты выражений для подробностей.
- Параметры функций, замыканий и указателей на функции принимают внешние атрибуты. Это включает атрибуты на вариативных параметрах, обозначенных
...в указателях на функции и внешних блоках.
Синтаксис метаэлементов атрибутов
“Метаэлемент” — это синтаксис, используемый для правила Attr большинством встроенных атрибутов. Он имеет следующую грамматику:
Syntax
MetaItem →
SimplePath
| SimplePath = Expression
| SimplePath ( MetaSeq? )
MetaSeq →
MetaItemInner ( , MetaItemInner )* ,?
Expressions in meta items must macro Выражения в метаэлементах должны раскрываться в макросах в литеральные выражения, которые не должны включать суффиксы целочисленных или плавающих типов. Выражения, не являющиеся литеральными, будут синтаксически приняты (и могут быть переданы в процедурные макросы), но будут отклонены после разбора.
Обратите внимание, что если атрибут появляется внутри другого макроса, он будет раскрыт после этого внешнего макроса. Например, следующий код сначала раскроет процедурный макрос Serialize, который должен сохранить вызов include_str!, чтобы его можно было раскрыть:
#[derive(Serialize)]
struct Foo {
#[doc = include_str!("x.md")]
x: u32
}
Кроме того, макросы в атрибутах будут раскрыты только после всех других атрибутов, применённых к элементу:
#[macro_attr1] // раскрывается первым
#[doc = mac!()] // `mac!` раскрывается четвёртым.
#[macro_attr2] // раскрывается вторым
#[derive(MacroDerive1, MacroDerive2)] // раскрывается третьим
fn foo() {}
Различные встроенные атрибуты используют разные подмножества синтаксиса метаэлементов для указания своего ввода. Следующие правила грамматики показывают некоторые часто используемые формы:
Syntax
MetaWord →
IDENTIFIER
MetaNameValueStr →
IDENTIFIER = ( STRING_LITERAL | RAW_STRING_LITERAL )
MetaListPaths →
IDENTIFIER ( ( SimplePath ( , SimplePath )* ,? )? )
MetaListIdents →
IDENTIFIER ( ( IDENTIFIER ( , IDENTIFIER )* ,? )? )
MetaListNameValueStr →
IDENTIFIER ( ( MetaNameValueStr ( , MetaNameValueStr )* ,? )? )
Некоторые примеры метаэлементов:
| Стиль | Пример |
|---|---|
| MetaWord | no_std |
| MetaNameValueStr | doc = "example" |
| MetaListPaths | allow(unused, clippy::inline_always) |
| MetaListIdents | macro_use(foo, bar) |
| MetaListNameValueStr | link(name = "CoreFoundation", kind = "framework") |
Активные и инертные атрибуты
Атрибут является либо активным, либо инертным. Во время обработки атрибутов активные атрибуты удаляют себя из формы, на которой они находятся, в то время как инертные атрибуты остаются на ней.
Атрибуты cfg и cfg_attr являются активными.
Атрибуты-макросы процедур являются активными. Все остальные атрибуты являются инертными.
Инструментальные атрибуты
Компилятор может разрешать атрибуты для внешних инструментов, где каждый инструмент находится в своём собственном модуле в прелюдии инструментов. Первый сегмент пути атрибута — это имя инструмента, за которым следует один или несколько дополнительных сегментов, интерпретация которых зависит от инструмента.
Когда инструмент не используется, атрибуты инструмента принимаются без предупреждения. Когда инструмент используется, он отвечает за обработку и интерпретацию своих атрибутов.
Инструментальные атрибуты недоступны, если используется атрибут no_implicit_prelude.
#![allow(unused)] fn main() { // Указывает инструменту rustfmt не форматировать следующий элемент. #[rustfmt::skip] struct S { } // Управляет порогом "цикломатической сложности" для инструмента clippy. #[clippy::cyclomatic_complexity = "100"] pub fn f() {} }
Note
В настоящее время
rustcраспознаёт инструменты “clippy”, “rustfmt”, “diagnostic”, “miri” и “rust_analyzer”.
Указатель встроенных атрибутов
Ниже приведён указатель всех встроенных атрибутов.
-
Условная компиляция
-
Тестирование
test— Помечает функцию как тест.ignore— Отключает тестовую функцию.should_panic— Указывает, что тест должен вызывать панику.
-
Производные (Derive)
derive— Автоматические реализации трейтов.automatically_derived— Маркер для реализаций, созданныхderive.
-
Макросы
macro_export— Экспортирует макросmacro_rulesдля использования между крейтами.macro_use— Расширяет видимость макросов или импортирует макросы из других крейтов.proc_macro— Определяет функциональный макрос.proc_macro_derive— Определяет производный макрос.proc_macro_attribute— Определяет атрибут-макрос.
-
Диагностика
allow,expect,warn,deny,forbid— Изменяет уровень проверок по умолчанию.deprecated— Генерирует предупреждения об устаревании.must_use— Генерирует проверку для неиспользуемых значений.diagnostic::on_unimplemented— Подсказывает компилятору выдавать определённое сообщение об ошибке, если трейт не реализован.diagnostic::do_not_recommend— Подсказывает компилятору не показывать определённую реализацию трейта в сообщениях об ошибках.
-
ABI, компоновка, символы и FFI
link— Указывает собственную библиотеку для компоновки с блокомextern.link_name— Указывает имя символа для функций или статиков в блокеextern.link_ordinal— Указывает порядковый номер символа для функций или статиков в блокеextern.no_link— Предотвращает компоновку внешнего крейта.repr— Управляет размещением типа в памяти.crate_type— Указывает тип крейта (библиотека, исполняемый файл и т.д.).no_main— Отключает генерацию символаmain.export_name— Указывает экспортируемое имя символа для функции или статика.link_section— Указывает раздел объектного файла для функции или статика.no_mangle— Отключает кодирование имён символов.used— Принуждает компилятор сохранять статический элемент в выходном объектном файле.crate_name— Указывает имя крейта.
-
Генерация кода
inline— Подсказка для встраивания кода.cold— Подсказка, что функция вряд ли будет вызвана.naked— Запрещает компилятору генерировать пролог и эпилог функции.no_builtins— Отключает использование определённых встроенных функций.target_feature— Настраивает генерацию кода для конкретной платформы.track_caller— Передаёт местоположение родительского вызова вstd::panic::Location::caller().instruction_set— Указывает набор инструкций, используемый для генерации кода функции.
-
Документация
doc— Определяет документацию. См. Книгу Rustdoc для получения дополнительной информации. Doc-комментарии преобразуются в атрибутыdoc.
-
Прелюдии (Preludes)
no_std— Удаляет std из прелюдии.no_implicit_prelude— Отключает поиск в прелюдии внутри модуля.
-
Модули
path— Указывает имя файла для модуля.
-
Ограничения
recursion_limit— Устанавливает максимальный предел рекурсии для определённых операций во время компиляции.type_length_limit— Устанавливает максимальный размер полиморфного типа.
-
Время выполнения
panic_handler— Устанавливает функцию для обработки паник.global_allocator— Устанавливает глобальный распределитель памяти.windows_subsystem— Указывает подсистему Windows для компоновки.
-
Функциональные возможности (Features)
feature— Используется для включения нестабильных или экспериментальных функций компилятора. См. Нестабильную книгу для функций, реализованных вrustc.
-
Система типов
non_exhaustive— Указывает, что в будущем к типу будут добавлены поля/варианты.
-
Отладчик
debugger_visualizer— Встраивает файл, определяющий вывод отладчика для типа.collapse_debuginfo— Управляет тем, как вызовы макросов кодируются в отладочной информации.