cargo-memlense
Static analysis tool for memkit — detect memory issues before runtime.
Version: 0.1.0-alpha.1

Overview
cargo-memlense analyzes your Rust source code for patterns that compile but violate memkit best practices. Catch memory issues at build time, not at runtime.
Installation
cargo install cargo-memlense
Usage
# Check current directory for memkit issues
cargo memlense check
# Check specific file
cargo memlense check src/game.rs
# Check with specific rules or categories
cargo memlense check --rules ML103,ML601
cargo memlense check --rules ML6 # All async safety checks
# Explain a diagnostic code
cargo memlense explain ML602
# List all diagnostic codes
cargo memlense list
Diagnostic Categories
ML1xx: Frame Lifecycle Errors
| Code |
Severity |
Description |
ML101 |
error |
begin_frame without matching end_frame |
ML102 |
error |
end_frame without matching begin_frame |
ML103 |
error |
Frame allocation escapes frame scope |
ML104 |
error |
Frame allocation stored in long-lived struct |
ML105 |
warning |
Game loop without frame boundaries |
ML106 |
error |
Nested frame scopes detected |
ML2xx: Threading & Transfer Errors
| Code |
Severity |
Description |
ML201 |
error |
Frame data sent to another thread |
ML202 |
error |
Transfer handle used after completion |
ML203 |
warning |
Cross-thread allocation without explicit policy |
ML204 |
warning |
Potential data race on shared allocation |
ML3xx: GPU Memory Errors
| Code |
Severity |
Description |
ML301 |
warning |
Staging buffer not freed before frame end |
ML302 |
error |
GPU buffer accessed without synchronization |
ML303 |
error |
Device-local memory mapped for CPU access |
ML304 |
warning |
Transfer without memory barrier |
ML305 |
note |
Unnecessary staging buffer copy |
ML306 |
error |
Coordinator frame mismatch with allocator |
ML4xx: Performance Warnings
| Code |
Severity |
Description |
ML401 |
warning |
Allocation in hot loop |
ML402 |
note |
Heap allocation where frame allocation would suffice |
ML403 |
warning |
Allocation pattern may cause fragmentation |
ML404 |
note |
Allocation could use frame tier |
ML405 |
note |
Consider pre-allocating |
ML406 |
warning |
Large frame allocation (>1MB) |
ML5xx: Best Practice Hints
| Code |
Severity |
Description |
ML501 |
note |
Missing allocation intent/tag |
ML502 |
note |
Inconsistent tagging across module |
ML503 |
note |
Memory budget not configured |
ML504 |
note |
Consider using MkFastArena for hot path |
ML6xx: Async Safety
| Code |
Severity |
Description |
ML601 |
warning |
Frame allocation in async function |
ML602 |
error |
Frame allocation held across await point |
ML603 |
warning |
FrameBox captured by async closure |
ML604 |
note |
Async context without TaskAlloc |
ML7xx: Architecture & Intent
| Code |
Severity |
Description |
ML701 |
warning |
Tag mismatch across module boundaries |
ML702 |
note |
Unknown allocation tag |
ML703 |
warning |
Cross-module allocation without clear ownership |
ML704 |
warning |
Allocation intent doesn't match usage pattern |
Example: ML103 (Frame Escapes)
// BAD: Frame allocation used after frame ends
let ptr = alloc.frame_alloc::<u32>();
alloc.end_frame();
*ptr = 42; // ML103: use after frame end
// GOOD: Use allocation before frame ends
let ptr = alloc.frame_alloc::<u32>();
*ptr = 42;
alloc.end_frame();
Example: ML602 (Frame Across Await)
// BAD: Frame allocation held across await
let data = alloc.frame_box(value);
some_async_fn().await; // ML602: allocation invalid here
println!("{:?}", data);
// GOOD: Use memkit-async or heap
use memkit_async::MkAsyncFrameAlloc;
let data = async_alloc.alloc::<Data>().await;
some_async_fn().await;
println!("{:?}", data); // Safe!
License
This project is licensed under the Mozilla Public License 2.0 - see the LICENSE.md file for details.