Skip to main content
This guide covers development of Rust’s standard library ecosystem, including core, alloc, std, and related libraries.

Library Structure

The Rust standard library is organized into several layers:
1

core - The Foundation

The core library is the dependency-free foundation of Rust.Location: library/core/Features:
  • No dependencies (not even libc)
  • No heap allocation
  • No I/O
  • Platform-agnostic
  • Used in #![no_std] environments
2

alloc - Memory Management

The alloc library provides heap allocation primitives.Location: library/alloc/Features:
  • Requires a global allocator
  • Collections: Vec, String, Box, etc.
  • No I/O or OS dependencies
3

std - The Standard Library

The standard library builds on core and alloc.Location: library/std/Features:
  • OS interaction
  • I/O operations
  • Threading
  • File system
  • Networking

Library Directory Layout

library/
├── core/                  # Core library (no_std)
│   ├── src/
│   │   ├── lib.rs
│   │   ├── ptr/          # Pointer utilities
│   │   ├── slice/        # Slice operations
│   │   ├── str/          # String slice operations
│   │   └── ...
│   └── Cargo.toml
├── alloc/                 # Allocation and collections
│   ├── src/
│   │   ├── lib.rs
│   │   ├── vec/          # Vec implementation
│   │   ├── string.rs     # String type
│   │   ├── boxed.rs      # Box type
│   │   └── collections/  # HashMap, BTreeMap, etc.
│   └── Cargo.toml
├── std/                   # Standard library
│   ├── src/
│   │   ├── lib.rs
│   │   ├── fs/           # File system
│   │   ├── io/           # I/O traits and types
│   │   ├── net/          # Networking
│   │   ├── thread/       # Threading
│   │   └── ...
│   └── Cargo.toml
├── test/                  # Test framework
├── proc_macro/            # Procedural macros
├── panic_abort/           # Panic abort handler
├── panic_unwind/          # Panic unwinding
├── unwind/                # Stack unwinding
└── backtrace/             # Backtrace support

Setting Up for Library Development

1

Configure for library development

Create or modify config.toml:
profile = "library"

[llvm]
download-ci-llvm = true

[rust]
# Download pre-built compiler if working only on library
download-rustc = "if-unchanged"

# Build library with debug info
debuginfo-level-std = 1
2

Build the library

# Build just the standard library
./x.py build library/std

# Build core library
./x.py build library/core

# Build alloc library
./x.py build library/alloc
3

Test your changes

# Test standard library
./x.py test library/std

# Test core library
./x.py test library/core

# Test specific module
./x.py test library/std --test-args vec

Working with Core Library

Core Library Constraints

The core library has special restrictions:
The core library cannot:
  • Use heap allocation
  • Perform I/O operations
  • Access the file system
  • Use OS-specific features
  • Depend on external crates (except compiler intrinsics)

Example: Adding to Core

// library/core/src/slice/mod.rs

impl<T> [T] {
    /// Returns the first element of the slice.
    #[stable(feature = "slice_first", since = "1.0.0")]
    pub const fn first(&self) -> Option<&T> {
        if let [first, ..] = self {
            Some(first)
        } else {
            None
        }
    }
}

Working with Alloc Library

Memory Allocation Primitives

The alloc library provides heap-allocated types:
// library/alloc/src/vec/mod.rs

impl<T> Vec<T> {
    pub fn push(&mut self, value: T) {
        // Check if we need to grow the buffer
        if self.len == self.buf.capacity() {
            self.grow_amortized(self.len + 1);
        }
        unsafe {
            let end = self.as_mut_ptr().add(self.len);
            ptr::write(end, value);
            self.len += 1;
        }
    }
}

Working with Std Library

Platform-Specific Code

The std library contains platform-specific implementations:
// library/std/src/sys/pal/unix/fs.rs

#[cfg(unix)]
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
    let path = cstr(path)?;
    unsafe {
        let ptr = libc::opendir(path.as_ptr());
        if ptr.is_null() {
            Err(io::Error::last_os_error())
        } else {
            Ok(ReadDir { dirp: ptr, root: path })
        }
    }
}

Library Development Workflow

1

Make your changes

Edit the appropriate library file in library/core/, library/alloc/, or library/std/.
2

Add tests

/// Returns the first element.
///
/// # Examples
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v.first(), Some(&1));
/// ```
pub fn first(&self) -> Option<&T> {
    // implementation
}
3

Build and test

# Build the library
./x.py build library/std

# Run library tests
./x.py test library/std

# Run doc tests
./x.py test library/std --doc

# Test specific module
./x.py test library/std --test-args vec
4

Check all platforms

# Test on different platforms
./x.py test library/std --target x86_64-pc-windows-gnu
./x.py test library/std --target aarch64-apple-darwin

Library Features

Feature Flags in Std

The standard library uses feature flags for conditional compilation:
// library/std/Cargo.toml
[features]
backtrace = ["addr2line", "object", "miniz_oxide"]
panic-unwind = ["dep:panic_unwind"]
compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
Usage in code:
#[cfg(feature = "backtrace")]
pub mod backtrace;

#[cfg(not(feature = "backtrace"))]
pub mod backtrace {
    // Stub implementation
}

Stability Attributes

All public APIs must have stability attributes:
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_empty(&self) -> bool {
    self.len() == 0
}

Testing Libraries

Test Organization

library/
├── core/tests/         # Core library tests
│   ├── slice.rs
│   ├── iter.rs
│   └── ...
├── alloc/tests/        # Alloc library tests
│   ├── vec.rs
│   ├── string.rs
│   └── ...
└── std/tests/          # Std library tests
    ├── fs.rs
    ├── thread.rs
    └── ...

Running Library Tests

# All standard library tests
./x.py test library/std

# Specific test file
./x.py test library/std --test-args vec

# With output
./x.py test library/std -- --nocapture

Cross-Platform Development

Platform Abstraction Layers

The std library uses a Platform Abstraction Layer (PAL):
library/std/src/sys/pal/
├── unix/           # Unix-like systems
│   ├── linux/     # Linux-specific
│   ├── macos/     # macOS-specific
│   └── ...
├── windows/        # Windows
├── wasm/          # WebAssembly
└── unsupported/   # Unsupported platforms

Conditional Compilation

#[cfg(target_os = "linux")]
fn platform_specific() {
    // Linux implementation
}

#[cfg(target_os = "windows")]
fn platform_specific() {
    // Windows implementation
}

#[cfg(target_family = "unix")]
fn unix_specific() {
    // All Unix-like systems
}

Performance Considerations

Use #[inline]

#[inline]
pub fn len(&self) -> usize {
    self.len
}
Small functions benefit from inlining

Avoid Allocations

Use iterators and stack allocation when possible

Benchmarking

./x.py bench library/std

Size Optimization

Use optimize_for_size feature for embedded targets

Common Tasks

  1. Edit library/alloc/src/vec/mod.rs
  2. Add implementation with stability attributes
  3. Add doc tests with examples
  4. Add unit tests in library/alloc/tests/vec.rs
  5. Run ./x.py test library/alloc
  1. Edit library/std/src/fs.rs or platform-specific file
  2. Add regression test
  3. Test on multiple platforms
  4. Run ./x.py test library/std --test-args fs
  1. Edit library/core/src/slice/mod.rs
  2. Add benchmarks if needed
  3. Ensure no unsafe code bugs
  4. Test thoroughly with Miri: ./x.py test library/core --stage 0

Resources

Std Dev Guide

Standard library development guide

Library Team

Chat with the library team on Zulip

API Guidelines

Rust API design guidelines

Libs Tracking

Library issues on GitHub

Next Steps

Compiler Development

Learn about compiler development

Debugging

Debug library issues

Profiling

Profile library performance

Build docs developers (and LLMs) love