|
libmemalloc 0.0.0-alpha
The Magic of Memory Transmutation
|
Use this standard to implement and review Rust libraries, applications, allocator bindings and platform adapters. It defines local requirements for code, API design, unsafe boundaries, resources, security and performance. The pitfalls catalogue explains failure mechanisms and regression designs. The architecture guide defines crates, dependency direction and release boundaries. These three documents contain the Rust requirements and explanations needed for review.
Must and imperative rules are requirements. Should identifies a default that needs a recorded reason when changed. May grants permission. A review trigger asks the owner to assess a design; it does not establish a defect by itself. Each RUST-*, RPERF-*, RBAN-* and RMOD-* identifier is stable. RPIT-* entries explain failures without adding hidden requirements.
Record deviations with the rule ID, affected paths and configurations, reason, risk, compensating checks, owner, reviewer, evidence and expiry or review condition. A lint suppression is only one part of that record. A soundness defect cannot receive a deviation that makes undefined behavior acceptable.
| Class | Meaning and evidence |
|---|---|
| PROJECT_STYLE | Readability and presentation; rustfmt and review. |
| CORRECTNESS | Required outputs, state transitions and failure behavior; contract tests. |
| SOUNDNESS | Safe callers cannot trigger undefined behavior through the abstraction; invariant review and tools. |
| SECURITY | Authority, input, secrets and dependency trust; threat-specific checks. |
| PORTABILITY | Compiler, target, ABI and configuration assumptions; build and execution matrix. |
| ARCHITECTURE | Ownership and dependency boundaries; graph, API and integration review. |
| VERIFICATION | Scope and reproducibility of evidence; retained results and limitations. |
| PERFORMANCE | Measured cost under a defined workload; reference comparison and resource limits. |
Language and library contracts constrain implementation. Product requirements select applicable profiles; this standard supplies project rules within those constraints. External guides provide technical context. The rules here are deliberate project choices, not a claim that Rust, Clippy or any cited organization mandates the entire policy. Compliance with coding rules does not establish product certification.
Select a named combination before claiming conformance:
| Profile | Required decisions |
|---|---|
| BASE | Edition, MSRV, pinned compiler, rustfmt, Clippy, targets, features and panic strategy. |
| HOSTED | std, filesystem/process/network authority, threads, logging and shutdown. |
| CORE | #![no_std], target support, panic handler owner and permitted language/library subset. |
| ALLOC | alloc, allocator owner, fallible growth and allocation budgets; can accompany CORE. |
| UNSAFE/FFI | Reviewed invariant boundary, ABI, allocator pairing, callbacks and unwind policy. |
| ASYNC | Executor, blocking rules, cancellation, task supervision and backpressure. |
| REALTIME/DEVICE | Interrupts, DMA, MMIO, bounded latency/stack, residency and platform evidence. |
| CRITICAL | Hazard-derived requirements, restricted subset, qualified tools and traceable verification. |
MSRV means minimum supported Rust version. Edition and compiler version are separate: select edition 2024 for new crates when their approved MSRV permits it; retain older editions until a tested migration. Use rust-version in Cargo metadata and test it. An edition migration does not select native library versions, CPU features or a stable binary interface. See the Edition Guide.
At authoring, this checkout has no tracked Cargo workspace, Rust toolchain policy or Rust CI runner. These documents specify a policy to apply when Rust code is introduced. Cargo commands below are recipes for that workspace, not existing repository gates. The example validation record identifies the compiler used for documentation examples.
Keep a machine-readable profile record with target triples, feature sets, linker and native dependencies, panic, overflow checks, optimization, LTO, CPU features, allocator, execution environment and tool versions. Do not infer a no_std, no-allocation or real-time claim from a successful desktop build.
A safe API must preserve memory safety for every safe caller, including callers that panic, forget values, provide unusual valid inputs or implement safe traits incorrectly. An unsafe fn transfers documented obligations to its caller. An unsafe block discharges particular obligations inside an implementation. Soundness review includes safe code that maintains those obligations. Memory safety does not establish logical correctness, confidentiality, authorization, bounded memory or freedom from deadlocks. See the Reference's undefined-behavior discussion and Fuchsia unsafe review guidance.
The following defaults are detailed in RUST-061–084. They supply reviewable source-style rules alongside the safety, API and implementation controls.
| Topic | Project default | Detailed controls |
|---|---|---|
| Names | Rust casing by construct; domain vocabulary, visible units and ownership semantics. | RUST-061–RUST-068 |
| Rust line width | 100 columns including indentation; local exceptions for indivisible content. | RUST-069 |
| Rust prose comments | Aim for 80 characters from the marker, within 100 columns including indentation. | RUST-069, RUST-080 |
| Indentation and spaces | Four spaces per level; rustfmt owns mechanical spacing and continuation layout. | RUST-070 |
| Blank lines | One between logical stages and distinct definitions; none inside an operation/check pair. | RUST-071–RUST-073 |
| Long expressions | Wrap at syntax boundaries; use meaningful intermediate names when needed. | RUST-074–RUST-077 |
| Imports and source order | Group by origin; keep contract, related definitions and tests easy to locate. | RUST-078, RUST-083 |
| Markdown prose | 120 columns under repository lint policy; table and URL exceptions follow that policy. | This overview |
Use the selected toolchain's rustfmt and stable configuration. Record the language edition and formatting style edition; changes to either deserve a dedicated formatting review. Use four-space indentation and the formatter's default width of 100 unless the repository later adopts an explicit Rust configuration. Do not copy whitespace rules from another language or maintain manual operator-alignment tables. The Rust Style Guide explains the canonical layout.
Organize a file as crate/module documentation, imports, constants and types, implementations, private helpers, and local tests where that order helps navigation. Keep mutually relevant types and implementations near each other. Put one blank line between logical stages; keep an operation and its error propagation together. Place /// documentation and attributes beside the item. Keep // SAFETY: beside the unsafe operation it justifies. Let rustfmt handle braces, continuation lines, spaces and trailing commas.
Use snake_case for modules, functions, methods, variables and Rust source filenames; UpperCamelCase for types and traits; SCREAMING_SNAKE_CASE for constants and statics. Use meaningful units such as _bytes, _count or a typed Duration. Prefer affirmative predicates such as is_empty and has_capacity. Use new for construction, try_new for a fallible constructor when it distinguishes an existing convention, as_* for cheap borrowed views, to_* for conversion that generally creates a value, and into_* for consuming conversion. Explain resource acquisition in the contract: new does not by itself promise no allocation. See the API Guidelines checklist for API naming and common trait conventions.
For one operation, validate(input)?; keeps propagation beside the call. A later cleanup obligation belongs in an owning guard or explicit transaction, not in a distant return label. Use early returns and ? when they clarify rejection paths. Review drop order and observable partial effects at each exit.
Comments explain invariants, why a constraint exists and which measurement supports an optimization. Remove commented-out production code. Track unfinished work with an owner and issue; state the missing behavior and its acceptance condition. Keep diagnostics searchable and redact secrets from Debug, Display and error chains. Avoid editor modelines, invisible directional controls and confusable identifiers in project-owned names. Strings that intentionally contain such characters need an explicit test and explanation.
Use UTF-8 and LF. Markdown prose stays within 120 columns, with tables and URLs under the repository lint policy. Owned Markdown ends with a blank line, <!-- EOF -->, then a final blank line. For future Rust files, use // EOF and keep any terminal-empty-line exception in a formatter adapter; do not add rustfmt::skip to hide unrelated differences. The current EOF checker has no Rust-specific extension entry.
Unless a rule names a narrower profile, it applies to BASE and all extensions. Each rule's verification paragraph states the minimum review or test obligation. Profile-specific deviations use the governance record.
Class: PROJECT_STYLE. Obligation: project requirement.
Run cargo fmt --all -- --check with the pinned formatter. Review blank-line grouping, comment placement and readable decomposition separately; formatting cannot identify transactions. Do not suppress formatting to preserve personal spacing. Verify generated sources with their generator policy.
Rationale: Consistent formatting keeps review attention on changed behavior.
Verification design: Check the formatter diff and inspect changed logical groups. Source: Rust Style Guide.
Contextual Rust example:
let used_bytes = header_bytes + payload_bytes;
Noncompliant fragment or claim (do not copy):
let used_bytes=header_bytes+payload_bytes;
Class: VERIFICATION. Obligation: project requirement.
Use the compiler-matched Clippy with -D warnings in required CI configurations. Review correctness, suspicious, complexity and performance findings; select pedantic and restriction lints individually rather than enabling contradictory restrictions. Prefer scoped #[expect(lint, reason = "...")] when supported and an occurrence is expected. Review unfulfilled expectations; generated code may need a narrow documented allow. Never suppress a warning instead of fixing unsound code.
Rationale: A narrow exception remains attributable and can become stale without hiding other warnings.
Verification design: Record lint ID, reason and affected configurations. Sources: Clippy CI, Microsoft universal guidelines.
Contextual Rust example:
#[expect(clippy::unused_async, reason = "trait requires an async operation")]
async fn ready(&self) {}
Noncompliant fragment or claim (do not copy):
#![allow(warnings)]
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE/FFI.
Put // SAFETY: immediately before unsafe operations and unsafe impls. Explain the origin of alignment, initialized extent, lifetime, aliasing and synchronization facts that matter there. Repeating “the pointer is valid” is insufficient. An unsafe function's # Safety section specifies caller obligations; the local comment explains how the implementation meets the called operation's contract.
Rationale: The reviewer needs evidence for the particular operation, not a restatement of its precondition.
Verification design: Trace every stated fact to a type, check or maintained invariant. Sources: std safety comments, Linux Rust coding guidelines.
Contextual Rust example:
// SAFETY: index is below the initialized slice length, checked above;
// the immutable borrow prevents mutation throughout this access.
let byte = unsafe { *bytes.get_unchecked(index) };
Noncompliant fragment or claim (do not copy):
// SAFETY: This should be fine.
let byte = unsafe { *bytes.get_unchecked(index) };
Class: CORRECTNESS. Obligation: project requirement.
Document inputs, outputs, units, ownership, mutation, allocation, blocking and thread requirements. Add # Errors, # Panics and # Safety where applicable, with an executable example for nontrivial APIs. Include partial progress, cancellation and cleanup behavior when they matter.
Rationale: Consumers need to distinguish returned failure from mutation, panic and resource costs.
Verification design: Build rustdoc with warnings denied and test examples. Source: rustdoc tests.
Related pitfalls: RPIT-038, RPIT-050.
Contextual Rust example:
/// Appends bytes without changing the buffer on error. /// /// # Errors /// Returns Limit if the new length exceeds the configured budget. pub fn try_append(&mut self, bytes: &[u8]) -> Result<(), AppendError>;
Noncompliant fragment or claim (do not copy):
/// Appends bytes. pub fn try_append(&mut self, bytes: &[u8]) -> Result<(), AppendError>;
Class: CORRECTNESS. Obligation: project requirement.
Return errors for invalid external input, capacity exhaustion and expected I/O failures. Document intentional panics and the boundary's unwind or abort behavior. debug_assert! cannot enforce a precondition needed to prevent undefined behavior in optimized builds. Library code must not install a global panic hook or terminate the process as routine error handling.
Rationale: Expected rejection is part of the interface and must remain recoverable under the selected profile.
Verification design: Test rejection in debug and release; inspect panic reachability at FFI and critical boundaries.
Related pitfalls: RPIT-014.
Contextual Rust example:
let size = text.parse::<usize>().map_err(ParseError::Size)?;
Noncompliant fragment or claim (do not copy):
let size = text.parse::<usize>().expect("user supplied a number");
Class: CORRECTNESS. Obligation: project requirement.
Use domain error enums in libraries and preserve causal information at adapters. Applications may add operation context for diagnostics. Use Option for legitimate absence, not for losing a failure cause. Propagate with ?; convert deliberately at the abstraction owner. Mark custom result-like types #[must_use] when ignoring them violates their purpose.
Rationale: Preserving the failure category lets the owning layer decide whether to retry or report it.
Verification design: Exercise each error variant and inspect ignored results, .ok() and wildcard error mappings.
Contextual Rust example:
let payload = read_payload().map_err(LoadError::Read)?;
Noncompliant fragment or claim (do not copy):
let payload = read_payload().ok();
Class: CORRECTNESS. Obligation: project requirement.
Production unwrap or expect requires a nearby proof that the failure state cannot occur under the function's contract. Prefer matching or type-level construction when the proof is brittle. A comment claiming valid user input is not a proof. Tests may use expect to state fixture assumptions; a failed fixture must remain visible.
Rationale: An unchecked assumption becomes fragile when its establishing condition is distant or external.
Verification design: Inspect each occurrence, including generated macros, and test the boundary that establishes the fact.
Contextual Rust example:
let first = values.first().ok_or(InputError::Empty)?;
Noncompliant fragment or claim (do not copy):
let first = values.first().unwrap();
Class: SOUNDNESS / ARCHITECTURE. Obligation: project requirement.
Borrow for temporary access, move for transfer, and return owners for newly acquired resources. Tie borrowed outputs to the actual owner. Avoid fabricated 'static lifetimes and raw pointers used to bypass a borrow conflict. Document who can mutate shared views and when handles become invalid.
Rationale: The type signature should constrain the actual owner lifetime instead of relying on caller discipline.
Verification design: Add compile-fail tests for forbidden lifetime escapes; exercise success and failure transfers.
Related pitfalls: RPIT-001, RPIT-023, RPIT-048.
Contextual Rust example:
fn payload(packet: &Packet) -> &[u8] {
&packet.bytes
}
Noncompliant fragment or claim (do not copy):
fn payload(packet: &Packet) -> &'static [u8] {
unsafe { std::mem::transmute(packet.bytes.as_slice()) }
}
Class: PERFORMANCE / CORRECTNESS. Obligation: project requirement.
Borrow or move when no independent copy is required. Keep a clone when it expresses needed ownership or simplifies a cold path within budget; explain expensive hot-path copies. Arc::clone shares the allocation and updates a reference count; it does not deep-copy the value.
Rationale: A copy changes cost and ownership; both should be intentional.
Verification design: Check ownership intent and measure allocation/copy counts in the production workload. Source: Performance Book: heap allocations.
Related pitfalls: RPIT-001, RPIT-022, RPIT-047.
Contextual Rust example:
inspect(payload.as_slice());
Noncompliant fragment or claim (do not copy):
inspect(payload.clone().as_slice());
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE/FFI.
Keep unsafe blocks small enough to audit and use #![deny(unsafe_op_in_unsafe_fn)] in unsafe-owning crates. Use #![forbid(unsafe_code)] in safe cores when feasible. Audit safe constructors, setters, trait implementations and destructors that maintain the unsafe invariant too. A tiny unsafe block does not compensate for an unchecked safe setter.
Rationale: Safe methods can invalidate an unsafe operation even if they contain no unsafe block.
Verification design: Enumerate unsafe sites and invariant-maintaining methods. Source: Fuchsia guidance.
Related pitfalls: RPIT-023, RPIT-024, RPIT-044.
Contextual Rust example:
pub fn set_len(&mut self, len: usize) -> Result<(), BoundsError> {
if len > self.initialized {
return Err(BoundsError);
}
self.len = len;
Ok(())
}
Noncompliant fragment or claim (do not copy):
pub fn set_len(&mut self, len: usize) {
self.len = len; // Used later by unchecked reads.
}
Class: PORTABILITY / SOUNDNESS. Obligation: project requirement.
Profile: FFI.
Use the matching extern calling convention and reviewed ABI-safe fields. Keep String, Vec, Rust references and trait objects out of a portable C interface. Prefer opaque handles or explicit pointer/length records with matching destroy functions. repr(C) on an outer type does not repair an incompatible field. Edition 2024 requires unsafe extern blocks and unsafe attributes where specified, such as #[unsafe(no_mangle)]; document symbol uniqueness and link obligations.
Rationale: Both sides must agree on representation and call behavior before exchanging a value.
Verification design: Compile and run a foreign-language caller on each ABI. Sources: FFI, type layout.
Related pitfalls: RPIT-012, RPIT-013.
Contextual Rust example:
#[repr(C)]
pub struct ByteView {
pub data: *const u8,
pub len: usize,
}
Noncompliant fragment or claim (do not copy):
#[repr(C)]
pub struct ByteView {
pub bytes: Vec<u8>,
}
Class: CORRECTNESS / PORTABILITY. Obligation: project requirement.
Use TryFrom for rejectable narrowing and signedness conversions. An as cast needs a demonstrated range or an explicit bit-level truncation contract. Bound lengths before conversion to usize; usize follows the target pointer width and is not a wire-format integer.
Rationale: Checking the original value is ineffective if a later cast changes its meaning.
Verification design: Test negative values, extrema and targets with different widths. See RPIT-007.
Related pitfalls: RPIT-007.
Contextual Rust example:
let count = usize::try_from(wire_count).map_err(|_| DecodeError::Length)?;
Noncompliant fragment or claim (do not copy):
let count = wire_count as usize;
Class: ARCHITECTURE. Obligation: project requirement.
Keep fields private when constructors maintain invariants. Use accessors or borrowed views, deliberate #[non_exhaustive] enums and sealed traits only when extension policy needs them. Do not promise stable Rust layout or ABI by exposing implementation types. Review auto traits and generic bounds as part of API compatibility.
Rationale: Private representation lets the owner change implementation while keeping consumer contracts stable.
Verification design: Build an external consumer and compare the previous release's API. Source: Cargo SemVer.
Contextual Rust example:
pub struct Buffer {
bytes: Vec<u8>,
}
Noncompliant fragment or claim (do not copy):
pub struct Buffer {
pub bytes: Vec<u8>, // Callers can bypass the length budget.
}
Class: SOUNDNESS / ARCHITECTURE. Obligation: project requirement.
Choose Cell, RefCell, locks or atomics from the sharing contract. RefCell checks borrows at runtime and does not provide cross-thread synchronization. Keep guards short; use fallible borrow methods when contention is an expected domain condition. A custom UnsafeCell wrapper must establish aliasing and synchronization invariants for its entire API.
Rationale: Interior mutability moves enforcement into a runtime or synchronization protocol that needs review.
Verification design: Test reentry and overlapping borrow attempts; review why ordinary &mut access is insufficient.
Related pitfalls: RPIT-006, RPIT-033.
Contextual Rust example:
let mut state = self.state.try_borrow_mut().map_err(|_| Error::Busy)?; state.update();
Noncompliant fragment or claim (do not copy):
let mut state = self.state.borrow_mut(); callback(self); // Can attempt another mutable borrow.
Class: ARCHITECTURE / SOUNDNESS. Obligation: project requirement.
Pass state through owners. A justified shared singleton needs an initialization, synchronization, reset and shutdown contract. Prefer an appropriate once-initialization primitive to manual publication. static mut requires a narrow platform/unsafe deviation and an aliasing proof.
Rationale: Hidden singleton state couples callers and tests through initialization and mutation order.
Verification design: Run isolated and concurrent tests; ensure test order does not establish hidden initialization.
Contextual Rust example:
pub struct Service {
config: Config,
}
Noncompliant fragment or claim (do not copy):
static mut CONFIG: Option<Config> = None;
Class: STYLE / CORRECTNESS. Obligation: project requirement.
Keep each function responsible for one transition or computation. Declare locals near first use, minimize mut, and use exhaustive match when new enum variants require design work. Early returns, ?, break and iterator combinators are allowed when effects and cleanup remain visible. Review functions above complexity 10, measured cognitive complexity 15 or five parameters; name the metric and counting convention. These are project review thresholds, not compiler limits.
Rationale: Short rejection paths reduce nesting while ownership guards retain cleanup responsibilities.
Verification design: Trace success, early error and cleanup paths; use a parameter type when arguments form a real concept.
Contextual Rust example:
let header = parse_header(input)?;
if header.is_empty() {
return Err(Error::Empty);
}
process(header)
Noncompliant fragment or claim (do not copy):
parse_header(input).ok().map(|header| process(header));
Class: ARCHITECTURE. Obligation: project requirement.
Review source files above 1,000 physical lines and dedicated public-contract modules above 500 lines for cohesion. There is no universal function-line cap. Keep imports explicit outside narrow preludes and test modules. Split crates when ownership, reuse or build isolation warrants the cost.
Rationale: Splitting by responsibility keeps reviewable boundaries without scattering one state machine.
Verification design: Record the owner and decision for large modules; reject arbitrary splits that scatter one invariant. Context: rust-analyzer style.
Contextual Rust example:
mod decode;
mod encode;
pub use decode::{DecodeError, Decoder};
Noncompliant fragment or claim (do not copy):
pub mod internals; pub use internals::*;
Class: CORRECTNESS / SOUNDNESS. Obligation: project requirement.
Use newtypes for distinct units and validated domains. Keep construction checked and fields private; audit derives, Default, deserialization and conversion paths. Implement Eq, Ord and Hash consistently. Safe traits cannot impose hidden memory-safety obligations on implementors; use an unsafe trait only when its documented contract genuinely requires them.
Rationale: A newtype protects a domain only when every creation and mutation path preserves its invariant.
Verification design: Exercise every constructor and implementation path, not just new.
Related pitfalls: RPIT-024, RPIT-032.
Contextual Rust example:
pub struct Port(u16);
impl TryFrom<u16> for Port {
type Error = InvalidPort;
fn try_from(value: u16) -> Result<Self, Self::Error> {
if value == 0 {
return Err(InvalidPort);
}
Ok(Self(value))
}
}
Noncompliant fragment or claim (do not copy):
pub struct Port(pub u16); // Supposedly guarantees nonzero values.
Class: ARCHITECTURE / PERFORMANCE. Obligation: project requirement.
Use generics for useful compile-time variation and trait objects for needed runtime substitution. Prefer concrete internal signatures when polymorphism adds no value. Public impl AsRef<_> can improve ergonomics but creates more instantiations; measure compile time and code size. Builders suit optional configuration; typestate suits important legal transitions, without encoding every runtime fact in a type parameter.
Rationale: Polymorphism should express actual substitution needs rather than multiply equivalent implementations.
Verification design: Review call sites, extension needs and representative builds. Context: rust-analyzer style.
Related pitfalls: RPIT-022.
Contextual Rust example:
fn checksum(bytes: &[u8]) -> u32 {
checksum_core(bytes)
}
Noncompliant fragment or claim (do not copy):
fn checksum<T: AsRef<[u8]> + Clone>(bytes: T) -> u32 {
checksum_core(bytes.clone().as_ref())
}
Class: CORRECTNESS. Obligation: project requirement.
Use checked arithmetic for sizes, offsets and counts; use wrapping or saturating operations only when those semantics belong to the contract. Check zero divisors, signed minimum divided by minus one and shift counts. Do not depend on debug/release overflow differences. Keep logical and bitwise operations distinct and validate external enum tags before constructing enum values.
Rationale: Overflow semantics are part of the domain and must survive changes of build profile.
Verification design: Test overflow boundaries and release behavior; compare arithmetic to an independent model.
Related pitfalls: RPIT-007, RPIT-009, RPIT-021.
Contextual Rust example:
let bytes = count.checked_mul(item_size).ok_or(Error::Size)?;
Noncompliant fragment or claim (do not copy):
let bytes = count * item_size; // Assumes the debug overflow check is sufficient.
Class: CORRECTNESS / PORTABILITY. Obligation: project requirement.
State whether NaN, infinities, signed zero and subnormals are accepted. Specify comparison tolerances, ordering and reproducibility requirements. Do not use floating point for allocator sizes. Changing reduction order, fused operations or target instructions needs numeric evidence.
Rationale: Exceptional floating-point values and reordering can change decisions without causing a memory error.
Verification design: Include exceptional values and cancellation-sensitive inputs; record compiler and target flags.
Contextual Rust example:
if !sample.is_finite() {
return Err(Error::NonFinite);
}
Noncompliant fragment or claim (do not copy):
if sample == f64::NAN {
return Err(Error::NonFinite);
}
Class: CORRECTNESS / SECURITY. Obligation: project requirement.
Use &[u8] for arbitrary bytes, &str for validated UTF-8 and Path/OsStr for platform paths. String indices are byte offsets and must lie on character boundaries. Define normalization and case rules at the protocol owner; do not silently replace invalid bytes when identity matters.
Rationale: Encoding and path identity need explicit types at the boundary.
Verification design: Test multibyte text, embedded NUL, invalid UTF-8 and non-Unicode paths where the OS supports them.
Contextual Rust example:
let text = std::str::from_utf8(bytes).map_err(Error::Encoding)?;
Noncompliant fragment or claim (do not copy):
let text = String::from_utf8_lossy(bytes); // Used as a unique identity.
Class: PORTABILITY / SECURITY. Obligation: project requirement.
Specify length limits, endianness, version, tags and error handling. Do not serialize a Rust object by reading its raw bytes: padding, pointers and layout are not a protocol. Decode unaligned input from bytes or reviewed unaligned operations without creating an invalid reference.
Rationale: Object storage can contain layout details and uninitialized padding that do not belong on the wire.
Verification design: Use golden vectors, truncated input and cross-endian models. Source: type layout.
Related pitfalls: RPIT-012, RPIT-030.
Contextual Rust example:
let encoded = counter.to_le_bytes();
Noncompliant fragment or claim (do not copy):
let encoded: [u8; 8] = unsafe { std::mem::transmute(record) };
Class: SOUNDNESS. Obligation: project requirement.
Profile: ALLOC/UNSAFE.
Check Layout construction, size arithmetic, alignment and zero-size policy. Pair allocation and deallocation APIs, including layout and allocator identity. Reallocation invalidates old locations according to its API contract. Box::from_raw and Vec::from_raw_parts require their exact ownership and allocation contracts; a pointer obtained from another allocator is not sufficient.
Rationale: Raw allocation APIs erase ownership information that must be recovered from the exact producer contract.
Verification design: Test failure, growth, zero-sized types and cross-boundary destruction.
Related pitfalls: RPIT-026, RPIT-027.
Contextual Rust example:
let layout = std::alloc::Layout::array::<Entry>(count).map_err(Error::Layout)?;
Noncompliant fragment or claim (do not copy):
let bytes = count * std::mem::size_of::<Entry>();
Class: CORRECTNESS / SECURITY. Obligation: project requirement.
Profile: ALLOC.
Enforce byte and element budgets before growth. Use try_reserve or an approved fallible container where exhaustion must become Result. A fallible outer operation cannot promise complete OOM recovery if formatting, error construction or another dependency allocates infallibly. No-allocation profiles cover hidden paths, logging and destructors as well as the main loop.
Rationale: An error-returning signature does not make every operation inside it fallible on allocation failure.
Verification design: Inject allocation failures without invoking UB; check unchanged state and allocation counts.
Related pitfalls: RPIT-002, RPIT-022, RPIT-025, RPIT-040.
Contextual Rust example:
buffer
.try_reserve(payload.len())
.map_err(Error::Allocation)?;
buffer.extend_from_slice(payload);
Noncompliant fragment or claim (do not copy):
buffer.extend_from_slice(payload); Ok(()) // Claimed to recover from allocation failure.
Class: SOUNDNESS / CORRECTNESS. Obligation: project requirement.
Drop performs best-effort nonpanicking cleanup; expose finish, flush or close when callers need a recoverable completion error. Specify ownership after a failed finalization. Do not make memory safety depend on destructors running: safe callers may use mem::forget, and abort or process termination can bypass cleanup. Avoid double release during partial construction or unwinding.
Rationale: Destruction can be skipped, and fallible external completion needs an observable result.
Verification design: Test partial initialization, repeated logical close and primary-error preservation.
Related pitfalls: RPIT-005, RPIT-016, RPIT-029, RPIT-048.
Contextual Rust example:
writer.finish()?; // Explicitly observes durable-completion errors.
Noncompliant fragment or claim (do not copy):
drop(writer); // Assumes Drop reported every flush failure.
Class: CORRECTNESS. Obligation: project requirement.
Profile: stricter REALTIME/CRITICAL.
Bound input nesting, recursion depth, queue size, retries, retained diagnostics and task counts. Large arrays and recursive destructors can exhaust a thread stack. Async futures retain locals across suspension and may become large even before execution.
Rationale: Bounds on admitted work need to include stack growth and retained asynchronous state.
Verification design: Measure configured thread stacks/future sizes, test maximum admitted work and inspect failure paths.
Related pitfalls: RPIT-025.
Contextual Rust example:
if depth >= limits.max_depth {
return Err(ParseError::Depth);
}
Noncompliant fragment or claim (do not copy):
parse_nested(input, depth + 1)?; // No nesting limit.
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE.
Preserve allocation origin when deriving pointers. Use pointer APIs whose contracts match the operation; an address integer alone does not demonstrate access rights. Keep arithmetic inside the required allocation and range, and avoid dereferencing one-past-end pointers. Shared references restrict mutation except through appropriate interior mutability. Recheck validity after calls that can reallocate, release or reenter.
Rationale: Pointer derivation must preserve the allocation and access rights required by the operation.
Verification design: Review derivation and lifetime chains; exercise the abstraction under Miri. Source: pointer APIs.
Related pitfalls: RPIT-008, RPIT-026.
Contextual Rust example:
let view = bytes.get(offset..end).ok_or(Error::Bounds)?;
Noncompliant fragment or claim (do not copy):
let ptr = saved_address as *const Entry;
let entry = unsafe { &*ptr }; // No retained allocation.
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE/FFI.
Before creating a reference or slice, establish non-nullness, alignment, initialized extent, a live allocation and legal aliasing for the whole lifetime. NonNull rules out zero; it does not prove those other properties. For an FFI convention permitting (null, 0), handle zero length before calling slice::from_raw_parts. A null check cannot validate an arbitrary foreign address.
Rationale: Constructing a reference already asserts its validity; validation after construction is too late.
Verification design: Test only inputs permitted by the unsafe contract; use safe boundary checks for rejectable values. Sources: raw slices, NonNull.
Related pitfalls: RPIT-011, RPIT-024, RPIT-028, RPIT-030.
Contextual Rust example:
if len == 0 {
return Ok(&[]);
}
// Nonempty input continues through the documented unsafe contract.
Noncompliant fragment or claim (do not copy):
let bytes = unsafe { std::slice::from_raw_parts(ptr, len) };
if ptr.is_null() { return Err(Error::Null); }
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE.
Use MaybeUninit<T> for storage that may not yet contain a valid T. Do not create &T, read a value or call assume_init before proving full initialization. For partial arrays, track the initialized prefix and drop exactly those elements on error. A zero byte pattern is not valid for all types. Keep ManuallyDrop and union active-member state under the same owner.
Rationale: Initialization tracking prevents both premature reads and incorrect cleanup of partial objects.
Verification design: Inject a failure after each initialization step and count drops. Source: MaybeUninit.
Related pitfalls: RPIT-010, RPIT-029.
Contextual Rust example:
let mut slot = std::mem::MaybeUninit::<String>::uninit();
slot.write(String::from("ready"));
Noncompliant fragment or claim (do not copy):
let value: String = unsafe { std::mem::zeroed() };
Class: SOUNDNESS. Obligation: project requirement.
Use constructors, byte conversion functions and checked casts first. A justified transmute needs size, validity, lifetime, provenance and representation proofs; equal size alone is insufficient. Do not read uninitialized padding or extend a borrow's lifetime to evade the checker. Union reads need proof that the chosen field's value is valid.
Rationale: A byte-size coincidence does not establish the destination type validity or its lifetime.
Verification design: Enumerate legal bit patterns and target assumptions; review the safe alternative explicitly.
Related pitfalls: RPIT-009.
Contextual Rust example:
let code = Code::try_from(raw_code)?;
Noncompliant fragment or claim (do not copy):
let code: Code = unsafe { std::mem::transmute(raw_code) };
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE/ASYNC.
Pin constrains movement of pinned pointees according to Unpin and the abstraction's contract; it does not freeze arbitrary data. Review structural pinning, projections, replacement, Drop and any manual Unpin implementation together. Prefer reviewed projection mechanisms to unchecked projection code. Self-references need an actual storage and lifetime design.
Rationale: Pinning obligations extend to field access and destruction, not just initial construction.
Verification design: Inspect every path that can move or invalidate pinned fields. Source: Pin.
Related pitfalls: RPIT-017.
Contextual Rust example:
let future = Box::pin(operation());
Noncompliant fragment or claim (do not copy):
let moved = unsafe { std::ptr::read(pinned.as_ref().get_ref()) };
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE.
Send concerns ownership transfer between threads; Sync concerns sharing references between threads. A raw pointer field and a mutex elsewhere do not automatically justify either. Account for thread-affine resources, destructors, callbacks, generic bounds and reachable interior state.
Rationale: Transfer and sharing proofs must account for the resource and its destructor, not only the wrapper fields.
Verification design: State the proof beside each unsafe impl and test concurrent lifecycle behavior. Source: Send and Sync.
Related pitfalls: RPIT-015, RPIT-033.
Contextual review example:
// Keep a thread-affine handle in its owning thread; send request values // through a bounded channel to that owner.
Noncompliant fragment or claim (do not copy):
unsafe impl Send for ThreadAffineHandle {}
Class: SOUNDNESS. Obligation: project requirement.
Profile: FFI.
Document whether each argument is borrowed, consumed or retained, on both success and failure. Pair returned owners with the matching release operation. Callback contracts include calling thread, retention, reentry, errors and shutdown. Unregister and drain in-flight callbacks before freeing context; keeping an Arc somewhere does not prove the native callback retains it correctly.
Rationale: Native retention must keep the right context alive through the last possible callback.
Verification design: Test acquisition failures, callback races and teardown with a native harness. Source: FFI.
Related pitfalls: RPIT-027.
Contextual Rust example:
registration.stop_new_calls(); registration.unregister()?; registration.drain()?; drop(context);
Noncompliant fragment or claim (do not copy):
drop(context); registration.unregister()?;
Class: SOUNDNESS / CORRECTNESS. Obligation: project requirement.
Profile: FFI.
Select a non-unwinding ABI or a deliberately supported unwind ABI. Prevent Rust panics escaping boundaries whose contract forbids them; catch_unwind catches unwinding panics, not aborts, arbitrary foreign exceptions or memory corruption. Do not use it to resume a broken invariant. Foreign longjmp must not bypass Rust frames that require destruction.
Rationale: The unwind policy must describe what the actual compiled binary does at the foreign boundary.
Verification design: Test the chosen panic strategy in a subprocess and document failure mapping. Source: FFI.
Related pitfalls: RPIT-014.
Contextual Rust example:
match operation() {
Ok(value) => encode_success(value),
Err(error) => encode_error(error),
}
Noncompliant fragment or claim (do not copy):
extern "C" fn entry() {
panic!("recoverable request failure");
}
Class: CORRECTNESS. Obligation: project requirement.
Profile: HOSTED/ASYNC.
Name a lock order, keep critical sections bounded and avoid calling unknown code while holding a lock. Treat poisoning as a signal to inspect protected invariants; neither ignoring nor unconditionally panicking on it is a universal recovery policy. Poisoning is advisory and cannot underpin unsafe soundness. Condition-variable waits recheck a predicate in a loop.
Rationale: Lock order and reentry determine progress; memory-safe locking can still deadlock.
Verification design: Test reentry, opposite acquisition orders and panics during mutation. Source: Mutex.
Related pitfalls: RPIT-004, RPIT-019.
Contextual Rust example:
{
let mut state = self.state.lock().map_err(Error::Poisoned)?;
state.prepare();
}
callback();
Noncompliant fragment or claim (do not copy):
let mut state = self.state.lock().unwrap(); callback(); // May try to lock self.state again.
Class: CORRECTNESS. Obligation: project requirement.
Profile: ASYNC.
Release blocking mutex guards before .await, preferably with a lexical scope that produces owned work. If an async mutex must span suspension, document why exclusive access must persist, which operations can wait and how cancellation restores state. Do not choose a mutex solely to satisfy a Send error. Move blocking I/O or CPU work to an appropriate bounded execution facility.
Rationale: Suspension can prevent the task needed to release a blocking lock from being scheduled.
Verification design: Test on a constrained executor with competing tasks. Source: Tokio shared state.
Related pitfalls: RPIT-003.
Contextual Rust example:
let request = {
let state = shared.lock().map_err(Error::Poisoned)?;
state.make_request()
};
send(request).await?;
Noncompliant fragment or claim (do not copy):
let state = shared.lock().unwrap(); send(state.request()).await?;
Class: CORRECTNESS. Obligation: project requirement.
Profile: ASYNC.
Dropping a future can stop it between suspension points. Define partial progress, resource ownership and retry behavior for each such point. In select!-style races, verify cancellation safety of each operation; losing a race can discard an in-progress read or write. Keep progress in an owner that survives cancellation when needed. Drop cannot perform ordinary awaited cleanup.
Rationale: Cancellation is an observable exit and may leave external progress behind.
Verification design: Cancel at each suspension boundary and inspect persisted effects. Source: Tokio select.
Related pitfalls: RPIT-018.
Contextual Rust example:
state.sent += write_some(&payload[state.sent..]).await?;
Noncompliant fragment or claim (do not copy):
write_all(payload).await?; // Retry policy assumes an error means zero bytes sent.
Class: CORRECTNESS / ARCHITECTURE. Obligation: project requirement.
The creator owns completion or transfers supervision explicitly. Specify stop, drain, join and error collection; dropping a task handle is not universally task cancellation. Bound channels and define full, closed and slow-consumer behavior. Prevent strong-reference cycles between workers, callbacks and owners; use Weak or an explicit breakable ownership edge when appropriate.
Rationale: An unobserved worker can outlive the state and shutdown assumptions of its creator.
Verification design: Test receiver loss, worker panic, full queues and shutdown with active users.
Related pitfalls: RPIT-005.
Contextual Rust example:
stop.send(()).map_err(Error::Stop)?; worker.join().map_err(Error::Worker)?;
Noncompliant fragment or claim (do not copy):
std::thread::spawn(move || use_resource(resource)); // No lifecycle owner.
Class: SOUNDNESS / CORRECTNESS. Obligation: project requirement.
Profile: UNSAFE/concurrent profiles.
Describe publication, observation and reclamation as one protocol. Justify each ordering and the read-modify-write success/failure pair. Relaxed can suit an independent counter, but does not publish unrelated data. SeqCst does not repair a lifetime or logical race. Use the weakest ordering established by the proof, not the weakest ordering that passed a stress run.
Rationale: Atomicity of one field does not publish the other state or keep its allocation alive.
Verification design: Model interleavings and run stress tests on relevant architectures. Sources: atomic ordering, Atomics and Locks: memory ordering.
Related pitfalls: RPIT-020, RPIT-033.
Contextual Rust example:
// The payload owner and access protocol establish non-atomic validity. ready.store(true, std::sync::atomic::Ordering::Release);
Noncompliant fragment or claim (do not copy):
ready.store(true, std::sync::atomic::Ordering::Relaxed); // Publishes payload.
Class: SOUNDNESS. Obligation: project requirement.
Profile: UNSAFE/concurrent profiles.
A pointer load does not keep its allocation alive. Use a reviewed retention, epoch, hazard-pointer or ownership-transfer protocol for shared objects. Address reuse can cause ABA. One-time initialization must publish the complete value before readers observe readiness. Define whether retries are bounded and whether the operation is lock-free, wait-free or merely nonblocking.
Rationale: Reclamation must wait for permitted readers, including those between acquisition steps.
Verification design: Model destruction concurrent with acquisition and test allocator reuse; state the progress guarantee.
Related pitfalls: RPIT-008, RPIT-020, RPIT-034.
Contextual Rust example:
let retained = registry.acquire(id)?; inspect(retained.as_ref());
Noncompliant fragment or claim (do not copy):
let ptr = shared.load(Ordering::Acquire);
unsafe { inspect(&*ptr) }; // Another thread may free the pointee.
Class: SOUNDNESS / PORTABILITY. Obligation: project requirement.
Profile: DEVICE.
Use volatile access only under the peripheral's register contract; it is not thread synchronization. Account for read-clear/write-one-to-clear bits, access width, alignment, barriers and reserved bits. DMA needs an ownership handoff and target-specific cache maintenance. Assembly must declare operands, clobbers, memory/stack effects and supported targets.
Rationale: Devices and assembly obey machine contracts outside ordinary borrow checking.
Verification design: Review device documentation, generated instructions and hardware tests. Source: volatile reads.
Contextual Rust example:
// Device-specific adapter owns access width, barriers and register semantics. device.acknowledge_interrupt(pending);
Noncompliant fragment or claim (do not copy):
*register_ptr = pending; // Assumes ordinary memory semantics for MMIO.
Class: PORTABILITY / CORRECTNESS. Obligation: project requirement.
Profile: CORE/REALTIME.
no_std removes the implicit standard-library dependency; it does not prove absence of allocation, locks or panics. Separate optional alloc support. State panic and interrupt policies, stack and WCET assumptions, target atomic support, blocking bounds and priority inversion controls. A watchdog update follows verified progress, not unconditional loop execution.
Rationale: A core profile needs explicit resource and termination limits beyond absence of std.
Verification design: Build without default features for the real target; retain stack, timing and hardware evidence. Context: Embedded Rust Book.
Related pitfalls: RPIT-040.
Contextual Rust example:
#![no_std] // Dependencies and target build separately establish the no-allocation profile.
Noncompliant fragment or claim (do not copy):
#![no_std] extern crate alloc; // Claimed as proof that this crate cannot allocate.
Class: SECURITY / ARCHITECTURE. Obligation: project requirement.
Profile: HOSTED.
Libraries do not own process exit, current directory, environment mutation, standard streams, signal policy or process-wide hooks. An adapter must justify inherited descriptors and handles. After fork in a multithreaded process, use only operations permitted by the platform until exec; Rust abstractions may hide locks or allocations. Signal handlers need their own restricted call contract.
Rationale: Process-global changes alter unrelated callers and cannot be scoped by a library object.
Verification design: Inspect global effects and child-process inheritance with platform integration tests.
Contextual Rust example:
let child = std::process::Command::new(program)
.current_dir(directory)
.spawn()?;
Noncompliant fragment or claim (do not copy):
std::env::set_current_dir(directory)?; // Hidden library-wide process effect.
Class: CORRECTNESS / SECURITY. Obligation: project requirement.
Validate type/domain, length, authority and capacity before externally visible mutation. Construct a candidate value, then commit it when possible. If partial effects are unavoidable, document progress and compensation; Result::Err does not imply rollback. No unsafe invariant may depend on a validation step that occurs after the unsafe operation.
Rationale: A rejected operation must leave the state specified by its error contract.
Verification design: Inject failures at each stage and assert the exact post-failure state.
Related pitfalls: RPIT-035.
Contextual Rust example:
let candidate = validate_and_prepare(input)?; self.state = candidate;
Noncompliant fragment or claim (do not copy):
self.state.clear(); validate(input)?; // Failure has already destroyed prior state.
Class: CORRECTNESS. Obligation: project requirement.
Profile: HOSTED.
Define short-read/write, EOF, interrupted operation and retry behavior. Use read_exact/write_all only when their completion contract fits; errors may follow partial external progress. Buffer flush is distinct from durable storage. Multi-write persistence needs a crash-consistency protocol, synchronization and recovery rules owned by the platform adapter.
Rationale: I/O completion, partial progress and durability are different observable contracts.
Verification design: Use short-I/O and interruption adapters, plus crash/restart tests for durability claims. Source: Write API.
Related pitfalls: RPIT-018, RPIT-035, RPIT-036.
Contextual Rust example:
writer.write_all(payload)?; writer.flush()?; // Durability requires the separate platform contract.
Noncompliant fragment or claim (do not copy):
let _ = writer.write(payload)?; // Assumes all bytes were accepted.
Class: CORRECTNESS / SECURITY. Obligation: project requirement.
Use a monotonic time domain for elapsed time and deadlines; wall time is for calendar meaning. Record overflow, suspend and cross-process limitations of the clock. Bound retries with a budget and cancellation. Use an approved cryptographic randomness source for security material and handle entropy failure; deterministic test seeds belong in the test record.
Rationale: Elapsed deadlines and security entropy cannot inherit wall-clock or test-seed assumptions.
Verification design: Inject clock movement, deadline exhaustion and unavailable randomness.
Contextual Rust example:
let deadline = std::time::Instant::now()
.checked_add(timeout)
.ok_or(Error::Time)?;
Noncompliant fragment or claim (do not copy):
let elapsed = SystemTime::now().duration_since(start).unwrap();
Class: SECURITY. Obligation: project requirement.
Profile: HOSTED.
Pass process arguments through an argv API and account for option injection; avoid shell interpolation of external input. Use parameterized downstream queries. A normalized path or string prefix is not an authorization proof against symlinks, races or platform path rules. Keep file-open and authority checks in a capability-aware adapter.
Rationale: Downstream interpreters and path resolution can grant authority beyond the validated string.
Verification design: Test boundary-specific adversarial inputs, path replacement and argument boundaries.
Related pitfalls: RPIT-037.
Contextual Rust example:
Command::new(tool).arg("--").arg(user_path).status()?;
Noncompliant fragment or claim (do not copy):
Command::new("sh").arg("-c").arg(format!("tool {user_path}")).status()?;
Class: SECURITY. Obligation: project requirement.
Limit bytes, nesting, decompression expansion, collection sizes, parse effort and concurrent requests. Enforce authentication and authorization before privileged effects and fail closed when a required decision is unavailable. For outbound requests, validate the effective destination including redirects and address resolution under the deployment policy.
Rationale: Memory-safe parsing still needs admission limits and authorization before privileged effects.
Verification design: Test oversized/deep input, denied authority, redirects and resource exhaustion without unbounded tests. Context: ANSSI guide.
Related pitfalls: RPIT-025.
Contextual Rust example:
authorization.require_write(&identity, &target)?; limits.check_bytes(payload.len())?; store.write(target, payload)?;
Noncompliant fragment or claim (do not copy):
store.write(target, payload)?; authorization.require_write(&identity, &target)?;
Class: SECURITY. Obligation: project requirement.
Profile: stricter CRITICAL.
Redact sensitive data in logs, formatting and errors. Ordinary equality and ordinary clearing are not constant-time comparison or guaranteed secure erasure. Use reviewed primitives and account for copies, allocator retention and crash dumps. If the threat model includes fault injection, define encoded states, redundant checks and critical side-effect ordering with machine-level evidence.
Rationale: Formatting and generated machine behavior can violate confidentiality despite correct ordinary outputs.
Verification design: Test redaction and inspect compiled behavior required by the threat model; do not infer resistance from duplicated source checks.
Related pitfalls: RPIT-038.
Contextual Rust example:
formatter.write_str("Secret([redacted])")
Noncompliant fragment or claim (do not copy):
write!(formatter, "Secret({})", self.value)
Class: SECURITY / PORTABILITY. Obligation: project requirement.
Profile: HOSTED/FFI.
Resolve native libraries and plugins through controlled paths and provenance checks. A Rust shared library is not a stable plugin ABI by default. Use a versioned boundary, validate capabilities and drain users before unloading code. In-process unsafe plugins share process authority; use a process boundary when the trust model requires isolation.
Rationale: A valid symbol address does not prove plugin trust, ABI agreement or safe unload timing.
Verification design: Test wrong versions, missing symbols, search-path substitution and unload with outstanding callbacks.
Related pitfalls: RPIT-049.
Contextual Rust example:
let plugin = trusted_loader.load_verified(manifest)?;
Noncompliant fragment or claim (do not copy):
let plugin = load_library(user_supplied_path)?;
Class: CORRECTNESS / SECURITY. Obligation: project requirement.
Prefer functions and types for ordinary behavior. Macros need explicit argument evaluation, hygiene, error and generated-API contracts; expression arguments must not gain surprising repeated effects. Procedural macros and build scripts execute with build-host authority.
Rationale: Macro expansion and build-time execution can hide repeated effects and privileged dependencies.
Verification design: Inspect representative expansions, test diagnostics and review filesystem/network/environment access.
Related pitfalls: RPIT-041.
Contextual Rust example:
let value = read_once()?; checked_operation(value)?;
Noncompliant fragment or claim (do not copy):
repeat_argument!(read_once()?); // Expansion evaluates the expression twice.
Class: PORTABILITY. Obligation: project requirement.
Prefer features that add capabilities without removing another consumer's behavior. Cargo feature unification means one dependency can enable features for another. Keep mutually exclusive backends in explicit supported configurations and diagnose invalid combinations. cfg! does not remove a branch from type checking; use #[cfg] for code unavailable on a target.
Rationale: Feature availability depends on resolution across consumers and on absent configurations.
Verification design: Test default, no-default, individual and supported combined features. Source: Cargo features.
Related pitfalls: RPIT-039, RPIT-043.
Contextual Rust example:
#[cfg(target_os = "linux")] mod linux;
Noncompliant fragment or claim (do not copy):
if cfg!(target_os = "linux") {
linux_only_call(); // Still type-checked on other targets.
}
Class: SECURITY / VERIFICATION. Obligation: project requirement.
Review direct and transitive dependencies, native components, licenses, source registries and build-time execution. Lock reproducible CI/release resolution and record advisory-database identity. Generated bindings need generator version, inputs, target flags and reproducible output; keep local patches to upstream imports traceable. Do not hand-edit generated files as the long-term fix.
Rationale: The release build depends on source identity and executable build inputs, not just a crate name.
Verification design: Rebuild from controlled inputs and inspect dependency/source changes. Sources: RustSec, cargo-deny, Microsoft project guidance.
Related pitfalls: RPIT-041.
Contextual review example:
// Record Cargo.lock, source registry, native inputs and generator revision // alongside the release artifact digest.
Noncompliant fragment or claim (do not copy):
// Install whichever dependency and generator versions are newest at build time.
Class: ARCHITECTURE / PORTABILITY. Obligation: project requirement.
Define deprecation, feature and MSRV policy. Review public traits, blanket impls, auto traits, error variants, lifetimes, impl Trait captures and macro expansions for downstream impact. Use semantic-version checks as evidence and maintain representative consumer tests.
Rationale: Public bounds, traits and features constrain downstream source even when private code is unchanged.
Verification design: Compare a released baseline with each supported feature set and inspect behavior changes separately. Source: Cargo SemVer.
Related pitfalls: RPIT-039, RPIT-042.
Contextual Rust example:
#[non_exhaustive]
pub enum Error {
InvalidInput,
Unavailable,
}
Noncompliant fragment or claim (do not copy):
// Add a required method to a publicly implementable trait in a patch release.
Class: SOUNDNESS. Obligation: project requirement.
Profile: allocator profile.
Allocator entry points must obey their allocation API, including alignment and failure results. GlobalAlloc implementations must not unwind. Avoid recursive allocation through logging, synchronization or lazy initialization inside allocator operations. Do not make program correctness depend on observing allocations that the optimizer may eliminate.
Rationale: Allocator entry points can reenter themselves through code that appears unrelated to allocation.
Verification design: Test recursion guards, failure paths, deallocation pairing and representative optimized clients. Source: GlobalAlloc.
Related pitfalls: RPIT-002, RPIT-046.
Contextual review example:
// Update an approved nonallocating counter; render diagnostics outside // allocator entry and its locks.
Noncompliant fragment or claim (do not copy):
let message = format!("allocating {size} bytes");
log(message);
Class: CORRECTNESS / VERIFICATION. Obligation: project requirement.
Sort map-derived output when order matters, use explicit seeds for reproducible tests and define filesystem enumeration order. Keep timestamps, paths and environment-derived metadata under a reproducible-build policy. A fixed seed alone does not make concurrent execution deterministic.
Rationale: Container order, environment and concurrency can change output independently of source revision.
Verification design: Repeat across process seeds, debug/release, target widths and controlled environment variations.
Related pitfalls: RPIT-031.
Contextual Rust example:
let mut keys: Vec<_> = values.keys().collect(); keys.sort();
Noncompliant fragment or claim (do not copy):
for key in values.keys() {
serialize(key); // Claims byte-identical output across processes.
}
Class: VERIFICATION. Obligation: project requirement.
Combine unit, external-consumer, property, differential, fuzz and fault-injection checks according to the claim. Include negative compile tests for lifetime/API restrictions. Code coverage identifies missing observations; it does not prove soundness or all interleavings. Inspect assertions removed or weakened by test-only configuration.
Rationale: Tests need to observe invariants and errors, not only a successful return.
Verification design: Map each high-risk contract to an observable check and retain minimized failing inputs.
Related pitfalls: RPIT-044, RPIT-050.
Contextual Rust example:
assert!(buffer.try_append(oversized).is_err()); assert_eq!(buffer.as_bytes(), before);
Noncompliant fragment or claim (do not copy):
assert!(buffer.try_append(oversized).is_err()); // No state assertion.
Class: VERIFICATION. Obligation: project requirement.
Pin tools, commands, inputs, target and enabled checks. Miri, sanitizers, linting, model checking and fuzzing observe different failure classes. A successful run only supports its tested scope; unsupported operations and excluded targets remain visible. Select stricter subsets and formal methods for CRITICAL profiles from product requirements.
Rationale: Tool success applies to a configured run and cannot establish excluded properties.
Verification design: Keep exit status, logs, limitations and not-run reasons with the review record.
Related pitfalls: RPIT-043, RPIT-044, RPIT-045, RPIT-047, RPIT-050.
Contextual review example:
// Record target, features, tool version, checked paths and unsupported FFI.
Noncompliant fragment or claim (do not copy):
// Miri passed one case, therefore all clients of this unsafe API are sound.
Class: VERIFICATION. Obligation: project requirement.
Profile: CRITICAL.
Link hazards and security requirements to code owners, controls, deviations and verification results. Pin the revision and maturity of external rules before adoption. Evaluate compiler, libraries, target and tooling in the product's qualification context. Do not call the result “MISRA Rust” or claim certification from this guide, a cross-reference matrix or a green tool run.
Rationale: Product assurance requires the implementation and evidence chain for each actual hazard.
Verification design: Audit traceability and evidence gaps before release. See sources and revision policy.
Contextual review example:
// requirement H-12 -> bounded queue owner -> RUST-027 -> exhaustion test
Noncompliant fragment or claim (do not copy):
// Clippy passes, therefore the product meets its safety-integrity target.
These controls apply to BASE and its extensions. They expand RUST-001 into authoring and review rules. The pinned formatter determines mechanical layout; reviewers check vocabulary, grouping and meaning. Preserve existing rule identifiers when extending this section.
Class: PROJECT_STYLE. Obligation: project requirement.
Use the following conventions in project-owned Rust. Keep externally imposed identifiers at the adapter or generated binding boundary, with any required lint exception scoped there. Avoid Hungarian prefixes, a project prefix on every private symbol, and _t suffixes. Modules already provide namespaces.
| Construct | Convention | Example |
|---|---|---|
| Module, source stem, function, method, local, parameter, field | snake_case | free_list, reserve_bytes |
| Struct, enum, union, type alias, trait, enum variant | UpperCamelCase | AllocationError, CapacityExceeded |
| Constant, static, const generic parameter | SCREAMING_SNAKE_CASE | MAX_BLOCK_BYTES, N |
| Type parameter | UpperCamelCase, often a conventional single letter | T, Reader |
| Lifetime parameter | Short lowercase or meaningful snake_case | 'a, 'arena |
| Function-like macro | snake_case | checked_offset! |
Use Rust's standard lint names to diagnose casing, including non_snake_case, non_camel_case_types and non_upper_case_globals. A clean lint run does not establish that a name describes its purpose.
Rationale: The spelling identifies the kind of construct before a reader follows its declaration.
Verification design: Run compiler naming lints and review new public identifiers. Reference: API naming conventions.
Contextual Rust example:
struct FreeBlock {
capacity_bytes: usize,
}
const MIN_BLOCK_BYTES: usize = 64;
Noncompliant fragment or claim (do not copy):
struct free_block_t {
nCapacityBytes: usize,
}
const minBlockBytes: usize = 64;
Class: PROJECT_STYLE. Obligation: project requirement.
Use English domain terms consistently across declarations, docs and diagnostics. Name an allocator region region everywhere unless arena, pool or slab denotes a different documented concept. Avoid vague names such as data2, thing, process_it and manager when a concrete responsibility is known.
Treat acronyms as words in type names: HttpClient, CpuFeatures, FfiHandle, Uuid. Use http_client and cpu_features in value names. Conventional terms such as len, ptr, src and dst are acceptable when their meaning is local and unambiguous. Use i or j only for a short index scope; prefer slot_index when several indexes coexist. Document domain-specific abbreviations at their first public use. Keep standardized external spellings in the boundary that requires them.
Rationale: Consistent vocabulary makes searches reliable and reduces interpretation at call sites.
Verification design: Search the module for competing names for the same concept and inspect acronyms in new public names. See API naming conventions.
Contextual Rust example:
struct CpuFeatures {
has_avx2: bool,
}
let slot_index = free_slots.next()?;
Noncompliant fragment or claim (do not copy):
struct CPUFeatures {
flag1: bool,
}
let n = free_slots.next()?;
Class: PROJECT_STYLE. Obligation: project requirement.
Distinguish byte lengths, element counts, capacities, offsets and indexes. Use names such as payload_bytes, element_count, capacity_bytes and slot_index; specify the origin of an offset when multiple origins exist. Prefer a type such as Duration or a unit newtype when it prevents accidental mixing. At primitive boundaries, encode the unit in the name, for example timeout_ms.
Name Boolean queries affirmatively, with predicates such as is_empty, has_capacity, can_retry or contains. Avoid a negated field that produces expressions such as !is_not_ready. Keep a negated name only where the domain itself defines that state and document it. Replace several Boolean mode parameters with named types or an options type when a call would otherwise require looking up each position.
Rationale: A reader can check dimensions and branch conditions without reconstructing them from arithmetic.
Verification design: Review arithmetic inputs and Boolean call sites without parameter tooltips; require units and mode meaning to remain clear. See RUST-018 for type-enforced distinctions.
Contextual Rust example:
let payload_bytes = input.len();
let has_capacity = payload_bytes <= remaining_bytes;
if has_capacity {
buffer.extend_from_slice(input);
}
Noncompliant fragment or claim (do not copy):
let size = input.len();
let is_not_full = size <= remaining;
if !is_not_full {
reject();
}
Class: PROJECT_STYLE. Obligation: project requirement.
Use new for conventional construction and a descriptive constructor such as with_capacity when its parameter changes the construction policy. A constructor may return Result; try_new is useful when distinguishing a fallible alternative. Document allocations, fallibility and acquired resources explicitly.
For conversions, follow the established as_* borrowed-view, to_* value-conversion and into_* consuming conventions. Select the corresponding standard traits when their contracts fit. Use iter, iter_mut and into_iter consistently with shared borrowing, exclusive borrowing and ownership transfer. Raw-pointer accessors must document validity and lifetime; their names alone cannot carry those obligations.
Prefer capacity() to get_capacity() for an ordinary getter. Reserve get for established access patterns such as optional indexed lookup. Use verbs such as reserve, clear, reset, flush, close and finish only with documented effects: clear need not release capacity, flush need not establish durability, and Drop cannot report a finalization error. Preserve standard trait method names exactly.
Rationale: Familiar method names allow callers to anticipate ownership and lifecycle effects.
Verification design: Compare names with receiver types, return types and contracts. Reference: API conversion and getter conventions; RUST-026 covers finalization.
Contextual Rust example:
impl Buffer {
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
Noncompliant fragment or claim (do not copy):
impl Buffer {
pub fn as_bytes(self) -> Vec<u8> {
self.bytes
}
}
Class: PROJECT_STYLE. Obligation: project requirement.
Use conventional short parameters such as T, E, K and V where their roles are immediately clear. Use role names such as Reader or Backend when several unrelated parameters would otherwise become T, U, V and W. Trait names describe capabilities or concepts; avoid automatic I prefixes or Trait suffixes. Follow established ecosystem names when implementing their interfaces.
Elide lifetimes where the signature remains clear and Rust permits it. Use 'a for one obvious relationship; name distinct lifetimes 'arena, 'input or 'config when that explains independent borrows. A name does not establish a relationship: express necessary outlives constraints in the signature. Document associated types by their role, such as Item or Error.
Rationale: Generic notation should expose the relationship a caller needs to understand.
Verification design: Read the signature without its body and identify each parameter's role and each borrowed output's source. Review constraints separately from naming.
Contextual Rust example:
struct Decoder<'input, Backend> {
input: &'input [u8],
backend: Backend,
}
Noncompliant fragment or claim (do not copy):
struct Decoder<'lifetime1, T1> {
input: &'lifetime1 [u8],
backend: T1,
}
Class: PROJECT_STYLE. Obligation: project requirement.
Use snake_case for Rust crate identifiers, modules and source stems. A Cargo package may use a hyphenated distribution name, such as memalloc-core; document its import name memalloc_core where users need both. Respect an established package name rather than renaming a published package for cosmetic consistency.
Name a module after its responsibility, for example free_list, layout or platform, and its main types after their domain roles. Prefer free_list::Cursor over free_list::FreeListCursor when the shorter name is unambiguous at intended use sites. Avoid dumping unrelated helpers into utils, common or misc. Choose the existing module.rs or module/mod.rs arrangement consistently within a subsystem; do not keep both candidates for the same module. Use lib.rs, main.rs, build.rs and integration-test paths according to Cargo's conventions.
Rationale: A name and its filesystem location should help a reader find the responsible component.
Verification design: Compare file names, module declarations and public paths. Review boundary cohesion with RMOD-001.
Contextual review example:
Cargo package: memalloc-core Rust crate: memalloc_core Source: src/free_list.rs Public path: memalloc_core::free_list::Cursor
Noncompliant fragment or claim (do not copy):
src/utils2.rs owns free lists, network retries and build configuration.
Class: PROJECT_STYLE. Obligation: project requirement.
Use enum variants that read naturally with their enum, such as AllocationError::CapacityExceeded. Avoid repeating an enum's name in every variant. Prefer named fields for several payloads with distinct roles; use tuple variants when the payload's single role is evident. Error type names should identify the operation or domain, such as AllocationError or ParseLayoutError.
Name constants for the invariant or policy they represent, such as MAX_ALIGNMENT_BYTES, and supply a type or unit where needed. Avoid identifiers such as VALUE_64 that restate a literal without its purpose. Several occurrences of the same number may represent different policies and do not automatically belong in one shared constant. Keep enum discriminants and protocol numbers explicit where required by a format.
Rationale: Names should survive a policy change and distinguish errors that need different handling.
Verification design: Read variant names at match sites and follow each constant to the policy it controls. Review representation separately under RUST-023.
Contextual Rust example:
enum AllocationError {
InvalidAlignment,
CapacityExceeded {
requested_bytes: usize,
limit_bytes: usize,
},
}
const MIN_ALIGNMENT_BYTES: usize = 8;
Noncompliant fragment or claim (do not copy):
enum AllocationError {
AllocationErrorInvalidAlignment,
Error2(usize, usize),
}
const VALUE_8: usize = 8;
Class: PROJECT_STYLE. Obligation: project requirement.
Use snake_case test names that identify the condition and expected behavior, such as append_over_limit_preserves_contents. The containing module may supply the subject; avoid repeating a long full path in every test name. Use tests for the conventional unit-test module and responsibility-based names for integration-test files. Name fixtures by the boundary they exercise, not by discovery order.
Benchmark names must distinguish workload parameters that change the interpretation, including size, ownership mode and backend where applicable. Preserve a benchmark identifier deliberately when tracking history; explain a rename or workload change. Avoid names such as fast, optimized or test_2 that hide the measured or asserted behavior.
Rationale: A failing check or changed measurement should identify the affected contract from its name.
Verification design: Inspect test listings and benchmark labels without reading bodies; compare each name with its assertions or workload. See RUST-058 and RPERF-001.
Contextual Rust example:
#[test]
fn append_over_limit_preserves_contents() {
let mut buffer = bounded_buffer_with(b"abc", 4);
assert!(buffer.try_append(b"de").is_err());
assert_eq!(buffer.as_bytes(), b"abc");
}
Noncompliant fragment or claim (do not copy):
#[test]
fn test_2() {
let mut b = bounded_buffer_with(b"abc", 4);
assert!(b.try_append(b"de").is_err());
}
Class: PROJECT_STYLE. Obligation: project requirement.
Use a 100-column budget for Rust source, including indentation, under the selected formatter. Wrap at syntax boundaries: arguments, fields, bounds and method-chain stages. Preserve complete identifiers and operators. If repeated wrapping obscures an expression, introduce a meaningful local or extract a cohesive operation; avoid shortening descriptive names merely to fit the margin.
For prose-only Rust comments, aim for at most 80 characters from the comment marker and remain within 100 columns including indentation. Review comments manually because rustfmt need not reflow them. Markdown prose in these guides uses the repository's 120-column policy. A required long URL, exact string, generated record or test fixture may exceed the Rust budget when splitting would obscure or change its meaning; keep that exception local and explain any non-obvious reason. max_width does not guarantee that every literal or macro body is wrapped.
Rationale: A predictable width supports side-by-side review while preserving meaningful source text.
Verification design: Run rustfmt, then inspect remaining overlong lines and comment paragraphs. Reference: Style Guide formatting conventions. Do not change a literal's value to satisfy a width check.
Contextual Rust example:
let payload_end = payload_offset
.checked_add(payload_bytes)
.ok_or(AllocationError::CapacityExceeded)?;
Noncompliant fragment or claim (do not copy):
let payload_end = payload_offset.checked_add(payload_bytes).ok_or(AllocationError::CapacityExceeded)?; // Rename payload_offset to p and AllocationError to E just to prevent wrapping.
Class: PROJECT_STYLE. Obligation: project requirement.
Use four spaces per indentation level and spaces rather than tabs for source indentation. Let rustfmt place continuation lines relative to the block; do not align them manually beneath a distant argument. Keep opening braces with their declaration or control expression and closing braces at the containing indentation. Accept the formatter's rules for else, compact expressions and empty bodies.
Use formatter-produced spaces around binary operators, after commas and after field/type colons. Keep path separators, member access and reference syntax compact: core::ptr, value.len(), &mut value and &[u8]. Avoid tabs or repeated spaces used to align assignments, types or trailing comments into columns. Literal tabs and spaces that are data are governed by RUST-081.
Rationale: Block indentation remains stable when names change and exposes nesting consistently.
Verification design: Check rustfmt output and inspect hand-aligned tables in code or macro bodies. Reference: Style Guide.
Contextual Rust example:
if requested_bytes <= capacity_bytes {
let remaining_bytes = capacity_bytes - requested_bytes;
report(remaining_bytes);
} else {
reject();
}
Noncompliant fragment or claim (do not copy):
if requested_bytes<=capacity_bytes
{
let remaining_bytes =capacity_bytes-requested_bytes;
report( remaining_bytes );
}
Class: PROJECT_STYLE. Obligation: project requirement.
Use one blank line when a function moves between meaningful stages, such as validation, preparation and publication. Keep statements that implement one small step together. Avoid consecutive blank lines, a blank line after every statement, and empty padding immediately inside a block. A blank line contains no spaces.
Keep a fallible operation beside its ?, match or explicit result check. Separate a completed operation from a distinct stage, not from the check that establishes whether it succeeded. Keep an invariant comment with the statements it explains. A tail expression may directly follow the final preparation step; use a blank line before it only when it marks a distinct stage. Do not require blank lines around every return, break, continue or ?.
Rationale: Vertical spacing shows where one thought ends without hiding operation/check relationships.
Verification design: Review changed functions with blank lines treated as paragraph boundaries. Rustfmt can normalize spacing but cannot decide whether the chosen transaction boundaries are meaningful.
Contextual Rust example:
validate_layout(layout)?; let required_bytes = checked_size(layout)?; let reservation = pool.try_reserve(required_bytes)?; reservation.initialize(input)?; Ok(reservation.publish())
Noncompliant fragment or claim (do not copy):
let result = pool.try_reserve(required_bytes); record_attempt(); let reservation = result?; reservation.initialize(input)?;
Class: PROJECT_STYLE. Obligation: project requirement.
Use one blank line between function definitions, impl blocks and distinct type declarations. Within an impl, separate methods by one blank line; keep each method's docs and attributes attached. Keep a small related constant group or consecutive simple fields together. Use a single blank line between distinct groups only when the grouping expresses a domain relationship.
Do not insert empty lines immediately after an opening brace or before a closing brace. Avoid large vertical banners and multiple blank lines to simulate sections. When a file needs many unrelated visual sections, review its module responsibilities under RUST-017. Whitespace alone does not define a boundary.
Rationale: Regular separation makes definitions easy to scan while preserving cohesive groups.
Verification design: Inspect item boundaries and constant/field groupings after rustfmt. A retained blank line must separate concepts rather than compensate for an oversized module.
Contextual Rust example:
impl Buffer {
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
}
Noncompliant fragment or claim (do not copy):
impl Buffer {
pub fn len(&self) -> usize { self.bytes.len() }
pub fn is_empty(&self) -> bool { self.bytes.is_empty() }
}
Class: PROJECT_STYLE. Obligation: project requirement.
Write item documentation with /// immediately before its attributes and declaration. Use //! for crate and module documentation. Put each outer attribute on its own line, with the indentation of its item. Use /// lines to separate paragraphs inside a doc comment rather than inserting an ordinary empty line between the documentation and its item. Keep #[cfg], lint expectations and other attributes next to the declaration or expression they control.
Place // SAFETY: beside the unsafe operation it justifies, normally immediately above the unsafe block or impl. Keep a public unsafe API's # Safety contract in its rustdoc. These two forms have different jobs under RUST-003. Do not move safety comments away from their operation merely to create uniform spacing. Preserve macro attribute ordering when it affects expansion.
Rationale: Readers and tools must agree on which declaration or operation a comment or attribute describes.
Verification design: Inspect rendered rustdoc and the scope of every moved attribute or safety comment. Reference: Style Guide documentation and attribute conventions.
Contextual Rust example:
/// Returns the number of initialized bytes.
///
/// Spare capacity is excluded.
#[must_use]
pub fn len(&self) -> usize {
self.bytes.len()
}
Noncompliant fragment or claim (do not copy):
/// Returns the number of initialized bytes.
#[must_use]
pub fn len(&self) -> usize {
self.bytes.len()
}
Class: PROJECT_STYLE. Obligation: project requirement.
Keep short signatures compact when rustfmt does so. Let long parameter lists break into a block with one parameter per line and formatter-produced trailing commas. Group a parameter's name and type together; avoid manually aligning colons or return arrows. Use a where clause when several bounds would obscure the function name, arguments or return type. Keep associated-type constraints readable.
Use a named request type when several arguments form a stable domain concept; do not create a throwaway type only to hide a long line. Avoid opaque type aliases that conceal ownership or error semantics just to shorten a signature. Split overly complex contracts by responsibility under RUST-016.
Rationale: Callers should be able to identify inputs, output ownership and constraints from the signature.
Verification design: Review the formatted signature independently of the implementation and check that any extracted type improves the domain model. Let the selected rustfmt decide exact wrapping.
Contextual Rust example:
fn write_record<W>(writer: &mut W, header: &[u8], payload: &[u8]) -> std::io::Result<()>
where
W: std::io::Write,
{
writer.write_all(header)?;
writer.write_all(payload)
}
Noncompliant fragment or claim (do not copy):
fn write_record<W: std::io::Write>(writer : &mut W,
header : &[u8],
payload : &[u8]) -> std::io::Result<()> {
writer.write_all(header)?; writer.write_all(payload)
}
Class: PROJECT_STYLE. Obligation: project requirement.
Let rustfmt wrap calls and method chains; use its trailing commas for multiline argument lists. Keep a fallibility operator attached to the expression it checks. For a long transformation chain, make each stage express a clear operation. Introduce a named intermediate when a reader needs to inspect a meaningful state or distinguish separate effects. Prefer a loop when a chain hides branching, error recovery or mutation.
Keep short closures as expressions when they remain clear. Give a multistatement closure a block and the same logical grouping as a function. Extract a named helper when the closure has an independent contract. Avoid deeply nested calls that combine input parsing, resource acquisition and publication in one expression. Check evaluation order and temporary lifetimes when extracting expressions.
Rationale: Expression layout should expose the order of computation and the point where failure occurs.
Verification design: Trace calls and effects in evaluation order; run rustfmt after decomposition and review drop timing for moved temporaries.
Contextual Rust example:
let layout = parse_layout(input)?; let reservation = pool.try_reserve(layout)?; registry.publish(reservation)
Noncompliant fragment or claim (do not copy):
registry.publish(pool.try_reserve(parse_layout(read_request(source)?)?)?)
Class: PROJECT_STYLE. Obligation: project requirement.
Accept rustfmt's compact layout for simple literals and its multiline layout for larger structs, enums and matches. Use field shorthand when the binding already has the field's name. Put a multistatement match arm in a block, keep its binding/guard/body relationship clear, and use formatter-owned commas and indentation. Do not force a multiline expression onto one line by removing useful names or suppressing formatting.
Keep variant and field ordering meaningful. Field order can affect representation and destruction; match-arm order can affect which pattern wins. Do not sort either as a cosmetic operation. Use exhaustive matches when a new variant should force review under RUST-018; an underscore arm is a semantic decision. Destructure only the fields the operation needs, following RUST-084.
Rationale: A regular layout lets the reader focus on alternatives and the state each alternative produces.
Verification design: Check the formatter diff, arm reachability and any field or variant reordering. Representation and drop effects require their own review, even in a formatting change.
Contextual Rust example:
match state {
State::Ready { offset_bytes } => Ok(offset_bytes),
State::Exhausted => {
metrics.record_exhaustion();
Err(AllocationError::CapacityExceeded)
}
}
Noncompliant fragment or claim (do not copy):
match state { State::Ready { offset_bytes } => Ok(offset_bytes), _ => { metrics.record_exhaustion(); Err(AllocationError::CapacityExceeded) } }
Class: PROJECT_STYLE. Obligation: project requirement.
Use parentheses when mixed arithmetic, shifts, masks or Boolean operators would require readers to recall precedence. Remove redundant outer parentheses around a simple if, while or match operand. Avoid a single condition that combines several independent validations; give checks a meaningful name or use early rejection when that clarifies behavior. Preserve short-circuit evaluation and side effects when rewriting.
Keep one statement per logical source line. Use braces for Rust control-flow bodies and let rustfmt choose the compact representation of simple value-producing expressions. Do not impose C-style parentheses around every condition or a final return on ordinary Rust tail expressions. See RUST-016 for exit policy.
Rationale: A reader should see the intended grouping and evaluation path without mentally parsing a puzzle.
Verification design: Review mixed-precedence expressions, short-circuit dependencies and nested conditions; use Clippy findings as prompts and inspect any automatic rewrite for preserved behavior.
Contextual Rust example:
let has_read_access = (flags & READ_MASK) != 0;
let can_publish = is_initialized && (has_read_access || is_owner);
if can_publish {
publish();
}
Noncompliant fragment or claim (do not copy):
if (is_initialized && flags & READ_MASK != 0 || is_owner) { publish(); }
Class: PROJECT_STYLE. Obligation: project requirement.
At module scope, group imports in this order when the groups exist: standard-library roots (core, alloc, std), external dependencies, then project paths (crate, super, self). Use one blank line between these groups. Let the selected formatter order and wrap entries within a group. Default rustfmt need not create these groups; review them explicitly without assuming an unstable configuration option is enabled.
Prefer explicit imports. A small use super::* in a local test module is acceptable when its scope is clear; other glob imports require a narrow reason, such as a documented prelude. Use aliases to resolve collisions or convey a stable domain role, not to abbreviate arbitrary types to one letter. Keep a deliberately local import next to the code it serves. Treat pub use as part of public API design and group re-exports coherently.
Rationale: A reader can identify where an operation comes from and notice new component dependencies.
Verification design: Review new imports alongside the dependency graph, and verify that feature-gated imports carry the correct cfg. See RUST-013 for visibility and re-exports.
Contextual Rust example:
use core::num::NonZeroUsize; use core::ptr::NonNull; use crate::layout::BlockLayout; use crate::pool::Pool;
Noncompliant fragment or claim (do not copy):
use crate::pool::*; use core::ptr::NonNull as P; use crate::layout::*;
Class: PROJECT_STYLE. Obligation: project requirement.
Declare a binding near its first use and use the smallest scope that preserves ownership and required drop timing. Prefer immutable bindings; add mut where mutation is part of the local operation. Use a separate let for unrelated values, while retaining tuple or struct destructuring that expresses one operation. Specify a type when it establishes an important boundary; let inference handle obvious local detail.
Shadowing is appropriate for an evident refinement, such as trimming then parsing the same input. Use a new name when the meaning, unit or ownership role changes substantially. Avoid reusing size successively for bytes, elements and aligned storage. Do not use shadowing to suggest that a previous resource has necessarily been dropped; explicit scopes or drop should mark required resource-release points.
Rationale: Local bindings should reveal the state being used and prevent stale or ambiguous interpretations.
Verification design: Follow each binding through its scope and review shadowing near guards or owning resources. Confirm that any scope reduction preserves the intended destruction order.
Contextual Rust example:
let input = input.trim(); let element_count: usize = input.parse()?; let allocation_bytes = checked_storage_bytes(element_count)?;
Noncompliant fragment or claim (do not copy):
let size = input.trim(); let size: usize = size.parse()?; let size = checked_storage_bytes(size)?;
Class: PROJECT_STYLE. Obligation: project requirement.
Use // followed by a space for ordinary comments and complete sentences for explanations. Prefer a comment above the relevant code over a long trailing comment. Explain an invariant, protocol choice, workaround or measured tradeoff; omit comments that merely restate the next statement. Keep diagrams or tables only when they clarify a real relationship, and maintain their accuracy with the code. Remove disabled production code from comments.
A TODO or FIXME must identify an issue or accountable owner and state the remaining behavior and acceptance condition. Use stable searchable terms in diagnostics. Include the failed operation and useful nonsensitive context, such as requested and allowed sizes; do not expose secrets or invent an error cause. Follow the error type's Display convention and let the application select user-facing presentation.
Rationale: Comments preserve reasoning and diagnostics support investigation beyond the author's session.
Verification design: Check comment/code agreement, tracked work and diagnostic usefulness. Inspect redaction under RUST-050 and contract documentation under RUST-004.
Contextual Rust example:
// Publish only after initialization so readers never observe spare capacity. state.publish(initialized_bytes);
Noncompliant fragment or claim (do not copy):
// Call publish. state.publish(initialized_bytes); // TODO: fix stuff later
Class: PROJECT_STYLE. Obligation: project requirement.
Use separators in long numeric literals to show meaningful groups, such as 1_000_000 or 0x00ff_ffff. Choose decimal for ordinary counts and hexadecimal for bit patterns where that helps review. Add a numeric suffix or type annotation when required to establish arithmetic width. A named policy constant still needs the rationale required by RUST-067.
Use ordinary, byte or raw strings according to the represented data and escaping needs. Long diagnostic text may use concat! with explicit spaces between segments. Multiline raw strings include their literal line breaks and indentation; do not reindent them as ordinary prose. Make significant tabs, trailing spaces, carriage returns or control characters visible through escapes or a documented fixture. Preserve exact protocol text and test vectors when wrapping, and keep a local overlong line when that is clearer.
Rationale: A cosmetic edit must not silently alter bytes, numeric width or a protocol value.
Verification design: Inspect the represented value after a literal edit. For fixtures and wire text, use the existing byte-level assertions; review width exceptions under RUST-069.
Contextual Rust example:
const MAX_PAYLOAD_BYTES: usize = 1_048_576;
const MESSAGE: &str = concat!(
"The requested allocation exceeds the configured limit. ",
"Reduce the payload or raise the limit explicitly."
);
Noncompliant fragment or claim (do not copy):
// Intended to preserve "allocation failed" while wrapping source text.
const MESSAGE: &str = concat!("allocation", "failed");
Class: PROJECT_STYLE. Obligation: project requirement.
Give project-owned function-like macros descriptive snake_case names and metavariables meaningful roles, such as $offset and $layout. Format macro bodies as ordinary Rust where their grammar permits. Keep distinct matcher arms visually separated when they implement different accepted forms. For a custom grammar that rustfmt cannot format, document and consistently apply that grammar's local layout.
Keep cfg and cfg_attr conditions readable, close to their items and consistent across declarations and imports. Factor repeated platform selection into a module boundary where that clarifies ownership. Explain any narrowly scoped formatter exception and keep it out of unrelated code. Do not reorder procedural attributes, matcher arms or derive inputs as a cosmetic change without checking expansion semantics.
Rationale: Macro syntax and conditional compilation need visible structure because readers cannot see all expanded configurations at once.
Verification design: Review each accepted macro form and affected configuration; use the expansion and feature checks required by RUST-052 and RUST-053.
Contextual Rust example:
#[cfg(all(target_os = "linux", feature = "os-pages"))] mod linux_pages;
Noncompliant fragment or claim (do not copy):
#[cfg(all(target_os="linux",feature="os-pages"))] mod linux_pages;
Class: PROJECT_STYLE. Obligation: project requirement.
Start owned files with the repository's license notice, followed by crate/module documentation and inner attributes as applicable. Keep module declarations, imports and public re-exports near the top. Then present domain constants and types, their implementations, helpers and local tests in an order that explains the module. Keep a type and its closely related impls near one another instead of separating every impl from every type mechanically. Group foreign declarations at their owned boundary.
Place unit tests in the conventional #[cfg(test)] mod tests near the end when a single local test module fits. Split large tests by responsibility rather than letting test volume hide implementation structure. Use UTF-8, LF and the repository EOF policy described in the formatting overview. Avoid editor modelines, hidden directional controls and decorative comment banners. Imported and generated files retain their documented provenance and generator policy.
Rationale: Predictable ordering helps readers move from contract to representation to behavior and checks.
Verification design: Review navigation through the file, license/provenance and source-text consistency. This ordering is a project policy; it does not claim that Rust requires every item to appear in this order.
Contextual review example:
License notice Module documentation and inner attributes Module declarations, grouped imports and public re-exports Domain constants and types with related implementations Private helpers Local tests Repository EOF marker
Noncompliant fragment or claim (do not copy):
Public API, platform imports, unrelated helpers and tests are interleaved in the order in which contributors happened to add them.
Class: PROJECT_STYLE. Obligation: project requirement.
Use destructuring to expose the roles of values returned together. Rename fields in a pattern when the local role needs clarification. Use .. only when omitted fields are deliberately irrelevant to the operation; use explicit fields when an added field should trigger a contract review.
An unused _name binding is appropriate when the value must remain owned, such as a lock guard, or a required callback parameter is unused. A wildcard _ does not provide the same ownership intent as a named guard. Do not silence an unused Result with let _ = unless deliberate best-effort handling is justified locally and permitted by the operation's contract. A leading underscore must not hide an unhandled failure.
Rationale: Patterns express both the data the operation depends on and the values it keeps alive or ignores.
Verification design: Inspect ignored fields, must-use results and guard bindings. Verify resource lifetime and error policy rather than accepting a warning-free build as evidence of intent.
Contextual Rust example:
let _guard = gate.lock().map_err(|_| AccessError::Poisoned)?; update_shared_state();
Noncompliant fragment or claim (do not copy):
let _ = gate.lock(); update_shared_state(); // The temporary result cannot retain the lock here.
An optimization must preserve the declared contracts, including timing/resource constraints, and outperform a maintained reference under a representative experiment. Rust is normally ahead-of-time compiled; there is no universal LuaJIT-like warm-up requirement. Distinguish process startup, cache/page warming, lazy initialization and steady state. A runtime code generator needs its own execution, invalidation and W^X policy.
Each RPERF control applies when making its corresponding performance claim. The review record identifies the hypothesis, source/toolchain/target, workload, reference, samples, correctness results, resource changes and acceptance criterion. Native tuning belongs to its backend owner, with portable public behavior unchanged.
Class: PERFORMANCE. Apply the scope and requirement words below.
Measure end-to-end latency and throughput alongside the kernel. Include construction, copying, allocation, shutdown and failure paths when the user pays those costs. Keep raw samples and report tails with sample count, timer resolution and variability. An observed maximum is not WCET. Use repeated baseline/candidate runs and predeclared regression thresholds. Context: Performance Book: profiling.
Rationale: A kernel improvement can hide a more expensive setup or cleanup phase.
Verification design: Measure startup and complete lifecycle separately; retain sample counts and timer resolution.
Experiment design (not a measured result):
same workload -> baseline/candidate alternation -> raw samples -> latency distributions
Noncompliant claim or experiment:
time one warm candidate run; compare with a cold baseline
Class: PERFORMANCE. Apply the scope and requirement words below.
Record rustc/LLVM, optimization, LTO, codegen units, panic strategy, overflow checks, target features, allocator, OS, CPU topology, affinity, frequency policy, SMT and speculation mitigations. Keep debug builds out of release speed claims. Profile-guided optimization needs representative training data and reproducible profile inputs. Verify deployed instruction compatibility. Context: build configuration.
Rationale: Compiler and machine policy can change costs without any source-code change.
Verification design: Compare run identities before interpreting timing differences.
Experiment design (not a measured result):
source + rustc + flags + allocator + CPU + affinity + mitigation state -> run identity
Noncompliant claim or experiment:
compare builds with different target-cpu settings without recording them
Class: PERFORMANCE. Apply the scope and requirement words below.
Remove repeated work and unnecessary copying before unsafe indexing or assembly. Compare complexity across small, large, skewed and adversarial inputs. Partition state by owner or CPU where feasible, then measure aggregation and cross-owner frees. A local fast path must include its slow/reclamation costs in the experiment.
Rationale: Removing repeated work often improves scaling without adding a new unsafe obligation.
Verification design: Sweep input size and contention; include owner handoff and reclamation costs.
Experiment design (not a measured result):
parse configuration once -> bounded per-owner work -> measured aggregation
Noncompliant claim or experiment:
replace checked indexing while retaining repeated full-table scans
Class: PERFORMANCE. Apply the scope and requirement words below.
Choose Box for ownership/indirection, Rc for single-thread sharing, Arc for justified cross-thread sharing, and Cow when retaining a borrowed representation avoids common copies. Cow may allocate on mutation. Select Vec, ordered maps, hash maps or bounded containers by access, determinism and growth requirements. Measure retained capacity, fragmentation and relocation; segmented storage can trade locality for stable growth. Context: heap allocations.
Rationale: Fewer allocations can still mean more retained memory or copying.
Verification design: Measure allocations, peak/retained capacity and lifetime under production providers.
Experiment design (not a measured result):
borrowed read: &[u8] owned growable bytes: Vec<u8> shared cross-thread owner: Arc<T> borrow-until-mutation: Cow
Noncompliant claim or experiment:
Arc for every value, even when one caller owns it exclusively
Class: PERFORMANCE. Apply the scope and requirement words below.
Measure runtime, compile time and binary size together. Generic adapters can call a smaller concrete core; dynamic dispatch can reduce duplicated code while adding an indirect call. Keep rare complex paths out of line when profiles justify it. Review #[inline], especially #[inline(always)], as an evidence-based decision. Do not infer an instruction sequence from source appearance. Context: machine-code inspection.
Rationale: Machine code grows with instantiated implementations, affecting build and instruction-cache cost.
Verification design: Compare code size, compile time, generated code and runtime on representative consumers.
Experiment design (not a measured result):
small generic facade -> concrete hot core -> out-of-line rare path
Noncompliant claim or experiment:
inline(always) on every generic helper without a profile
Class: PERFORMANCE. Apply the scope and requirement words below.
Use slices, iterators, chunks and a validated shared bound so the compiler can reason about accesses. Retain a checked implementation as the oracle. get_unchecked requires a complete local bounds proof and a measured benefit after generated-code inspection; a benchmark win cannot waive its unsafe contract. Context: bounds checks.
Rationale: Expressed bounds can remove redundant checks without transferring proof obligations to every caller.
Verification design: Inspect generated checks and test boundaries before considering unsafe indexing.
Experiment design (not a measured result):
validated shared range -> slice iterator -> checked reference comparison
Noncompliant claim or experiment:
get_unchecked used because all current tests happen to pass
Class: PERFORMANCE. Apply the scope and requirement words below.
Measure false sharing before padding. Separate independent locks, counters and compact flags when coherence traffic explains a bottleneck. State target cache-line assumptions; one line of padding may not account for adjacent-line prefetch. Keep layout tuning internal and include its larger memory footprint in the result. Context: Atomics and Locks: hardware.
Rationale: Sharing a coherence unit couples otherwise independent writers.
Verification design: Use contention measurements and access-layout records; include memory overhead.
Experiment design (not a measured result):
writer A counter -> measured isolated placement writer B counter -> measured isolated placement
Noncompliant claim or experiment:
add a hard-coded padding width to every public struct
Class: PERFORMANCE. Apply the scope and requirement words below.
Avoid repeated shared writes that convey no new information. Consider per-owner statistics and deferred aggregation. Select batch size using throughput, fairness, memory and maximum queue delay. A remote free, Arc clone/drop or atomic counter update belongs in the synchronization budget, even when the source is short. Test under the deployed contention topology.
Rationale: Batching trades synchronization frequency against latency and retained work.
Verification design: Measure throughput, tails, queue depth and cross-owner free cost.
Experiment design (not a measured result):
bounded local batch -> one publication -> measured drain interval
Noncompliant claim or experiment:
unbounded batch accumulation to minimize atomic operations
Class: PERFORMANCE. Apply the scope and requirement words below.
Compare locks, bounded spinning, parking, channels and read-mostly schemes using reader/writer mix and tails. Document wakeup, starvation and priority-inversion behavior. Epoch or RCU-like reclamation needs bounded-retention and shutdown policies. Raw atomics remain inside semantic operations reviewed under RUST-040 and RUST-041.
Rationale: Progress and reclamation behavior depend on the actual reader/writer mix.
Verification design: Test starvation, oversubscription, retirement growth and shutdown.
Experiment design (not a measured result):
read-mostly workload -> retention budget -> chosen wait/wake protocol
Noncompliant claim or experiment:
replace locks with spinning and declare every path wait-free
Class: PERFORMANCE. Apply the scope and requirement words below.
For hot loads/stores, investigate alignment, split boundaries, store-to-load forwarding geometry, store-buffer pressure and false 4 KiB aliasing only after counters or controlled experiments identify a cause. Atomic operands must satisfy the target's alignment and atomicity contract; never construct a split or misaligned atomic by packed representation. Record exact access sizes and offsets.
Rationale: A source-level load or store can cross hardware boundaries that alter its cost or validity.
Verification design: Check atomic alignment first; then vary geometry with fixed workload and target.
Experiment design (not a measured result):
access offset + width + alignment -> target counter hypothesis -> controlled experiment
Noncompliant claim or experiment:
pack atomics into an unaligned wire-format struct
Class: PERFORMANCE. Apply the scope and requirement words below.
Coordinate CPU affinity, first-touch memory placement, IRQ/device locality and cross-node traffic at the platform owner. Measure TLB/page-walk cost separately from data-cache misses. Page size, residency and prefaulting affect deterministic latency. Cache coloring and TLB invalidation are allocator/kernel experiments; user-space Rust cannot claim control it does not have.
Rationale: Translation and topology costs require different evidence from data-cache locality.
Verification design: Measure remote accesses, page walks, residency and migration under the deployment policy.
Experiment design (not a measured result):
CPU owner + memory placement + page policy + IRQ/device locality -> experiment
Noncompliant claim or experiment:
claim NUMA improvement after only changing a Rust struct field order
Class: PERFORMANCE. Apply the scope and requirement words below.
Compare branches and branchless alternatives under realistic distributions. Do not use UB-producing unchecked assumptions to remove a branch. Bind stable indirect targets outside inner loops when measurement supports it. Investigate deep call chains, return prediction, branch hints and code alignment as target-specific hypotheses. Runtime patching requires an instruction-cache, concurrency and patch-geometry protocol.
Rationale: Removing a branch can add work or worsen prediction for common inputs.
Verification design: Record input distribution, code size and branch/indirect-target observations.
Experiment design (not a measured result):
representative branch distribution -> branch/branchless candidates -> equal outputs
Noncompliant claim or experiment:
replace every conditional with branchless arithmetic
Class: PERFORMANCE. Apply the scope and requirement words below.
Specify access validity, prefetch distance, reuse and cache pollution. Overlap independent work with long-latency loads when dependencies allow it. Record hardware prefetcher settings and working-set distribution; a change that helps one stride can harm another. Keep unsafe intrinsics inside a reviewed backend and preserve bounds.
Rationale: Prefetch can consume bandwidth and evict useful data before the consumer reaches it.
Verification design: Vary distance and working set; retain bounds and compare pollution effects.
Experiment design (not a measured result):
valid access range + prefetch distance + reuse window + target settings
Noncompliant claim or experiment:
prefetch arbitrarily beyond the allocation to hide every miss
Class: PERFORMANCE. Apply the scope and requirement words below.
Use non-temporal stores only with measured streaming reuse and target ordering evidence. Complete cache-line streams when practical for write-combining paths, and test alignment, tails and partial lines. DMA buffers need a hardware owner for cache maintenance and ownership handoffs; a Rust borrow alone cannot stop a device from accessing memory.
Rationale: Streaming and DMA behavior depend on device and cache-coherence contracts.
Verification design: Test aligned/misaligned starts, tails, partial lines and required device maintenance.
Experiment design (not a measured result):
owned buffer -> complete-line stream -> ordering handoff -> measured reuse
Noncompliant claim or experiment:
use non-temporal stores for a small buffer reread immediately
Class: PERFORMANCE. Apply the scope and requirement words below.
Keep a portable independent reference and one dispatch owner. Check CPU/OS support before entering a #[target_feature] backend. Differential-test every supported implementation, including tails, alignment, feature-disabled fallbacks and variable vector lengths where applicable. Tests must observe which backend ran; “the test passed” cannot demonstrate specialized execution.
Rationale: A passing fallback test does not establish that a specialized backend executed.
Verification design: Observe selection and exercise each supported backend without executing unsupported instructions.
Experiment design (not a measured result):
forced backend ID -> oracle comparison -> target capability check -> candidate
Noncompliant claim or experiment:
dispatch to the portable fallback and report SIMD coverage
Class: PERFORMANCE. Apply the scope and requirement words below.
Cache keys include the semantic input, target capabilities, code/configuration identity and lifetime domain needed by the specialization. Synchronize replacement and drain users before release. For generated executable memory, control writable/executable transitions and instruction-cache synchronization through the platform API. Do not reuse pointers after their owning module or code allocation has gone away.
Rationale: A cached function is valid only while its code and semantic assumptions remain current.
Verification design: Change each key dimension and test replacement with active users.
Experiment design (not a measured result):
key + retained code generation -> invoke -> release -> retire after drain
Noncompliant claim or experiment:
reuse a code pointer after plugin unload because its address did not change
Class: PERFORMANCE. Apply the scope and requirement words below.
Compare candidate outputs and errors to an independently understandable implementation, with exact or explicitly tolerated numeric results. Prevent benchmark elimination with consumed results and appropriate harness barriers; black_box is not a correctness proof. Track latency, throughput, allocations, peak memory, stack, code size and compilation cost according to the change's claim.
Rationale: Two implementations can agree while sharing the same defect or ignored work.
Verification design: Compare independent results and check resource limits alongside timing.
Experiment design (not a measured result):
simple oracle -> expected output <- separately structured candidate
Noncompliant claim or experiment:
reference and candidate both call the same optimized kernel
Class: PERFORMANCE. Apply the scope and requirement words below.
Retain raw-data location, scripts, build identity, measurement uncertainty, target coverage and the acceptance or rejection decision. Keep unsupported machine claims visible. Remeasure after compiler, allocator, topology or workload changes. Compiler reports and hardware counters explain observations; they do not replace contract tests or the deployment benchmark.
Rationale: Future maintainers need enough evidence to reproduce or reject the original explanation.
Verification design: Reproduce from the saved record and identify unsupported target claims.
Experiment design (not a measured result):
owner + hypothesis + scripts + raw data + constraints + decision
Noncompliant claim or experiment:
commit only a percent speedup without workload or source identity
These entries identify review boundaries. “Restricted” permits an approved use satisfying the named rule; “prohibited” forbids the stated use. A wrapper with a different name does not evade the restriction.
| ID | Facility or behavior | Policy and required alternative |
|---|---|---|
| RBAN-001 | Unproved unwrap, expect, unchecked unwrap | Prohibited in production; RUST-007 and checked matching. |
| RBAN-002 | Unjustified unsafe or unsafe impl | Prohibited; RUST-003, RUST-010 and a complete invariant proof. |
| RBAN-003 | Unchecked indexing, unreachable_unchecked | Restricted to proved invariants and measured need; RPERF-006. |
| RBAN-004 | transmute, zeroing arbitrary typed values | Restricted; RUST-030 and RUST-031, prefer typed conversion. |
| RBAN-005 | static mut, process-global mutation | Restricted platform owner; RUST-015 and RUST-044. |
| RBAN-006 | Raw owner reconstruction from foreign memory | Restricted to exact allocator/ownership contract; RUST-024. |
| RBAN-007 | Panic as expected failure; exit/abort in libraries | Prohibited routine handling; RUST-005 and RUST-006. |
| RBAN-008 | Blocking guards across .await | Prohibited; RUST-037. Async mutexes require their own rationale. |
| RBAN-009 | Unbounded growth, spawning or retries on input | Prohibited; enforce RUST-025, RUST-027 and RUST-049. |
| RBAN-010 | Shell interpolation and unauthorized loading | Prohibited on untrusted input; RUST-048 and RUST-051. |
| RBAN-011 | Deterministic randomness for secrets | Prohibited; use the qualified source in RUST-047. |
| RBAN-012 | Blanket warning/formatter suppression | Prohibited; scoped justified exceptions under RUST-001 and RUST-002. |
| RBAN-013 | Public-ABI promises from default Rust layout | Prohibited; RUST-011, RUST-013 and a versioned interface. |
| RBAN-014 | mem::forget/ManuallyDrop as ordinary cleanup | Restricted to a documented transfer/leak protocol; RUST-026. |
| RBAN-015 | Unsigned/width casts without range semantics | Prohibited at external boundaries; RUST-012 and RUST-020. |
| RBAN-016 | Debug-only checks protecting unsafe access | Prohibited; establish release invariants before access. |
| RBAN-017 | Volatile as synchronization | Prohibited; RUST-040 and a separate device contract. |
| RBAN-018 | Global “all restriction lints” policy | Prohibited without individual review; restrictions may conflict. |
Run commands from a real Cargo workspace with its pinned toolchain and reviewed lockfile. Use the repository cache wrapper for local artifacts. The following recipe assumes every declared feature can coexist; if not, replace --all-features with each supported set and test invalid combinations for the expected diagnostic.
cargo fmt --all -- --check cargo clippy --workspace --all-targets --all-features --locked -- -D warnings cargo test --workspace --all-features --locked cargo test --workspace --all-features --release --locked cargo test --workspace --all-features --doc --locked RUSTDOCFLAGS='-D warnings' cargo doc --workspace --all-features --no-deps --locked
--all-targets means Cargo target kinds, not every CPU/OS target triple. Add explicit cross-target jobs and execute on the target or a qualified emulator. --all-features does not cover absent features. Add default, --no-default-features, supported minimal combinations, MSRV and each native ABI. A host test harness may use std for a no_std library; separately compile the library for its actual target.
| Gate | Scope and operating rule | Limit |
|---|---|---|
| rustfmt | Pinned formatter and style edition. | Presentation only. |
| rustc and Clippy | Same compiler family, required warning-clean profiles. | Do not establish soundness. |
| Unit, integration and rustdoc tests | Contracts and executable examples; run doctests explicitly. | Only observed inputs and paths. |
| Miri | Pin a supported nightly; cargo +<nightly> miri test on compatible targets. | Limited host/FFI support; no proof for unexecuted paths. |
| cargo-nextest | Pinned test runner for isolation/scheduling and reports. | Keep cargo test --doc; not a soundness checker. |
| cargo-fuzz | Pinned toolchain and bounded harness; retain corpus and minimized cases. | Campaign duration and reachable paths limit evidence. |
| Sanitizers | Target-supported sanitizer profile, including compatible native instrumentation. | Instrumentation/target coverage varies. |
| Concurrency model checker | Model the actual atomic/lock protocol with declared bounds. | A simplified model needs a link back to implementation. |
| cargo-deny | Review advisories, licenses, bans and source policy. | Depends on configured graph and database. |
| cargo-audit | Review the locked dependency graph and dated RustSec data. | Known advisories are not all vulnerabilities. |
| cargo-semver-checks | Compare with an identified release and feature configuration. | Behavior, ABI and all compatibility cases need review. |
| Native ABI/export/hardening checks | Inspect archives/shared objects and foreign consumers. | Target-specific evidence. |
| Formal/product qualification | Named properties, assumptions and qualified tools. | Only the demonstrated scope. |
Tool sources: Miri, cargo-fuzz, sanitizers, cargo-deny, RustSec, cargo-semver-checks, cargo-nextest and rustdoc. Missing required tools fail the selected gate; optional or unsupported checks need an explicit not-run record. Do not install unpinned “latest” tools as part of a reproducibility claim.
Save this complete library as bounded_buffer.rs. It uses safe Rust, private state, Result, bounded growth and a commit-after-validation rule. try_append has no logical mutation on a reported error. It does not promise recovery from arbitrary process failure or a malicious allocator. The caller chooses the limit; a production ingress adapter must cap that choice under its own resource budget.
use std::collections::TryReserveError;
use std::fmt;
/// An owned byte buffer with a caller-selected logical limit.
#[derive(Debug)]
pub struct Buffer {
bytes: Vec<u8>,
limit: usize,
}
/// Failure to append bytes without exceeding the resource contract.
#[derive(Debug)]
pub enum AppendError {
Limit,
Allocation(TryReserveError),
}
impl fmt::Display for AppendError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Limit => formatter.write_str("buffer limit exceeded"),
Self::Allocation(error) => write!(formatter, "buffer reservation failed: {error}"),
}
}
}
impl std::error::Error for AppendError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Limit => None,
Self::Allocation(error) => Some(error),
}
}
}
impl Buffer {
/// Constructs an empty buffer without reserving payload storage.
///
/// # Examples
/// ```
/// use bounded_buffer::Buffer;
///
/// let mut buffer = Buffer::new(4);
/// buffer.try_append(b"ab")?;
/// assert_eq!(buffer.as_bytes(), b"ab");
/// # Ok::<(), bounded_buffer::AppendError>(())
/// ```
#[must_use]
pub fn new(limit: usize) -> Self {
Self {
bytes: Vec::new(),
limit,
}
}
/// Borrows the initialized bytes until the next mutable borrow.
#[must_use]
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
/// Appends bytes, preserving the existing contents on error.
///
/// May allocate while reserving capacity. Does not perform I/O.
///
/// # Errors
/// Returns `Limit` for length overflow or a logical limit violation,
/// and `Allocation` when the required reservation fails.
pub fn try_append(&mut self, payload: &[u8]) -> Result<(), AppendError> {
let new_len = self
.bytes
.len()
.checked_add(payload.len())
.ok_or(AppendError::Limit)?;
if new_len > self.limit {
return Err(AppendError::Limit);
}
self.bytes
.try_reserve(payload.len())
.map_err(AppendError::Allocation)?;
self.bytes.extend_from_slice(payload);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{AppendError, Buffer};
#[test]
fn rejected_append_preserves_contents() {
let mut buffer = Buffer::new(4);
buffer.try_append(b"ab").expect("fixture fits");
assert!(matches!(buffer.try_append(b"cde"), Err(AppendError::Limit)));
assert_eq!(buffer.as_bytes(), b"ab");
buffer.try_append(b"cd").expect("exact boundary fits");
assert_eq!(buffer.as_bytes(), b"abcd");
}
#[test]
fn empty_payload_fits_zero_capacity() {
let mut buffer = Buffer::new(0);
buffer.try_append(b"").expect("empty input fits");
assert!(matches!(buffer.try_append(b"x"), Err(AppendError::Limit)));
assert!(buffer.as_bytes().is_empty());
}
}
// EOF
The example verifies ordinary logical rejection. It does not deterministically force allocator failure; RUST-025 requires an injected allocation policy or a qualified harness when that claim is part of a product. No documentation snippet marked text should be compiled as a Rust example. Compile-fail cases need an isolated harness that checks the intended diagnostic rather than accepting any compilation failure.
Validation on 2026-09-22 used four extracted libraries: bounded_buffer, raw_input, composition and byte_count. The temporary workspace declares edition 2024 and rust-version = "1.85", has no external crate dependencies and lives under .cache/tests/rust-guide/.
| Check | Observed result |
|---|---|
| rustc 1.97.1 and Cargo 1.97.1, host Linux x86_64 | Eight unit tests and two rustdoc examples passed. |
| rustc/Cargo 1.85.1, same host | The same eight unit tests and two rustdoc examples passed. |
| Optimized release tests, rustc 1.97.1 | Eight unit tests and two rustdoc examples passed. |
| rustfmt 1.9.0, edition/style edition 2024 | Four complete source files passed the formatting check. |
| Clippy 0.1.97 | All targets passed -D warnings, undocumented_unsafe_blocks and missing_safety_doc checks. |
| rustdoc, rustc 1.97.1 | Documentation built with warnings denied. |
| Negative lifetime example, rustc 1.97.1 | Compilation failed with the expected E0515 diagnostic. |
To reproduce after extraction, create one temporary package per named source file, using that name as the crate name and the file as src/lib.rs. Use a resolver-3 workspace containing those packages. Run the Cargo recipes in the tooling section against its manifest, plus the explicit safety lints used above:
cargo clippy --workspace --all-targets --all-features --offline -- \
-D warnings -D clippy::undocumented_unsafe_blocks -D clippy::missing_safety_doc
Keep the expected-failure snippet outside the ordinary packages and check its diagnostic separately. Contextual snippets require the types and conditions stated in their owning section; negative fragments must not be executed. The examples do not qualify native FFI, other targets, Miri, fuzzing, sanitizers, product assurance or performance. No Rust CI runner was added to the repository by this documentation change.
Save this complete library as byte_count.rs. Both implementations count a byte value in a borrowed slice without allocating. The reference uses a scalar loop; the candidate separates complete chunks and a tail. The test varies the length, starting offset and searched value. No measured speedup is claimed: the candidate still needs the RPERF experiment before adoption. Safe chunking alone does not imply SIMD generation.
/// Counts occurrences with a simple scalar loop used as the reference.
#[must_use]
pub fn count_reference(bytes: &[u8], needle: u8) -> usize {
let mut count = 0;
for byte in bytes {
if *byte == needle {
count += 1;
}
}
count
}
/// Counts occurrences through complete chunks and a checked remainder.
#[must_use]
pub fn count_candidate(bytes: &[u8], needle: u8) -> usize {
let mut chunks = bytes.chunks_exact(8);
let complete: usize = chunks
.by_ref()
.map(|chunk| chunk.iter().filter(|byte| **byte == needle).count())
.sum();
let tail = chunks
.remainder()
.iter()
.filter(|byte| **byte == needle)
.count();
complete + tail
}
#[cfg(test)]
mod tests {
use super::{count_candidate, count_reference};
#[test]
fn candidate_matches_reference_for_offsets_and_tails() {
let mut storage = [0_u8; 80];
for (index, byte) in storage.iter_mut().enumerate() {
*byte = [0, 1, 255][index % 3];
}
for offset in 0..8 {
for len in 0..=65 {
let input = &storage[offset..offset + len];
for needle in [0, 1, 2, 255] {
assert_eq!(
count_candidate(input, needle),
count_reference(input, needle),
"offset={offset}, len={len}, needle={needle}"
);
}
}
}
}
}
// EOF
The snippets are contextual replacement patterns. They require the owning operation's types and contracts.
Class: RESTRICTED_FACILITY. Action: Prohibited in production; RUST-007 and checked matching.
Contextual replacement example:
let value = input.parse::<usize>().map_err(Error::Parse)?;
Class: RESTRICTED_FACILITY. Action: Prohibited; RUST-003, RUST-010 and a complete invariant proof.
Contextual replacement example:
// SAFETY: The documented owner, bounds and aliasing proof applies here. // Replace this review sketch with the facts established at the actual call.
Class: RESTRICTED_FACILITY. Action: Restricted to proved invariants and measured need; RPERF-006.
Contextual replacement example:
let byte = bytes.get(index).ok_or(Error::Bounds)?;
Class: RESTRICTED_FACILITY. Action: Restricted; RUST-030 and RUST-031, prefer typed conversion.
Contextual replacement example:
let tag = Tag::try_from(raw_tag)?;
Class: RESTRICTED_FACILITY. Action: Restricted platform owner; RUST-015 and RUST-044.
Contextual replacement example:
let service = Service::new(config);
Class: RESTRICTED_FACILITY. Action: Restricted to exact allocator/ownership contract; RUST-024.
Contextual replacement example:
// Keep the native pointer in an owner whose Drop calls the paired // native destroy operation; do not reconstruct an unrelated Box or Vec.
Class: RESTRICTED_FACILITY. Action: Prohibited routine handling; RUST-005 and RUST-006.
Contextual replacement example:
return Err(RequestError::InvalidInput);
Class: RESTRICTED_FACILITY. Action: Prohibited; RUST-037. Async mutexes require their own rationale.
Contextual replacement example:
let request = { state.lock()?.make_request() };
send(request).await?;
Class: RESTRICTED_FACILITY. Action: Prohibited; enforce RUST-025, RUST-027 and RUST-049.
Contextual replacement example:
limits.check_bytes(payload.len())?; queue.try_send(request)?;
Class: RESTRICTED_FACILITY. Action: Prohibited on untrusted input; RUST-048 and RUST-051.
Contextual replacement example:
Command::new(tool).arg("--").arg(path).status()?;
Class: RESTRICTED_FACILITY. Action: Prohibited; use the qualified source in RUST-047.
Contextual replacement example:
approved_entropy.fill(&mut secret_bytes)?;
Class: RESTRICTED_FACILITY. Action: Prohibited; scoped justified exceptions under RUST-001 and RUST-002.
Contextual replacement example:
#[expect(clippy::unused_async, reason = "trait contract requires async")]
async fn ready(&self) {}
Class: RESTRICTED_FACILITY. Action: Prohibited; RUST-011, RUST-013 and a versioned interface.
Contextual replacement example:
#[repr(C)]
struct ByteView {
data: *const u8,
len: usize,
}
Class: RESTRICTED_FACILITY. Action: Restricted to a documented transfer/leak protocol; RUST-026.
Contextual replacement example:
writer.finish()?;
Class: RESTRICTED_FACILITY. Action: Prohibited at external boundaries; RUST-012 and RUST-020.
Contextual replacement example:
let count = usize::try_from(wire_count).map_err(|_| Error::Length)?;
Class: RESTRICTED_FACILITY. Action: Prohibited; establish release invariants before access.
Contextual replacement example:
let value = values.get(index).ok_or(Error::Bounds)?;
Class: RESTRICTED_FACILITY. Action: Prohibited; RUST-040 and a separate device contract.
Contextual replacement example:
// Use the reviewed atomic/locking protocol for shared memory. // Keep device volatile accesses in their separate hardware adapter.
Class: RESTRICTED_FACILITY. Action: Prohibited without individual review; restrictions may conflict.
Contextual replacement example:
// Enable selected restriction lints individually and retain justified // exceptions for each supported configuration.
The topic audit used the repository C standard's implementation, performance and restricted-facility families, its pitfalls catalogue and its module architecture. The table locates the corresponding Rust treatment. It compares engineering coverage; readers do not need to apply C rules to interpret the Rust requirements. Rules about headers, pointer declarator placement and C preprocessing have no direct Rust syntax equivalent. Their underlying visibility, portability and expansion concerns appear below.
| Engineering topic | Rust treatment |
|---|---|
| Naming, lifecycle verbs, source text, spacing, comments | Formatting section; RUST-001–004, RUST-061–084. |
| Column budgets, indentation, blank lines and long expressions | RUST-069–077. |
| Test names, imports, source order and ignored bindings | RUST-068, RUST-078–079, RUST-083–084. |
| Local declarations, conditions, loops, result checks, exits | RUST-005–008, RUST-016, RUST-020, RUST-045. |
| Headers, imports, module privacy and peer communication | RUST-013, RUST-017; RMOD-001–010. |
| Types, constants, enums, unions and compile-time invariants | RUST-012, RUST-018, RUST-020–023, RUST-030–031. |
| Layout, representation, wire formats, ABI and alignment | RUST-011–013, RUST-023–024, RUST-029; RMOD-013–015. |
| Macros, compiler extensions, conditional compilation | RUST-052–055; RMOD-016–020. |
| Ownership, allocation, realloc, pools, arenas, cleanup | RUST-008–009, RUST-024–027, RUST-056; RMOD-011–012. |
| Provenance, pointer extent, aliasing, raw typed access | RUST-028–033; RPIT-008–017. |
| Errors, assertions, logging, callbacks, input validation | RUST-004–007, RUST-034–035, RUST-045; RPIT-014, RPIT-024. |
| Text, encoding, format boundaries and path handling | RUST-022–023, RUST-048–050. |
| Threads, locks, publication, reclamation and reentry | RUST-014–015, RUST-033, RUST-036–041; RMOD-021–023. |
| Async cancellation, partial I/O and resource inheritance | RUST-034–039, RUST-044, RUST-046. |
| Overflow, shifts, division, floating-point exceptional values | RUST-012, RUST-020–021. |
| MMIO, DMA, signals, assembly and real-time progress | RUST-042–044; RPERF-010–014; RMOD-024. |
| Authentication, authorization, filesystem/network ingress | RUST-045, RUST-048–051; RMOD-025. |
| Secrets, fault injection and protected effect sequences | RUST-050, RUST-060; RMOD-025–026. |
| Clocks, resource budgets, stack and exhaustion | RUST-025, RUST-027, RUST-043, RUST-047. |
| Crash consistency and persistent updates | RUST-045–046; RPIT-036. |
| Dependencies, generated/imported code, loaders and plugins | RUST-051–055; RMOD-017–020, RMOD-027. |
| Performance evidence, reference/backend equivalence | RPERF-001–006, RPERF-015–018; RMOD-028–029. |
| Cache lines, coherence, contention, wait/wake, remote frees | RPERF-007–010. |
| Store forwarding, split accesses, 4 KiB aliasing, store buffers | RPERF-010. |
| NUMA, TLB, residency, page walks and cache coloring | RPERF-011. |
| Branching, inlining, code size, indirect and return prediction | RPERF-005, RPERF-012. |
| Prefetch, streaming stores, write combining and device layout | RPERF-013–014. |
| ISA dispatch, vector length, code caches and invalidation | RPERF-015–016. |
| Build/link stages, exports, stripping, hardening, release ABI | RMOD-016–020, RMOD-027, RMOD-030. |
| Traceability, deviations, test modes, docs and static evidence | RUST-002, RUST-058–060; RMOD-026, RMOD-031–032. |
Web references below were consulted on 2026-09-22. Rust documentation URLs track upstream and do not constitute an immutable compiler specification. The repository commit containing this guide fixes the local rule wording. For a product audit, archive the adopted source revision or content digest alongside its rule mapping, date, profile, maturity and exceptions. A retrieval date alone does not pin future website content.
| Source | Role and adoption boundary |
|---|---|
| Rust Style Guide, API Guidelines | Formatting and public API conventions; project rules remain explicit. |
| Rust Reference, Rust Book, Edition Guide | Semantics, idioms and migration; select the actual compiler/edition. |
| Clippy | Compiler-matched diagnostics; select lint policy rather than treating all lints as laws. |
| Microsoft Pragmatic Rust Guidelines | Identified engineering recommendations; evaluate their library/application context. |
| ANSSI Secure Rust Guidelines | Security review context; consulted site is unstable and excludes async Rust. |
| rust-analyzer style | Component boundaries and complexity; its internal conventions are project-specific. |
| Standard Library Developers Guide | Safety comments and library implementation review; std-only facilities are not general APIs. |
| Linux Rust guidelines, Fuchsia unsafe guidance | Local proof comments and full invariant-boundary review. |
| Rustonomicon FFI, Embedded Rust Book | Low-level and target-specific reasoning, checked against the Reference and API contracts. |
| Safety-Critical Rust Coding Guidelines | Developing 0.1 guidance; adopt reviewed rules individually with maturity and revision. |
| Consortium standards matrices | Applicability research; unfinished mappings are not conformance evidence. |
| MISRust research | Mapping of MISRA C++:2023 concerns; not an official Rust coding standard. |
| FLS general scope | Compiler-validation reference with an explicit edition/compiler scope; verify it matches the target. |
| UCG Reference | Largely archived guidance; maintained glossary is supplementary, not sole unsafe authority. |
| Performance Book, Atomics and Locks | Measurement and synchronization reasoning; hardware observations need target validation. |
| Effective Rust, Rust Design Patterns | Design alternatives and tradeoffs, not universal prohibitions. |
| Rust for Rustaceans | Advanced background; check the edition's errata before relying on an example. |
| High Assurance Rust, Comprehensive Rust | Further study and teaching; not qualification evidence. |
| Compiler development conventions | Exhaustive matching and review practices in a compiler-specific context. |
| Tokio shared state and select | Async-profile behavior; pin the actual executor/library version. |
The FLS states a particular edition and compiler scope; do not silently apply it to another profile. The UCG introduction directs readers to current documentation and does not supply a complete current unsafe specification. Preserve uncertainty when aliasing or provenance details remain unsettled. For MISRA/CERT cross-references, record the exact source edition and resolve inconsistent labels before adopting a mapping.