# Contributing to Surelock ## Prerequisites This project uses [Nix](https://nixos.org/) for reproducible development environments. ```sh nix develop menu # list available commands ``` ## Building ```sh cargo build cargo build --all-features cargo build --no-default-features # no_std check ``` ## Testing ```sh cargo test # all tests (unit, integration, doc, property, compile-fail) cargo test --doc # doc tests only cargo test --test integration # integration tests only cargo test --test property # property tests (bolero) cargo test --test compile_fail # compile-fail tests (trybuild) ``` ## Linting ```sh cargo clippy --all-targets cargo clippy --all-targets --all-features cargo fmt --check cargo doc # check for doc warnings ``` ## Project Structure ``` src/ ├── acquirable.rs Acquirable<'a> trait (internal) ├── acquirable/tuples.rs Tuple impls 2-12 ├── id.rs LockId ├── key.rs MutexKey, lock_scope, try_lock_scope ├── key_handle.rs KeyHandle ├── key_voucher.rs KeyVoucher ├── level.rs Level, IsLevel, LockAfter, etc. ├── locksmith.rs Locksmith ├── mutex.rs Mutex ├── mutex/guard.rs MutexGuard ├── raw_mutex.rs RawMutex trait ├── raw_mutex/std_mutex.rs StdMutex backend ├── raw_mutex/lock_api_adapter.rs lock_api bridge └── set.rs LockSet tests/ ├── integration.rs Full lifecycle tests ├── lock_order.rs Level declaration tests ├── compile_fail.rs Compile-fail test runner ├── compile_fail/*.rs Individual compile-fail cases └── property.rs Property tests (bolero) design/ Published design docs ├── README.md Architecture overview ├── ROADMAP.md Planned features for v2+ └── comparison/ Comparisons with prior art .ignore/ Internal design notes (gitignored, not published) ├── CONTEXT.md Codebase overview ├── DESIGN.md Architecture reference ├── DECISIONS.md ADRs (Architecture Decision Records) ├── ALTERNATIVES.md Approaches considered ├── TODO.md Task list └── CRITICAL_SECTION_BACKEND.md no_std backend sketch ``` ## Unsafe Policy `#![deny(unsafe_code)]` at the crate level. Only modules that need `unsafe` opt in via `#![allow(unsafe_code)]`: - `raw_mutex.rs` -- `unsafe trait RawMutex` - `raw_mutex/std_mutex.rs` -- `unsafe impl` for StdMutex - `raw_mutex/lock_api_adapter.rs` -- blanket `unsafe impl` - `mutex.rs` -- `unsafe impl Send/Sync` - `mutex/guard.rs` -- `Deref`/`DerefMut` on `UnsafeCell` - `key_voucher.rs` -- `unsafe impl Send` All other modules are fully safe. Adding `unsafe` to a new module requires justification. ## Naming Conventions | Type | Name | Variable | |--------------|-----------------|-------------| | Factory | `Locksmith` | `smith` | | Voucher | `KeyVoucher` | `voucher` | | Per-thread | `KeyHandle` | `handle` | | Scope key | `MutexKey` | `key` | | Guard | `MutexGuard` | `guard` | | Lock group | `Acquirable` | -- | | Pre-sorted | `LockSet` | `set` | ## Adding a New Level Trait Level impls are generated by macros in `src/level.rs`. To change the default count or add a new trait to the level system: 1. Update the `generate_level_impls!` macro 2. Update the `#[cfg]` blocks for feature-gated counts 3. Run `cargo test` -- property tests verify level ordering invariants ## Adding a New Tuple Arity Tuple `Acquirable` impls are in `src/acquirable/tuples.rs`. The 2-tuple supports multi-level (different `Lvl` per element); arities 3-12 require same level. To add a multi-level impl for higher arities, see the 2-tuple impl as a reference. ## Compile-Fail Tests Compile-fail tests use `trybuild`. Each test case is a `.rs` file in `tests/compile_fail/` with a corresponding `.stderr` file. To update expected output after a change: ```sh TRYBUILD=overwrite cargo test --test compile_fail ``` ## Design Documents Published design docs live in `design/`: - `design/README.md` -- architecture overview and design principles - `design/ROADMAP.md` -- planned features for v2+ - `design/comparison/` -- detailed comparisons with `happylock` and `lock_tree` Internal design notes live in `.ignore/` (gitignored, not published): - `DECISIONS.md` -- numbered ADRs with rationale - `DESIGN.md` -- architecture reference - `TODO.md` -- task list with checkbox notation When making design decisions, add an ADR to `.ignore/DECISIONS.md`.