Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contributing to Conjure Oxide

We love your input! We want to make contributing to this project as easy and transparent as possible, whether it’s:

  • Reporting a bug
  • Discussing the current state of the code
  • Submitting a fix
  • Proposing new features
  • Becoming a maintainer

Where to find us

  • We use GitHub to host code, track issues and feature requests, and accept pull requests.
  • There is also Conjure Zulip.
  • At St Andrews, we are running a Vertically Integrated Project on Conjure. If you are a student on this project, you will also be added to an MS Teams team.

GitHub Flow

Pull requests are the best way to propose changes to the codebase (we use GitHub Flow). We actively welcome your pull requests:

  1. Fork the repo, create a branch, and do not develop on main.
  2. Create a pull request as soon as you want others to be able to see your progress, comment, and/or help. Err on the side of creating the pull request too early instead of too late. Having an active PR makes your work visible, allows others to help you and give feedback. Request reviews from people who have worked on similar parts of the project.
  3. Keep the PR in draft status until you think it’s ready to be merged.
  4. Assign the PR to reviewer(s) when it’s ready to be merged.
    • If you are working as part of a group, ask for code reviews from the rest of the group. Once everyone in the group is happy, proceed to the next step.
    • Only Oz (@ozgurakgun) can merge PRs, so add him as a reviewer when you want your PR to be merged.
  5. Get your PR merged.
    • We squash-merge PRs by default. Do not worry about keeping history on your PR branch “clean”.
    • During reviewing, avoid force-pushing to the pull request, as this makes reviewing more difficult. You may force-push on draft PRs if you really want to.
    • If you are keen to keep history clean in the PR, consider using fixup commits using Git’s built-in support for fixups.
      • You can make changes to a commit by running git commit --fixup <commit>.
      • You can squash fixup commits on top of their original commits by running git rebase --autosquash main and then force pushing to the branch.
      • We have CI checks to block accidental merging of fixup! commits.
      • Also see this and this.

Reporting bugs

We use GitHub issues to track public bugs. Report a bug by opening a new issue; it’s that easy!

Write bug reports with detail, background, and sample code. Take a look at this advice from Simon Tatham for how to effectively report bugs. This is an example of a well-written bug report.

Great bug reports tend to have:

  • A quick summary and/or background
  • Specific steps to reproduce
  • What you expected would happen
  • What actually happens
  • Notes (possibly including why you think this might be happening, or stuff you tried that didn’t work)

People love thorough bug reports. I’m not even kidding.

Hygiene: code layout, style, linting

  • Run make check in the project directory to automatically check for hygiene.
  • Run make fix to apply fixes automatically.
  • Use make fix-dirty when there are uncommitted changes.
  • This is not strictly enforced, but we want to use a consistent ordering of type/domain/expression variants, unless there is a good reason not to do so. The codebase contains several places where we match on (almost) all variants of an enum. For code like this, stick to the same ordering that is used in the enum definition.

House rules

These project conventions are more specific than the general guidance above.

Tooling

  • Use the Makefile for the standard install, test, and check workflows. Prefer make targets over running cargo commands directly.

Language

  • Use British spelling in prose, comments, rustdocs, commit messages, and user-facing text.
  • Keep comments and rustdocs brief. Explain intent or behaviour, not obvious syntax.
  • Use ASCII characters unless there is a justified need to use non-ASCII characters.

Rust Code

  • Document all top-level public functions, structs, enums, and type aliases with brief rustdocs.
  • Document public fields and enum variants when their meaning is not completely obvious.
  • Do not clone a value just to ask it a question. Prefer borrowed views and iterators for checks such as lengths, predicates, lookups, and traversal; clone only data that must escape.
  • Put representation-dependent rules under types/<type>/<representation>/vertical; reserve types/<type>/horizontal for representation-independent rules.

Test Runs

  • Use MAX_EXPECTED_TIME=N to only run test cases that are expected to take up to N seconds. Omit or use MAX_EXPECTED_TIME=0 to run all tests.
  • Use TEST_CASE_TIMEOUT=N to set a per-test timeout for exhaustive tests.
  • When recording artefacts from a timeout-bounded run, record the timeout value explicitly in the relevant config.toml file.

Test Artefacts

  • Update trace files when the test output has changed for a good reason. Do not try to keep trace files unchanged for their own sake.
  • Update stats.toml files when the recorded statistics have changed for a good reason, especially when non-time features change.
  • make test-accept / ACCEPT=true also rewrites expected-time (and other timing fields) from the current run. Do not blindly commit those timing updates: runtimes are noisy across machines and load, and tiny time-only diffs create pointless churn. Prefer leaving small timing wobbles uncommitted; only land timing changes when they reflect a real, intentional shift (for example a new slow test, or a deliberate budget change). Use make test-accept-with-max-times when recording budgets over several runs: each run keeps the max of the current budget and the observed time, so a fast fluke does not lower it. To discard small timing-only changes, run ./tools/discard-config-time-changes.sh. A file is restored from HEAD only when every changed *-time value either has both old and new times <= 1 second or has an absolute change <= 10% of the HEAD value. Override these defaults with --max-time SECONDS and --max-change-percent PERCENT; use --dry-run to preview restorations. Files with larger timing changes, non-time edits, added/removed timing fields, or non-numeric timing changes are left alone.

Commits

  • Never commit code changes and test artefact/config updates in the same commit.
  • Commit code and harness changes first, with a normal Conventional Commit-style subject.
  • Commit generated or recorded test updates separately, using chore(test-suite): ... in the subject line.
  • Reserve test(test-suite): for changes to test code or harness logic.

The Book

Exists.

What We Didn’t Do

To prevent unknown unknowns, skim the documentation and What We Didn’t Do.

License

Any contributions you make will be under the Mozilla Public License. When you submit a PR, your submissions will be understood to be under the same Mozilla Public License that covers the project. Feel free to contact the maintainers if that’s a concern.

References

This document was adapted from this template and then significantly edited with project specific information.