core, alloc, and std
Purpose and Scope
Rust library APIs are organized as a stack rather than as one flat crate. At the bottom, the core library defines the dependency-free foundation that is available even when a program has no operating system, allocator, or I/O support. The alloc library adds heap allocation, owned containers, and shared ownership types for environments that can provide an allocator but still do not link the full standard library. The std library sits at the top and is what ordinary Rust crates use by default, combining portable abstractions with platform integration such as I/O and multithreading. Sources: library/core/src/lib.rs, library/alloc/src/lib.rs, library/std/src/lib.rs
This layering matters whenever a developer chooses between normal Rust, embedded Rust, kernels, bootloaders, WebAssembly targets, or other constrained platforms. A default application usually writes imports through std and receives the prelude, primitives, collections, strings, synchronization, file system access, and process facilities through the normal distribution. A no standard library crate makes a more explicit choice: it may rely only on core, or it may add alloc if the target supplies a global allocator. The repository crate roots document these boundaries directly, which makes them the best starting point for understanding what each layer promises.
Relevant Source Files
- library/Cargo.toml - Defines the library workspace members used for the standard library build, including std, sysroot, coretests, and alloctests, plus standard-library-specific profile and patch settings.
- library/core/src/lib.rs - Crate root and crate-level documentation for the Rust Core Library, including its dependency-free role, platform-agnostic constraints, required symbols, panic handler expectations, and lint policy.
- library/alloc/src/lib.rs - Crate root and crate-level documentation for heap allocation, smart pointers, collections, allocator interfaces, no_std use, and the fact that std normally re-exports its contents.
- library/std/src/lib.rs - Crate root and crate-level documentation for the Rust Standard Library, including the default availability of std, the documentation tour, primitive documentation notes, modules, macros, prelude, I/O, and multithreading.
Layered Model
The core crate is described in its own crate documentation as the portable glue between the language and its libraries. It defines intrinsic and primitive building blocks of all Rust code and explicitly links to no upstream libraries, no system libraries, and no libc. That statement is stronger than simply saying core is small: it explains why core can be used on targets where there is no operating system service to call. The crate root also marks the crate with no core, because core is the bottom of this particular stack rather than a crate implemented on top of another Rust library layer. Sources: library/core/src/lib.rs
Core intentionally does not know about heap allocation, concurrency, or input and output. Those capabilities require either platform integration, an allocator, or both, so they are outside the responsibility of a platform-agnostic foundation. The documentation also records a small set of assumptions that consumers of core must satisfy, including memory routines such as copying and setting bytes, a panic handler that never returns, and an exception personality symbol used by compiler failure mechanisms. These requirements are important for no standard library users because omitting std does not mean omitting every runtime obligation; it means taking ownership of the pieces std would normally arrange. Sources: library/core/src/lib.rs
The alloc crate is the middle layer. Its crate documentation says it provides smart pointers and collections for managing heap-allocated values. That includes boxed values, reference counted pointers, atomically reference counted pointers, collections, and the low-level interface to the default global allocator. The crate is marked no standard library and needs an allocator, which captures the design boundary precisely: alloc does not require the full standard library, but it cannot operate in a completely allocation-free environment either. For many embedded or runtime projects, adding alloc is the point where owned growable data structures become available. Sources: library/alloc/src/lib.rs
The std crate is the upper layer and the user-facing default. Its documentation calls the Rust Standard Library the foundation of portable Rust software and lists core types, primitive operations, standard macros, I/O, and multithreading among its responsibilities. The std crate is available to all Rust crates by default, which is why most examples import through std without enabling anything special. It also provides the main documentation surface that new and experienced developers browse, with sections for modules, primitive types, macros, and the Rust prelude. Sources: library/std/src/lib.rs
System-to-Code Mapping
The relationship can be read as a set of dependency and re-export boundaries. Core defines the most fundamental APIs and language-adjacent operations. Alloc builds on core concepts while adding heap-backed ownership and collections. Std then presents the commonly used distribution API, including platform-backed services, and re-exports many items that users might otherwise find in alloc or core. The alloc documentation states that its contents normally do not need to be used directly because they are re-exported in std, while the std documentation tells users that std is the default path for standard library access. Sources: library/alloc/src/lib.rs, library/std/src/lib.rs
The library workspace manifest gives the build-system view of this arrangement. The workspace under the library directory includes std, sysroot, coretests, and alloctests. It also contains profile choices for building standard-library components, such as using many code generation units for compiler builtins to reduce symbol clashes, reducing debug information for backtrace-related dependencies, forcing panic abort behavior for panic_abort, and defining a dist profile used by bootstrap for prebuilt standard library artifacts. These settings show that the layered API model is also a distribution artifact with special build requirements. Sources: library/Cargo.toml
A practical mental model is to ask what the target can support. If the target only supports the language primitives and whatever symbols the final image provides, core is the appropriate layer. If the target can provide a global allocator but not an operating system, alloc unlocks common owned data structures without pulling in file handles, process management, or networking. If the target has the normal platform services expected by Rust’s tiered distributions, std is the ergonomic default. This question is often more useful than asking which crate contains a particular type, because std deliberately gathers and re-exports APIs for everyday use.
API Components
Core is where developers should expect primitive-adjacent APIs, marker traits, option and result types, pointer and memory operations, formatting foundations, cell and reference primitives, and other minimal abstractions that do not require allocation or platform services. The crate documentation emphasizes minimality, not lack of importance. Many APIs that feel like ordinary Rust are rooted in this layer because every Rust program needs a common vocabulary for values, references, comparison, iteration, panics, and compiler-facing operations. When authoring portable libraries, choosing core-compatible APIs can make the difference between supporting embedded consumers and forcing a dependency on the full standard library.
Alloc adds the APIs that need heap storage. The crate documentation names Box as the single-owner smart pointer for heap values, Rc as the non-threadsafe reference-counted pointer for sharing within a thread, and Arc as the threadsafe counterpart that can be sent when the contained value is shareable. It also houses general-purpose collections and the allocator module. Because std re-exports these APIs, application authors often see them under std paths, while no standard library authors may import them through alloc after arranging the allocator required by the crate root. Sources: library/alloc/src/lib.rs
Std adds operating-system-facing and platform-integrated capabilities while presenting the most familiar entry point. Its crate documentation highlights I/O and multithreading alongside portable abstractions, and it explains that primitive methods are documented in the standard library even though primitive types are implemented by the compiler. That distinction is useful when navigating generated API documentation: there can be a primitive type page and a module with a similar name, but the methods that can be called directly on the primitive are documented with the primitive. Sources: library/std/src/lib.rs
Implementation Details and Edge Cases
The most important edge case is that no standard library does not automatically mean no runtime requirements. Core’s crate root lists symbols that may be expected, including memory routines generated by Rust code generation backends or provided by compiler builtins or a platform C library. It also describes the panic handler requirement and the exception personality symbol used by failure mechanisms. Developers building firmware, kernels, or freestanding targets need to treat these details as part of the integration contract, because the compiler and core library still need well-defined behavior for operations such as copying memory and handling panics. Sources: library/core/src/lib.rs
A second edge case is allocation. The alloc crate gives access to powerful data structures, but the crate-level attributes and documentation make clear that it needs an allocator. That means a project can be no standard library and still use heap-backed containers, but only after the target supplies allocation infrastructure. This is why alloc occupies a middle position rather than being folded into core. Core is suitable for allocation-free environments; alloc is suitable for environments that can provide heap management; std is suitable when the target also supports the broader platform services that Rust exposes by default. Sources: library/alloc/src/lib.rs
Documentation navigation can also create confusion. The public standard library documentation encourages users to browse modules, primitive types, macros, and the prelude, and it explicitly points readers to source links. The repository mirrors that reader-facing intent in the std crate root by embedding the documentation tour in source. When looking for a method on String or Vec, remember that many calls are actually methods on str or slice reached by deref coercions. That is not merely documentation trivia; it reflects the layered design where owned types, borrowed views, and primitive operations are documented together in the standard library surface. Sources: library/std/src/lib.rs
Practical Guidance
For everyday libraries and binaries, start with std unless there is a concrete reason not to. This is the path that Rust crates receive by default, and it provides the broadest compatibility with examples, documentation, Cargo defaults, testing tools, and common ecosystem crates. For reusable libraries that want to support constrained consumers, consider whether the public API can be expressed in terms of core plus optional alloc features. A library that avoids I/O and thread APIs may be able to serve both standard and no standard library users by keeping its foundation small and enabling allocation only where necessary.
For no standard library work, decide early whether the crate is core-only or core plus alloc. A core-only crate should avoid heap-backed collections and should not assume platform services. A core plus alloc crate can expose owned buffers, reference-counted data, boxed values, and common collections, but the final program or target support layer must still provide allocation. When debugging build failures, separate language and library questions from integration questions: a missing panic handler, allocator, or memory routine is not the same kind of problem as an unavailable collection type.
Next Steps
Read the standard library overview next if you want a broad tour of the modules and documentation conventions exposed through std. Read the embedded and no standard library page if your main concern is constrained targets, allocator setup, or freestanding integration. For low-level APIs, the pointer APIs and provenance page is the natural companion because many core-level operations are intentionally explicit about addresses, references, and memory behavior. If you are contributing to Rust itself, keep the library workspace manifest in view because API layering and distribution profiles are maintained together in this repository. Sources: library/Cargo.toml, library/core/src/lib.rs, library/alloc/src/lib.rs, library/std/src/lib.rs