Элементы языка (lang items)
Замечание: многие элементы языка предоставляются контейнерами в стандартной поставке Rust, а у самих элементов языка нестабильный интерфейс. Рекомендуется использовать официально распространяемые контейнеры, вместо того, чтобы определять свои собственные элементы языка.
У компилятора rustc
есть некоторые подключаемые операции, т.е. функционал, не
встроенный жёстко в язык, а реализованный в библиотеках и специально помеченный
как элемент языка. Метка — это атрибут #[lang="..."]
. Есть различные значения
...
, т.е. разные «элементы языка».
Например, для указателей Box
нужны два элемента языка — для выделения памяти и
для освобождения. Вот программа, не использующая стандартную библиотеку, и
реализующая Box
через malloc
и free
:
#![feature(lang_items, box_syntax, start, no_std, libc)]
#![no_std]
extern crate libc;
extern {
fn abort() -> !;
}
#[lang = "owned_box"]
pub struct Box<T>(*mut T);
#[lang="exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
let p = libc::malloc(size as libc::size_t) as *mut u8;
// malloc завершился ошибкой
if p as usize == 0 {
abort();
}
p
}
#[lang="exchange_free"]
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
libc::free(ptr as *mut libc::c_void)
}
#[start]
fn main(argc: isize, argv: *const *const u8) -> isize {
let x = box 1;
0
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
Заметьте, что exchange_malloc
должен возвращать допустимый указатель, поэтому
он производит проверку внутри и делает abort
, если она не прошла.
Ниже перечислены другие возможности, предоставляемые элементами языка:
- перегружаемые операторы через типажи: типажи, соответствующие
==
,<
, разыменованию (*
),+
и другим операторам, помечены как элементы языка; конкретно эти типажи помечены какeq
,ord
,deref
иadd
; - раскрутка стека и общая ошибка; это элементы
eh_personality
,fail
иfail_bounds_check
; - типажи в модуле
std::marker
, используемые чтобы помечать различные типы; элементыsend
,sync
иcopy
; - типы-метки и индикаторы вариантности из
std::marker
; это элементыcovariant_type
,contravariant_lifetime
и другие.
Элементы языка загружаются компилятором лениво, т.е. если программа не
использует Box
, вам не нужно определять элементы exchange_malloc
и
exchange_free
. rustc
выдаст ошибку, если элемент языка необходим, но не
найден ни в текущем контейнере, ни в его зависимостях.