lang_items
The tracking issue for this feature is: None.
The rustc
compiler has certain pluggable operations, that is, functionality that isn't hard-coded into the language, but is implemented in libraries, with a special marker to tell the compiler it exists. The marker is the attribute #[lang = "..."]
and there are various different values of ...
, i.e. various different ‘lang items’. Most of them can only be defined once.
Lang items are loaded lazily by the compiler; e.g. if one never uses Box
then there is no need to define a function for exchange_malloc
. rustc
will emit an error when an item is needed but not found in the current crate or any that it depends on.
Some features provided by lang items:
==
, <
, dereferencing (*
) and +
(etc.) operators are all marked with lang items; those specific four are eq
, partial_ord
, deref
/deref_mut
, and add
respectively.panic
and panic_impl
lang items, among others.eh_personality
is a function used by the failure mechanisms of the compiler. This is often mapped to GCC‘s personality function (see the std
implementation for more information), but programs which don’t trigger a panic can be assured that this function is never called. Additionally, a eh_catch_typeinfo
static is needed for certain targets which implement Rust panics on top of C++ exceptions.core::marker
used to indicate types of various kinds; e.g. lang items sized
, sync
and copy
.Most lang items are defined by core
, but if you're trying to build an executable without the std
crate, you might run into the need for lang item definitions.
Box
Box
pointers require two lang items: one for the type itself and one for allocation. A freestanding program that uses the Box
sugar for dynamic allocations via malloc
and free
:
#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] #![allow(internal_features)] #![no_std] extern crate libc; extern crate unwind; use core::ffi::c_void; use core::intrinsics; use core::panic::PanicInfo; use core::ptr::NonNull; pub struct Global; // the global allocator struct Unique<T>(NonNull<T>); #[lang = "owned_box"] pub struct Box<T, A = Global>(Unique<T>, A); impl<T> Box<T> { pub fn new(x: T) -> Self { #[rustc_box] Box::new(x) } } impl<T, A> Drop for Box<T, A> { fn drop(&mut self) { unsafe { libc::free(self.0.0.as_ptr() as *mut c_void); } } } #[lang = "exchange_malloc"] unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { let p = libc::malloc(size) as *mut u8; // Check if `malloc` failed: if p.is_null() { intrinsics::abort(); } p } #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { let _x = Box::new(1); 0 } #[lang = "eh_personality"] fn rust_eh_personality() {} #[panic_handler] fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
Note the use of abort
: the exchange_malloc
lang item is assumed to return a valid pointer, and so needs to do the check internally.
An up-to-date list of all language items can be found here in the compiler code.