Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Special pages
JOHNWICK
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
How Rust’s Target-Independent Core Works
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
There’s a moment every Rust developer has: You’re writing code for a tiny embedded board, or compiling to WebAssembly, or even booting Rust on bare metal… and you realize: “Wait. I have no OS, no allocator, no threads… So how the hell is Rust still working?” The answer is the core crate — Rust’s target-independent standard library. It is the smallest, most portable piece of the entire language, and honestly, one of the most beautiful pieces of software engineering in Rust. This article goes deep into: * How core works without an OS * How it avoids allocations * How formatting, slices, iterators, and results exist without std * How the compiler treats core specially * Why core is the foundation for embedded, WASM, and kernels * Architecture diagrams, code flows, internals, and real examples And yes — fully human-written, fully technical, and emotionally honest. Why core Even Exists Rust has three “layers” of libraries: core → alloc → std Think of them like this: * core — no OS, no heap, just pure language primitives. * alloc — adds heap-backed containers, uses an allocator. * std — adds OS features like threads, sockets, files. core is the only layer guaranteed to work everywhere, even here: ✔ A bootloader ✔ An STM32 microcontroller ✔ A browser running WebAssembly ✔ A custom kernel ✔ A GPU shader runtime ✔ A Raspberry Pi with no Linux Without core, Rust would be just a compiler classroom experiment. With core, Rust becomes a systems language. What’s Actually Inside core? Here’s the funny part: You use core every day — you just call it by other names. | Feature You Use | Actually Lives In | | ------------------------------------ | -------------------------- | | `Option<T>` | `core::option` | | `Result<T, E>` | `core::result` | | Iterators | `core::iter` | | `&[T]`, `&str` | `core::slice`, `core::str` | | Traits like `Copy`, `Clone`, `Sized` | `core::marker` | | Arithmetic ops | `core::ops` | | Pointers | `core::ptr` | | Panics | `core::panicking` | | `format_args!` | `core::fmt` | This is shocking the first time you see it. All these everyday tools don’t require an OS or heap. A Peek at core’s File Layout Here’s a simplified view of the internals: core/ ├── alloc/ (NOT heap allocation — core uses static alloc only) ├── array/ ├── char/ ├── cmp/ ├── convert/ ├── fmt/ <— formatting engine ├── future/ ├── hint/ ├── intrinsics/ <— compiler magic hooks ├── iter/ ├── mem/ ├── num/ ├── ops/ ├── option/ ├── panic/ ├── ptr/ ├── result/ ├── slice/ └── str/ Every part is designed to work with: * no OS * no heap * no system calls * no global allocator * no threads * no I/O This is what makes core the “portable soul” of Rust. How core Works Without Allocation Let’s take something we all use: let s = [1, 2, 3]; s.iter().map(|x| x + 1); How does .map() exist without allocation? Because iterators are lazy, and laziness costs zero memory. This is core’s philosophy: “Provide tools that need no heap, only the stack.” Example: core::iter::Map is just: pub struct Map<I, F> { iter: I, f: F, } That’s it. Just two fields on the stack. When you do: let x = arr.iter().map(|x| x + 1); No memory allocated. No data created. You’ve just built a little struct with two fields. How core Handles Formatting Without I/O println! lives in std — it needs I/O. But format_args! lives in core. Wait — formatting with no printing? Here’s what’s happening: format_args!("hi {}", 5) Expands to something like: Arguments { pieces: &["hi ", ""], args: &[5], } It’s just a structured description of formatting. core doesn't print anything. It just builds an IR (intermediate representation). Why? Because the compiler uses it for: * panic messages * formatting inside alloc::format! * debug derives * errors inside no-std environments Zero I/O. Zero heap. Zero runtime. How core’s Intrinsics Work (Compiler Magic) Deep inside core::intrinsics are functions that only the compiler can call, for example: fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); These become LLVM instructions: memcpy memmove abort unreachable Example: Rust’s slice indexing is implemented using intrinsics: #[inline] pub unsafe fn get_unchecked(&self, index: usize) -> &T { &*self.as_ptr().add(index) } And LLVM turns this into a real pointer math operation, even on WASM or embedded. How core Provides Panic Support Without std You might think panics need: * strings * stdout * printing * unwinding But core provides the minimal interface: #[panic_handler] fn panic(_info: &PanicInfo) -> ! { loop {} } This is why in embedded Rust you often see: #[panic_handler] fn panic(_info: &PanicInfo) -> ! { cortex_m::asm::bkpt(); loop {} } core doesn’t care what the panic does. It just provides the structure (PanicInfo). The platform decides what to do. Architecture of core (ASCII Diagram) ┌──────────────────────────┐ │ rustc │ └─────────────┬────────────┘ │ ▼ ┌────────────────────────────────────┐ │ core crate │ │────────────────────────────────────│ │ primitives: Option, Result │ │ pointer types │ │ slices, str, iterators │ │ no heap, no OS │ └─────────────────┬──────────────────┘ │ ┌──────────────────┼─────────────────┐ ▼ ▼ ▼ embedded targets wasm32-unknown custom kernels Real Example: Option<T> Implementation in core You use it daily. Here’s how insanely simple it really is: pub enum Option<T> { None, Some(T), } But the magic is in zero-cost optimizations. For example, Option<&T> is stored in one pointer: * None is represented as null * Some(ptr) is literally the pointer No overhead. No extra bytes. No runtime work. Rust’s niche optimizations are implemented directly inside core. Real Example: &str in core &str is two fields: pub struct Str { ptr: *const u8, len: usize, } String indexing, slicing, and UTF-8 validation all live inside core. And the compiler inlines almost everything: let s = "hello"; let h = &s[0..1]; // core::str::slice_error checks In optimized builds, Rust removes slice checks when it can prove safety. How core Enables no_std Ecosystems Embedded Rust is possible because core gives developers: * iter * Option, Result * pointer APIs * formatting IR * numeric traits * cell types * slices & byte manipulation You can write a complete I2C driver, RTOS, or microkernel using only: #![no_std] That line means: use core; not use std; Everything still works — because core is all Rust really needs. Code Flow: How Your Rust Program Uses core Here’s the surprising truth: Even when you use std, your program internally depends on core. your code ↓ std (uses alloc) ↓ alloc (uses core) ↓ core (depends only on compiler) ↓ rustc/LLVM ↓ machine code core is the only crate that rustc treats as a language primitive. Everything else — even std — is just a library. Why core Matters for the Future of Rust The world is moving toward: * WASM without JavaScript * tiny IoT hardware * edge compute * unikernels * WASI-as-the-new-OS * Rust inside firmware + bootloaders All of these require a language that can work with: * No malloc * No threads * No filesystem * No OS Most languages simply cannot operate in that world. Rust can — because core exists. core is the “Rust DNA”: The minimal blueprint needed to express ownership, slices, pointers, traits, and control flow anywhere. Final Thoughts (Human, Emotional) The core crate is one of the most beautiful parts of Rust. It represents the language distilled to its pure form — no OS, no fancy runtime, no threading model, no heap. Just the essence: * predictable memory * zero-cost abstractions * safe pointers * move semantics * powerful algebraic types When you look at core, you’re not just looking at Rust’s internals. You’re looking at what makes Rust portable, safe, and honestly, timeless. Every blinking LED on an STM32 board, every WASM module sent to a browser, every bootloader written in Rust — they all owe their existence to the quiet brilliance of the core crate. It’s the foundation nobody sees, but everyone relies on. And that’s the kind of engineering that deserves respect.
Summary:
Please note that all contributions to JOHNWICK may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
JOHNWICK:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Search
Search
Editing
How Rust’s Target-Independent Core Works
Add topic