#[no_builtins]Attribute
Explanation
#![no_builtins] is an inner attribute placed at the top of a crate root
that disables the compiler's freedom to silently substitute certain code
patterns with calls to builtin/intrinsic implementations — typically
memory-related routines like memcpy, memset, and memmove that LLVM
recognizes and can lower a plain loop or a [T]-copying operation into
automatically, on the assumption that a C-runtime-compatible
implementation of those symbols will be available at link time.
In ordinary hosted Rust, those symbols always exist — they come from the
platform's C runtime (libc) that's already linked in — so this
substitution is invisible and harmless; it's simply a codegen
optimization. In a freestanding or kernel context, where there is no C
runtime and no guarantee those symbols exist at all, that same
substitution becomes a linker error or, worse, a silent jump to whatever
symbol happens to occupy that name if one was defined incidentally.
#![no_builtins] tells the compiler not to perform this substitution, so
the crate's own code is the only thing that can introduce a dependency on
memcpy-like symbols — and if it does need them, it (or a compiler_builtins-style
crate) must provide its own implementations explicitly.
This is a narrow, kernel/freestanding-specific attribute: it matters only
to code that cannot assume any runtime support functions exist, which
in practice means operating-system kernels and similarly deep
bare-metal/freestanding crates — most #![no_std] embedded application
code sits on top of a runtime crate that already handles this and never
needs to reach for #![no_builtins] itself.
Usage examples
Disabling implicit libc-builtin substitution
#![no_std]
#![no_builtins] // <- forbids the compiler from silently assuming a libc-provided memcpy/memset exist
Designing a public API
A minimal kernel crate provides its own low-level memory primitives
rather than linking against any C runtime — #![no_builtins] guarantees
the compiler never quietly assumes a memcpy symbol will show up from
somewhere else.
#![no_std]
#![no_builtins] // <- this kernel supplies its own memory routines; nothing may assume libc's exist
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
let mut i = 0;
while i < n {
unsafe {
// SAFETY: caller guarantees `dest` and `src` are valid for `n`
// bytes and don't overlap, per the standard memcpy contract.
*dest.add(i) = *src.add(i);
}
i += 1;
}
dest
}
Without #![no_builtins], the compiler may still lower
some Rust code into a call to memcpy even though this crate defines its
own — in an environment with no C runtime, an unexpected implicit call
to a symbol nothing provides is a link failure at best; the
rustc book
and kernel-development guides (e.g. the
Writing an OS in Rust series)
document #![no_builtins] as part of the freestanding-binary checklist
alongside #![no_std].