Skip to content

Latest commit

 

History

History
162 lines (111 loc) · 6.33 KB

File metadata and controls

162 lines (111 loc) · 6.33 KB

Contributing

We welcome contributions! Please feel free to look through Issues and submit Pull Requests.

Important

  • When creating a PR, please ensure a corresponding issue has first been opened. The issue should detail the motivation for the changes, expected behaviours and, if the issue relates to bugs, it should include a minimal reproducible example.
  • When adding new features, please include corresponding tests to ensure these are well-tested and behave as expected.
  • Please ensure all PRs pass just verify before submission.

Development Environment

This project uses Nix to manage the development environment.

  1. Install Nix Package Manager.
  2. Install nix-direnv (recommended) for automatic environment loading.

To set up the environment:

# If using direnv
direnv allow

# Or manually enter the shell
nix develop

This will provide a shell with the correct Rust version and dependencies.

Rebuilding the Dev Shell

nix-direnv caches the dev shell for performance. If devenv/flake.nix or devenv/flake.lock changes (e.g., after pulling new commits that update dependencies or add tools), the cache may be stale and new tools will be missing from your PATH.

Signs the cache is stale:

  • A tool listed in devenv/flake.nix is not found (e.g., lychee: command not found).
  • direnv export output says "Using cached dev shell" after you know the flake changed.
  • A just recipe fails with a missing command even though the tool is in the flake.

To rebuild:

# Remove the cached shell and reload
rm -f .direnv/flake-profile* .direnv/nix-direnv.*
direnv allow

If using nix develop directly instead of direnv, exit and re-enter the shell.

Building and Testing

All commands are run via just recipes defined in the project's justfile. Never run cargo directly; the justfile handles Nix environment setup automatically.

just fmt     # Format all files (Rust, Nix, Markdown, YAML, TOML)
just clippy  # Run clippy
just test    # Run all tests (cached; only re-runs when content changes)
just doc     # Build docs (must produce zero warnings)
just deny    # Check licenses and advisories with cargo-deny
just verify  # Run fmt, check, clippy, deny, doc, test in order
just clean   # Remove build artifacts and test cache

Run just --list to see all available recipes.

Filtered command output

When a command is expected to produce a large amount of output, use just filtered instead of writing an ad-hoc shell pipeline. The first argument is the just recipe to run, the second argument is a ripgrep regex used to select output lines, and the remaining arguments are forwarded to the selected recipe.

just filtered check '^(error|warning|[[:space:]]*-->)' -p fp-library --lib
just filtered test '^(test .* \.\.\. FAILED|failures:|error)' -p fp-library -- prop_

just filtered preserves the selected recipe's exit status, rejects unsupported recipes and unsafe forwarded arguments, and limits filtered matches so accidental broad filters do not dump full logs.

Snapshot Tests

The HM type signature generation system uses insta snapshot tests to guard against regressions. If you change the signature rendering code in fp-macros, snapshots may need updating.

# Run snapshot tests to see if any changed
just test -p fp-macros --lib -- snapshot

# Review and accept/reject changed snapshots interactively
just cargo insta review

# Accept all changed snapshots without review
just cargo insta accept

You can also review snapshots manually by running the tests with INSTA_UPDATE=new and inspecting the .snap.new files in fp-macros/src/documentation/snapshots/.

When regenerating snapshots, make sure the tests actually rerun. The just test cache key is based on tracked file contents and test arguments, not environment variables such as INSTA_UPDATE. If you are rerunning the same test command to regenerate snapshot files, run just clean first to clear the cached test output. The just test banner lines (for example, === Running tests ===) are terminal output only; they are not written into snapshot files.

Compile-Fail Tests (trybuild)

Both fp-macros and fp-library use trybuild for compile-fail tests. These are .rs files in tests/ui/ that must fail to compile, with expected compiler output stored in matching .stderr golden files.

If your changes alter error messages (e.g., changing a proc macro's error output, renaming types, or moving modules), the .stderr files need updating.

Signs a trybuild test is stale:

  • Test output shows a diff between expected and actual compiler stderr.
  • The diff contains changed file paths, line numbers, or error wording.

To update:

# Clear cached test output so TRYBUILD=overwrite reruns the tests
just clean

# Overwrite all stale .stderr files with current compiler output
TRYBUILD=overwrite just test

# Or update only a specific crate's tests
TRYBUILD=overwrite just test -p fp-macros
TRYBUILD=overwrite just test -p fp-library

Always review the updated .stderr files before committing to ensure the new error messages are correct and intentional.

The just test banner lines (for example, === Running tests ===) are terminal output only; they are not part of the compiler stderr captured by trybuild.

Project Structure

See the Project Structure documentation.

Release Process

For maintainers, the release process is documented in release-process.md.

Benchmarking

This project uses Criterion.rs for benchmarking to ensure zero-cost abstractions and detect performance regressions.

just bench -p fp-library                               # To run all benchmarks
just bench -p fp-library --bench benchmarks -- --list  # To list available benchmarks
just bench -p fp-library --bench benchmarks -- Vec     # To run a specific benchmark (e.g., `Vec`)

Benchmark reports are generated in target/criterion/report/index.html.