Skip to content

Appendix C-Contributing to rustc: A Playbook

Most engineers never contribute to a compiler. The barrier is reputational ("compilers are hard"), not technical. This appendix is the on-ramp.


C.1 Mental Model

rustc is a query-driven, incrementally-compiled, multi-stage compiler whose front-end (HIR), middle (MIR), and back-end (LLVM/Cranelift codegen) are loosely coupled by a query system. You do not need to understand all of it to land a useful PR. You need to understand:

  1. The query system at a high level (queries memoize derived data; recompiles invalidate dependent queries).
  2. The MIR if you are touching borrow check, optimizations, or const-eval.
  3. The HIR and resolver if you are touching name resolution or module structure.
  4. The lint infrastructure if you are adding a lint (the easiest first PR).
  5. The diagnostic infrastructure if you are improving an error message (the easiest possible first PR).

C.2 The Pipeline, in 30 Seconds

Source
  │ Lexer ── tokens
  │ Parser ── AST
  │ Macro expansion + name resolution ── expanded AST
  │ AST → HIR lowering
  │ Type checking + trait solving (on HIR)
  │ HIR → THIR → MIR
  │ Borrow checking (on MIR)
  │ MIR optimization (inlining, const-prop, dead-code, dataflow analyses)
  │ MIR → LLVM IR (or Cranelift IR)
  │ LLVM optimization + codegen
Object code → linker → binary

Each arrow above is a query. Each query has inputs and outputs. The tcx: TyCtxt<'tcx> is the god-object that holds the query context.


C.3 Setting Up

git clone https://github.com/rust-lang/rust
cd rust
./x.py setup           # choose 'compiler' or 'library' profile
./x.py check           # ~5 min on a fast machine; sanity check
./x.py build library/std --stage 1

Edit, then:

./x.py build --stage 1 compiler/rustc
./build/host/stage1/bin/rustc --version

For most PRs, stage 1 is enough. Only stage 2 fully self-bootstraps; reserve it for final verification and ./x.py test.

Use rust-analyzer with the rustc workspace; the maintainers ship a config (.vscode/settings.json template in the repo root).


C.4 Where the Easy Wins Are

In rough order of difficulty, the on-ramp issues:

C.4.1 Diagnostic improvements

  • An error like error[E0308]: mismatched types whose note: line could be more helpful. Search the issue tracker for A-diagnostics + E-easy.
  • Touch compiler/rustc_*/messages.ftl (Fluent translations) and the corresponding *.rs site of emission. Often <30 lines.

C.4.2 New clippy lints

  • The clippy repo (rust-lang/rust-clippy) maintains a good-first-issue queue. Each lint is roughly: declare in clippy_lints/src/lib.rs, write an EarlyLintPass or LateLintPass impl, add UI tests, document.
  • Lower bar than rustc proper for review.

C.4.3 Small library PRs (library/std, library/core, library/alloc)

  • API additions need an ACP (API Change Proposal) before code; small soundness fixes do not.
  • Library team ships fast and reviews kindly; great track for a first PR.

C.4.4 Diagnostic suggestion / rustfix integration

  • Existing errors that lack - -helpsuggestions. Adding a structured suggestion thatcargo fix` can apply is high-impact and well-bounded.

C.4.5 rustdoc improvements

  • Search ranking, intra-doc-link resolution, theme tweaks. Self-contained crate (src/librustdoc/).

C.4.6 MIR optimization passes

  • compiler/rustc_mir_transform/. Each pass is a struct implementing MirPass. Adding a new pass is medium-difficulty; fixing an existing pass is easier and more common.
  • This is where the curriculum lands you by week 23. Examples of tractable PRs: tightening an existing const-prop, adding a new dataflow analysis for a specific shape.

C.4.7 Don't start here (yet)

  • Trait solver (chalkification is in flight; touching it requires deep context).
  • Borrow checker proper (Polonius is similarly in flight).
  • Codegen / LLVM interface.
  • Bootstrap.

C.5 The First-PR Workflow

  1. Pick an issue. Comment @rustbot claim to assign yourself.
  2. Write a one-paragraph plan in the issue or in a draft PR description: what you'll change, where, and how you'll test.
  3. Ask early. The t-compiler/help Zulip stream and the issue's mentor (named in the E-mentor label) want to be asked. Pre-PR clarification beats a rejected PR every time.
  4. Implement, test, format:
  5. ./x.py test compiler/rustc_<crate> --stage 1
  6. ./x.py test src/test/ui --stage 1 if you've changed UI tests (most diagnostics PRs).
  7. ./x.py fmt
  8. Open the PR referencing the issue. Add the r? reviewer suggested by the issue or r?@rustbot for triage.
  9. Address review-expect 1–3 rounds. The reviewers are unpaid volunteers; be patient and concrete.
  10. @bors r=<reviewer> approves; bors will batch and merge. Your name is in the changelog.

C.6 The Compiler Reading Map

When the dev guide is dense, these source files are the most yield-per-page reads:

File What it teaches
compiler/rustc_middle/src/ty/context.rs The TyCtxt: how everything is queried.
compiler/rustc_middle/src/mir/mod.rs MIR: Body, BasicBlock, Statement, Terminator.
compiler/rustc_borrowck/src/lib.rs The borrow checker entry point.
compiler/rustc_mir_transform/src/lib.rs MIR passes: how they're declared and ordered.
compiler/rustc_lint_defs/src/builtin.rs How lints are declared.
compiler/rustc_resolve/src/lib.rs Name resolution.
compiler/rustc_hir/src/hir.rs The HIR data model.
compiler/rustc_codegen_ssa/src/base.rs The codegen façade above LLVM.

Read in this order: MIR → borrow check → MIR transform → lints → resolver → HIR → codegen.


C.7 Adjacent Targets if rustc Is Too Heavy

  • rust-clippy-same machinery, smaller surface, faster review.
  • rust-analyzer-entirely different codebase but high-impact contributions.
  • cargo-large but well-modularized; build-system contributions.
  • rustup-small, contained.
  • miri-interpretive twin of rustc; PRs here teach you the abstract machine.
  • stdlib-library/std, library/core. Often the easiest first merge.

A merged PR in any of these is a credible signal in interviews and grant applications.


C.8 Calibration

A reasonable goal for a curriculum graduate:

  • By end of week 23: a PR open against rust-clippy (a new lint or a false-positive fix) or rust-lang/rust (a diagnostic improvement).
  • By end of capstone: that PR merged.
  • 6 months post-curriculum: a non-trivial PR-a new MIR pass, a stabilized API, a soundness fix.

These are realistic timelines. The maintainers prioritize correctness over speed; do not be discouraged by a 4-week review cycle.

Comments