Thanks to visit codestin.com
Credit goes to lib.rs

#memory-allocator #linter #game-engine #static-analysis

app cargo-fa

Static analysis tool for framealloc - detect memory intent violations before runtime

9 releases (breaking)

new 0.11.1 Dec 26, 2025
0.11.0 Dec 23, 2025
0.10.0 Dec 23, 2025
0.9.0 Dec 23, 2025
0.5.1 Dec 21, 2025

#172 in Memory management

MIT/Apache

160KB
3.5K SLoC

cargo-fa

Static analysis for framealloc — catch memory intent violations before runtime

Crates.io Documentation License

InstallationUsageDiagnosticsCI Integration


Overview

cargo-fa is a static analysis tool for framealloc that detects memory intent violations at build time. It catches patterns that compile but violate frame allocation principles — issues that would otherwise only surface as performance problems or subtle bugs at runtime.

What It Catches

Category Examples
Lifetime Issues Frame allocations escaping scope, hot loop allocations
Async Safety Frame data crossing await points, closure captures
Threading Cross-thread frame access, missing thread-local init
Architecture Tag mismatches, unknown tags, module boundary violations
Budgets Unbounded allocation loops

Installation

cargo install cargo-fa

Or from source:

git clone https://github.com/YelenaTor/framealloc
cd framealloc/cargo-fa
cargo install --path .

Usage

Basic Checks

# Check specific categories
cargo fa --dirtymem       # Lifetime/escape issues (FA6xx)
cargo fa --async-safety   # Async/await issues (FA7xx)
cargo fa --threading      # Thread safety issues (FA2xx)
cargo fa --budgets        # Budget violations (FA3xx)
cargo fa --architecture   # Tag/module issues (FA8xx)

# Run all checks (optimized order)
cargo fa --all

Filtering

# Treat specific diagnostic as error
cargo fa --all --deny FA701

# Suppress specific diagnostic
cargo fa --all --allow FA602

# Exclude paths (glob pattern)
cargo fa --all --exclude "**/tests/**"

# Stop on first error
cargo fa --all --fail-fast

# Minimum severity threshold
cargo fa --all --min-severity warning

Output Formats

# Human-readable (default)
cargo fa --all

# JSON for programmatic consumption
cargo fa --all --format json

# SARIF for GitHub Actions
cargo fa --all --format sarif

# JUnit XML for test reporters
cargo fa --all --format junit

# Checkstyle XML for Jenkins
cargo fa --all --format checkstyle

# Compact one-line-per-issue
cargo fa --all --format compact

Subcommands

# Explain a diagnostic code in detail
cargo fa explain FA601

# Analyze a single file
cargo fa show src/physics.rs

# List all diagnostic codes
cargo fa list

# Filter by category
cargo fa list --category async

# Generate configuration file
cargo fa init

Diagnostics

Diagnostic Codes

Range Category Description
FA2xx Threading Cross-thread frame access, thread-local issues
FA3xx Budgets Unbounded allocations, missing budget guards
FA6xx Lifetime Frame escape, hot loops, missing boundaries
FA7xx Async Await crossing, closure capture, async functions
FA8xx Architecture Tag mismatch, unknown tags, module violations
FA9xx Rapier Physics engine integration issues (Rapier 0.31)

Example Output

error[FA701]: frame allocation in async function
  --> src/network/client.rs:45:12
   |
45 |     let buffer = alloc.frame_box(vec![0u8; 1024]);
   |            ^^^^^^ frame allocation here
   |
   = note: async functions can suspend across frame boundaries
   = help: use `alloc.heap_box()` or `alloc.pool_box()` instead

warning[FA602]: allocation in hot loop
  --> src/physics/collision.rs:128:16
   |
128|         let contact = alloc.pool_alloc::<Contact>();
   |                ^^^^^^ allocation inside loop
   |
   = note: loop may execute many times per frame
   = help: consider pre-allocating with `alloc.frame_vec()`

Getting Detailed Explanations

$ cargo fa explain FA701

━━━ FA701 ━━━

Name: async-frame
Category: Async Safety
Severity: error

Summary
Frame allocation in async function

Description
Async functions can suspend at await points. When they resume, they might
be on a different thread or at a different point in the frame lifecycle...

Example (incorrect)
async fn load_asset(alloc: &SmartAlloc) {
    let buffer = alloc.frame_box(vec![0u8; 1024]);  // FA701
    ...

Example (correct)
async fn load_asset(alloc: &SmartAlloc) {
    let buffer = alloc.heap_box(vec![0u8; 1024]);  // Safe
    ...

CI Integration

GitHub Actions (SARIF)

- name: Run cargo-fa
  run: cargo fa --all --format sarif > results.sarif

- name: Upload SARIF
  uses: github/codeql-action/upload-sarif@v2
  with:
    sarif_file: results.sarif

Jenkins (Checkstyle)

stage('Static Analysis') {
    sh 'cargo fa --all --format checkstyle > checkstyle.xml'
    recordIssues tools: [checkStyle(pattern: 'checkstyle.xml')]
}

Generic CI

# Exit with error on any issues
cargo fa --all --deny-warnings

# Exit with error only on specific codes
cargo fa --all --deny FA701 --deny FA702

Configuration

Create a .fa.toml in your project root:

cargo fa init

Example configuration:

[global]
enabled = true
exclude = ["target/**", "tests/**"]

[lints.FA601]
level = "warn"

[lints.FA701]
level = "deny"

[tags]
known = ["physics", "rendering", "audio", "network"]

[tags.modules]
"src/physics/**" = "physics"
"src/render/**" = "rendering"


License

Licensed under either of:

at your option.

Dependencies

~2–13MB
~112K SLoC