rust-lang/rust
github.com/rust-lang/rust ↗ · 4000 files · 28.0 MB · scan capped
[Website][Rust] | [Getting started] | [Learn] | [Documentation] | [Contributing] This is the main source code repository for [Rust].
Overview
This is rust-lang/rust, the monorepo for the Rust programming language: it contains the rustc compiler (~70 rustc_* crates under compiler/), the standard library (library/core, alloc, std), the 'bootstrap' build system invoked via ./x, the compiletest test harness, in-tree documentation including the rustc-dev-guide, and externally-maintained tool subtrees (clippy, rustfmt, miri, rust-analyzer). The rustc binary itself is a thin shell (compiler/rustc/src/main.rs) that delegates to rustc_driver_impl::run_compiler, which orchestrates parsing, macro expansion, the demand-driven query system (TyCtxt), and a pluggable codegen backend (default: LLVM). Everything — building, testing, formatting, dist — flows through the ./x bootstrap entry point rather than direct cargo invocations.
System map
The repo is a Cargo workspace whose members are the rustc binary crate plus ~35 in-tree tools; the compiler proper is ~70 rustc_* crates under compiler/, the standard library is a separate workspace under library/, and src/bootstrap is a self-contained build system excluded from the workspace. The rustc binary is a stub that links rustc_driver as a dylib and calls rustc_driver::main(). The heart of the compiler is the query system defined in compiler/rustc_middle/src/queries.rs and wired together in rustc_interface::passes::DEFAULT_QUERY_PROVIDERS. Build/test orchestration is bootstrap (x.py -> src/bootstrap), and CI is GitHub Actions whose job matrix is computed by the in-tree citool crate from src/ci/github-actions/jobs.yml.
- The root Cargo.toml defines a workspace with members compiler/rustc, src/build_helper, src/rustdoc-json-types, the rustc-std-workspace shims, and ~35 tools under src/tools/ (compiletest, tidy, miri, clippy, rustfmt, opt-dist, etc.); src/bootstrap, compiler/rustc_codegen_cranelift, compiler/rustc_codegen_gcc, and tests/rustdoc-gui are explicitly excluded.
- The rustc binary entrypoint is compiler/rustc/src/main.rs: it uses #![feature(rustc_private)] to link rustc_driver as a dylib, calls rustc_driver::override_c_allocator_in_binary!() so the whole process (including LLVM's C++ allocations) uses jemalloc, and its main() is just rustc_driver::main().
- compiler/rustc_driver is an intentionally empty crate that re-exports rustc_driver_impl so that rustc_driver_impl can be compiled in parallel with the other rustc_* crates.
- rustc_driver_impl::run_compiler is the primary compiler entry point: it expands @-argfiles (args::arg_expand_all), parses options (handle_options), builds session options (config::build_session_options), handles --explain, builds an interface::Config, and calls interface::run_compiler with a callback that runs the whole pipeline.
- rustc_interface::run_compiler sets the parallel/dyn-thread-safe mode, initializes the jobserver, builds the target config, loads the codegen backend (dylib or injected via Config::make_codegen_backend), builds the Session, parses --cfg/--check-cfg, builds the lint store, and runs the caller's closure inside util::run_in_thread_pool_with_globals.
- The compiler is decomposed into ~70 rustc_* crates: rustc_lexer/rustc_parse (lexing/parsing), rustc_ast/rustc_hir (AST/HIR), rustc_expand (macro expansion), rustc_resolve (name resolution), rustc_hir_typeck/rustc_hir_analysis/rustc_trait_selection (type checking/traits), rustc_borrowck, rustc_mir_build/rustc_mir_transform/rustc_mir_dataflow (MIR), rustc_monomorphize, rustc_metadata (rmeta), and rustc_codegen_ssa/rustc_codegen_llvm (codegen).
- The query system is declared in compiler/rustc_middle/src/queries.rs inside rustc_queries proc-macro blocks (implemented in compiler/rustc_macros/src/query.rs), which generate TyCtxt methods, provider structs, caching, and dep-graph integration; the default providers are assembled in rustc_interface::passes::DEFAULT_QUERY_PROVIDERS which calls each subcrate's provide() function.
- Build entry: ./x (sh), x.ps1 (Windows), or x.py all funnel to src/bootstrap/bootstrap.py, which verifies/downloads the stage0 toolchain pinned in src/stage0 (with sha256 verification of downloads), compiles the bootstrap crate, and execs it; the Rust side starts at src/bootstrap/src/bin/main.rs -> bootstrap::cli_main::main -> Flags::parse -> Config::parse.
- Bootstrap staging: stage0 (downloaded beta compiler) builds stage1 rustc+std, stage1 builds stage2; output lives under build/ with downloaded tarballs cached in build/cache; the flow is documented in src/bootstrap/README.md.
- library/ is its own Cargo workspace (library/Cargo.toml, resolver=1) with members std, sysroot, coretests, alloctests; library/sysroot is a dummy crate whose public dependencies (proc_macro, std, test, optional profiler_builtins) force all required crates into the distributed sysroot.
- There are three codegen backends: rustc_codegen_llvm (in-workspace, FFI through compiler/rustc_llvm and the src/llvm-project submodule), and the workspace-excluded subtrees compiler/rustc_codegen_cranelift and compiler/rustc_codegen_gcc.
- CI is GitHub Actions: .github/workflows/ci.yml runs a calculate_matrix job that executes `cargo run --locked calculate-job-matrix` in src/ci/citool over src/ci/github-actions/jobs.yml, then fans out matrix jobs that run src/ci/scripts/run-build-from-ci.sh; a 'bors' GitHub environment with S3/secrets is only attached for automation/bors/* branches.
Feature catalog
User-facing surface = the rustc CLI plus the ./x build CLI plus the bundled tools and libraries. rustc supports the usual compile driver flags plus --print, --explain, -Zunpretty pretty-printing, --check-cfg validation, pluggable codegen backends via -Zcodegen-backend, incremental compilation, MIR emission, and hundreds of lints. ./x exposes subcommands like build/check/test/doc/dist/fmt/miri implemented as bootstrap Steps. The repo also ships rustdoc (with JSON output), the test harness crate library/test, and subtrees for clippy/rustfmt/miri/rust-analyzer.
- rustc CLI option handling lives in rustc_driver_impl: handle_options supports -Zhelp/--help early-exit modes, --explain <code> routes to handle_explain, and --print requests are served by print_crate_info before any input is required.
- --check-cfg arguments are parsed by rustc_interface::parse_check_cfg into a CheckCfg of expected cfg names/values supporting cfg(name, values(...)), any(), none(); passing any --check-cfg enables exhaustive_names and exhaustive_values by default.
- Pretty-printing/unpretty modes (-Zunpretty) are handled in rustc_driver_impl::pretty::print, with PrintExtra::NeedsAstMap running early_lint_checks through TyCtxt when an AST map is needed, and MIR emission via pretty::emit_mir when OutputType::Mir is requested.
- Codegen backends are pluggable: rustc_interface::util::get_codegen_backend loads a backend dylib and resolves the __rustc_codegen_backend symbol (load_backend_from_dylib), selected via -Zcodegen-backend=<name> or Config::make_codegen_backend.
- rustc's lint system registers builtin lint passes through rustc_lint: register_builtins registers BuiltinCombinedPreExpansionLintPass, BuiltinCombinedEarlyLintPass, BuiltinCombinedLateLintModPass, foreign_modules, and hardwired lints into the LintStore; drivers can add more via Config::register_lints.
- -Ztime-passes is implemented by TimePassesCallbacks in rustc_driver_impl, which records total time/RSS around catch_with_exit_code(run_compiler) and prints a 'total' entry unless --print output would be corrupted.
- Incremental compilation is a first-class feature: rustc_incremental persists the dep graph and query results on disk under the incremental directory (persist/{save,load,file_format,work_product}.rs) and create_and_enter_global_ctxt loads the query-result cache before running queries.
- rustdoc lives in src/librustdoc with the binary crate at src/tools/rustdoc; it extern-crates the rustc_* internals (rustc_driver, rustc_interface, rustc_hir, etc.) loaded implicitly from the sysroot, and supports JSON output via src/rustdoc-json-types.
- The standard library ships core (dependency-free primitives), alloc, std (with a sys/ platform-abstraction layer containing pal/fs/net/thread modules), plus supporting crates: test (built-in test harness), backtrace, std_detect, portable-simd, panic_abort/panic_unwind, unwind, and compiler-builtins.
- ./x subcommands are parsed by bootstrap's Flags/Subcommand (src/bootstrap/src/core/config) and dispatched to Step implementations under src/bootstrap/src/core/build_steps/ (check.rs, clean.rs, compile.rs, dist.rs, doc.rs, format.rs, install.rs, llvm.rs, perf.rs, run.rs, setup.rs, test.rs, tool.rs, vendor.rs, gcc.rs, clippy.rs).
- compiletest (src/tools/compiletest) is the compiler test runner supporting 15 TestModes: pretty, debuginfo, codegen, rustdoc-html, rustdoc-json, codegen-units, incremental, run-make, ui, rustdoc-js, mir-opt, assembly, coverage-map, coverage-run, crashes.
- tidy (src/tools/tidy) is the repo style/consistency checker run by `./x test tidy`: it enforces alphabetical-order markers (tidy-alphabetical-start/end), license/deps rules (deps.rs, extdeps.rs), error-code registration, UI test conventions, unstable-book entries, target policy, and more via per-check modules.
Data flow
Data enters as a source file (or string) plus CLI options, is lexed/parsed into an AST, expanded and lowered to HIR, then nearly everything else is demand-driven through the TyCtxt query system: type checking, trait solving, borrow checking, MIR construction/transforms, monomorphization, and finally codegen through a CodegenBackend trait to object files and a linked binary. Cross-crate state travels via rustc_metadata .rmeta blobs in rlibs/dylibs; incremental state is a serialized dep-graph+query cache; diagnostics flow out through rustc_errors' DiagCtxt. Bootstrap's data flow is stage0 binaries -> stage1 artifacts -> stage2 artifacts under build/.
- Input boundary: run_compiler builds an interface::Config from CLI matches — Input::File/Str, output dir/file, crate_cfg/crate_check_cfg, and an optional FileLoader; the default RealFileLoader reads from disk but the hook exists for e.g. rust-analyzer VFS.
- Text -> tokens -> AST: rustc_lexer produces tokens, rustc_parse (new_parser_from_source_str / passes::parse) produces ast::Crate; only the crate root is parsed initially, submodules are parsed during macro expansion.
- AST -> HIR: create_and_enter_global_ctxt forces tcx.resolver_for_lowering() which runs rustc_resolve + rustc_ast_lowering to produce resolutions and lowered HIR inside the GlobalCtxt; the 'tcx lifetime originates in this function's gcx_cell/arena setup.
- All mid/late compilation state is owned by the query system: queries.rs declares each query's key/value types and modifiers (caching, arena allocation, incremental), rustc_macros::rustc_queries generates TyCtxt accessors, and tcx.ensure_ok().analysis(()) drives typeck/borrowck/MIR construction.
- Provider wiring: each rustc_* crate exposes a provide() that fills fields of the generated Providers table; DEFAULT_QUERY_PROVIDERS chains ~25 such provide() calls, then codegen_backend.provide() and the Config::override_queries hook can overwrite individual providers before the GlobalCtxt is created.
- Codegen boundary: Linker::codegen_and_build_linker runs the backend's codegen queries producing object files/modules, then linker.link(sess, incr_comp_session, codegen_backend) runs outside the GlobalCtxt so the 'tcx arena can be freed earlier.
- Backend abstraction: rustc_codegen_ssa::traits::CodegenBackend defines the contract (name, init, target_config, provide, codegen methods); rustc_codegen_llvm::LlvmCodegenBackend is the default implementation bridging to LLVM via compiler/rustc_llvm FFI.
- Cross-crate metadata: rustc_metadata encodes crate metadata (EncodedMetadata) into .rmeta sections inside rlibs/dylibs and reads dependencies back through creader.rs/locator.rs/native_libs.rs, including the MetadataLoaderDyn interface the backend supplies.
- Incremental persistence: rustc_incremental::persist::{load,save,file_format,work_product,fs} manage an on-disk dep graph and query-result cache; create_and_enter_global_ctxt calls setup_dep_graph and rustc_incremental::load_query_result_cache before queries run.
- Dependency info output: passes::write_dep_info and passes::write_interface run inside the global-ctxt closure; Session exposes env_depinfo/file_depinfo that a driver's Config::track_state callback can populate for dep tracking.
- Diagnostics flow: everything reports through rustc_errors Diag/DiagCtxt built on DiagMessage (Str or inline Fluent); early errors before a Session exists go through EarlyDiagCtxt, and ICEs are captured by install_ice_hook writing a report to config.ice_file.
- Bootstrap data flow: bootstrap.py reads src/stage0 for pinned toolchain hashes and downloads from static.rust-lang.org/ci-artifacts; the Rust bootstrap reads bootstrap.toml (defaults in src/bootstrap/defaults, schema in bootstrap.example.toml) and produces staged artifacts under build/.
Behavior traces
Three flows traced end-to-end. (1) ./x build: x.py -> bootstrap.py downloads stage0 per src/stage0 -> builds bootstrap binary -> cli_main::main -> Flags::parse -> Config::parse -> out/lock -> Builder runs Step descriptions. (2) rustc hello.rs: main.rs -> rustc_driver_impl::main -> run_compiler -> interface::run_compiler -> parse -> create_and_enter_global_ctxt -> resolver_for_lowering -> analysis -> Linker::codegen_and_build_linker -> link. (3) ./x test: bootstrap test steps build compiletest -> run_tests walks suite dirs -> directive parsing -> per-mode runtest runners -> snapshot diffing. CI is a fourth: ci.yml -> citool matrix -> run-build-from-ci.sh -> x.
- Build startup order: x.py adds src/bootstrap to sys.path and calls bootstrap.main(); bootstrap.py verifies python>=3.x, reads src/stage0 pins, downloads stage0 rustc/cargo tarballs with sha256 verification into build/cache, compiles the bootstrap crate, then execs it.
- Bootstrap main order: src/bootstrap/src/bin/main.rs -> cli_main::main installs a panic hook that prints the active StepStack, parses Flags then Config, acquires a lock file at config.out.join("lock") unless bypass_bootstrap_lock, then runs the Builder.
- Step dispatch: Builder::get_step_descriptions uses the describe! macro per Kind to map CLI paths to Step impls; run_step_descriptions executes each matching Step's run() in dependency order (builder/mod.rs).
- rustc process startup order: rustc_driver_impl::main -> init_rustc_env_logger -> signal_handler::install -> TimePassesCallbacks::default -> install_ice_hook(DEFAULT_BUG_REPORT_URL) -> install_ctrlc_handler (sets rustc_const_eval::CTRL_C_RECEIVED then exits after 100ms) -> catch_with_exit_code(run_compiler).
- Compile pipeline order inside run_compiler: arg_expand_all -> handle_options -> build_session_options -> make_input/make_output -> interface::run_compiler -> passes::parse -> (optional pretty-print early exit) -> create_and_enter_global_ctxt -> resolver_for_lowering -> write_dep_info/write_interface -> tcx.ensure_ok().analysis -> Linker::codegen_and_build_linker -> linker.link.
- Session construction order inside interface::run_compiler: set_dyn_thread_safe_mode -> jobserver::initialize -> build_target_config -> build_early_session -> get_codegen_backend (dylib __rustc_codegen_backend or make_codegen_backend) -> codegen_backend.init -> build_session -> target_config -> parse_cfg/add_configuration -> parse_check_cfg -> lint store via register_lints.
- GlobalCtxt creation order in create_and_enter_global_ctxt: pre_configure_attrs -> get_crate_name -> collect_crate_types -> StableCrateId::new -> build_output_filenames -> setup_dep_graph -> CStore/Definitions/untracked construction -> load_query_result_cache -> clone DEFAULT_QUERY_PROVIDERS -> codegen_backend.provide -> override_queries hook -> TyCtxt::create_global_ctxt with OnceLock gcx_cell and WorkerLocal arenas.
- Test-run order: ./x test -> bootstrap build_steps/test.rs builds and runs the compiletest binary -> compiletest::run_tests installs a panic hook, raises the fd limit, sets __COMPAT_LAYER=RunAsInvoker on Windows, walks tests/<suite> dirs collecting files -> directives parsing (FileDirectives/DirectivesCache) -> executor schedules CollectedTests -> runtest::<mode> modules execute compile/run and diff .stderr/.stdout snapshots.
- CI job order: ci.yml 'calculate_matrix' runs citool calculate-job-matrix over jobs.yml -> each matrix job checks out, runs ~15 setup scripts under src/ci/scripts (free-disk-space, install-sccache/clang/ninja/mingw, verify-channel, verify-line-endings, verify-stable-version-number) -> builds citool -> run-build-from-ci.sh executes the build -> doc artifacts to GitHub, dist artifacts to S3, metrics to DataDog via citool upload-build-metrics.
- Incremental compile ordering: setup_dep_graph decides whether incremental is enabled and returns an IncrCompSession; dep_graph.assert_ignored() runs during HIR construction; load_query_result_cache reads the on-disk cache; after codegen, persist::save writes the new dep graph and work products.
- Early-exit branches in run_compiler happen in a fixed order: --explain, -Whelp (describe_lints after session/lint registration), help_only, --print (print_crate_info), missing input (fatal 'no input filename given'), -Zls metadata listing, -Zlink-only process_rlink, then pretty-printing, then parse_crate_root_only.
Testing signals
Testing is dominated by compiletest-driven suites under tests/ (~27k .rs files; tests/ui alone has ~21k), organized by 15 TestModes with //@-style file directives. Unit tests live inside compiler crates as #[cfg(test)] modules and in library/coretests + alloctests. tidy enforces repo-wide hygiene. CI runs everything via the citool-computed matrix in jobs.yml, and bootstrap itself has python and Rust self-tests. Coverage tests exercise LLVM source-based coverage; rustdoc has html/json/js/gui suites.
- tests/ contains suites: ui, ui-fulldeps, mir-opt, codegen-llvm, codegen-units, assembly-llvm, coverage, coverage-run-rustdoc, crashes, debuginfo, incremental, pretty, run-make, run-make-cargo, rustdoc-html, rustdoc-js, rustdoc-js-std, rustdoc-json, rustdoc-gui, build-std; tests/ui alone contains ~21,000 .rs files.
- compiletest's TestMode enum (common.rs) maps each suite to a mode; each mode has a runner module under src/tools/compiletest/src/runtest/ (ui.rs, mir_opt.rs, codegen.rs, incremental.rs, run_make.rs, coverage.rs, debuginfo.rs, rustdoc.rs, rustdoc_json.rs, js_doc.rs, crashes.rs, pretty.rs, assembly.rs, codegen_units.rs).
- Test files declare behavior via directives parsed by src/tools/compiletest/src/directives.rs: KNOWN_DIRECTIVE_NAMES_SET in directive_names.rs, a DIRECTIVE_HANDLERS_MAP in directives/handlers.rs, ignore-*/only-*/needs-* cfg conditions precompiled in DirectivesCache, and AuxProps for aux builds.
- UI tests compare compiler output against checked-in .stderr/.stdout/.svg snapshots; compute_diff in runtest produces line diffs and `--bless` regenerates expectations (per AGENTS.md, bless runs only after a human authors new diagnostic text).
- Compiler crates carry in-tree unit tests: e.g. compiler/rustc_interface/src/tests.rs, compiler/rustc_middle/src/tests.rs, compiler/rustc_feature/src/tests.rs, rustc_target/src/tests.rs, compiletest/src/tests.rs; bootstrap has src/bootstrap/bootstrap_test.py and builder/tests.rs.
- Standard library tests live in separate crates in the library workspace: coretests and alloctests exercise core/alloc without running inside std; library/test is the user-facing #[test] harness crate.
- tidy acts as a repo-wide lint gate: src/tools/tidy/src/main.rs spawns per-check threads (style, alphabetical ordering, deps/extdeps allowlist, error_codes, features, ui_tests conventions, target_policy, unit_tests placement, edition, mir_opt_tests) runnable via ./x test tidy.
- run-make tests are driven by the src/tools/run-make-support library and live in tests/run-make and tests/run-make-cargo; coverage tests use the coverage-map/coverage-run modes sharing tests/coverage files.
- CI executes tests through the matrix in src/ci/github-actions/jobs.yml computed by src/ci/citool (calculate-job-matrix), with the actual build/test run delegated to src/ci/scripts/run-build-from-ci.sh inside ci.yml's 'run the build' step.
- rustdoc-gui tests are a separate excluded workspace (tests/rustdoc-gui in Cargo.toml exclude list) driven by src/tools/rustdoc-gui-test and compiletest's rustdoc_gui_test module.
- tests/crashes is a dedicated ICE-regression suite, and tests/debuginfo is skipped on emscripten targets (run_tests special-cases TestMode::DebugInfo for emscripten).
- Cross/remote testing is supported by src/tools/remote-test-client and remote-test-server, and test-float-parse is an optimized dev/release binary used to validate float parsing.
Risk map
The dominant risks are soundness and supply-chain. AGENTS.md explicitly classifies the query system, type checking, trait solving, MIR, borrow checking, const eval, layout, and codegen as soundness-sensitive where LLM implementation is banned. The compiler dlopens codegen backends and proc-macro dylibs, executes test binaries, downloads stage0 toolchains, and deserializes incremental caches — all trust boundaries. Several giant files (runtest.rs ~3.2k lines, queries.rs ~2.9k) concentrate coupling, and externally-maintained subtrees must not be edited in-place.
- AGENTS.md bans LLM implementation in soundness-sensitive areas — explicitly naming the query system, type checking, trait solving, MIR construction/optimization, borrow checking, const evaluation, normalization/semantic caches, layout/validity, and codegen — and requires a failing regression test before any bug fix.
- Codegen backend loading is a dlopen boundary: load_backend_from_dylib uses rustc_metadata::load_symbol_from_dylib to resolve __rustc_codegen_backend from a path derived from -Zcodegen-backend or the sysroot; a malicious/mismatched dylib executes arbitrary code in-process.
- bootstrap.py downloads stage0 compilers and CI LLVM over HTTPS and verifies sha256 against src/stage0 checksums; a stale/unchecksummed URL raises but any checksum drift blocks builds entirely (single trust anchor).
- The incremental on-disk cache (dep graph + query results + work products) is a hand-rolled binary format in rustc_incremental::persist::file_format — corruption or version skew here miscompiles incrementally or crashes; load_query_result_cache silently consumes it at GlobalCtxt creation.
- ICE handling writes a crash report to config.ice_file and installs a ctrlc handler that sets rustc_const_eval::CTRL_C_RECEIVED then hard-exits after 100ms — a safety valve that can truncate in-flight diagnostic/report writes.
- tidy's main() sets RUSTC_BOOTSTRAP=1 in-process to let Cargo read unstable manifest features — an env var that also unlocks unstable rustc features if it leaks into other subprocesses.
- Externally maintained subtrees (src/tools/cargo, clippy, rustfmt, miri, rust-analyzer, rustc_codegen_cranelift/gcc, llvm-project) are banned from in-place edits; CONTRIBUTING.md and AGENTS.md route changes to their owning repos — a major trap for agents editing the wrong tree.
- Concurrency blast radius: rustc_data_structures::sync::set_dyn_thread_safe_mode must be called before any Lock creation, and the jobserver is initialized from inherited MAKEFLAGS fds — misordered init or a misconfigured jobserver produces subtle parallel-frontend failures (warns 'build environment is likely misconfigured').
- Hotspots of coupling: compiler/rustc_driver_impl/src/lib.rs (1686 lines) sequences the entire pipeline; rustc_interface/src/passes.rs (1523) owns provider wiring and GlobalCtxt construction; rustc_middle/src/queries.rs (2905) is a macro-dense registry every subcrate's provide() feeds into — edits there have compiler-wide blast radius.
- compiletest executes compiled test binaries and on Windows mutates the process-global error mode (SetErrorMode SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX) plus sets __COMPAT_LAYER=RunAsInvoker — global state that is inherited by all child test processes.
- rustc_parse asserts at compile time that rustc_lexer, rustc_span, unicode-normalization, and unicode-width all agree on UNICODE_VERSION — dependency version drift here is a hard panic, so unicode-crate bumps must be coordinated.
- The jemalloc override in compiler/rustc/src/main.rs replaces malloc for the whole process including LLVM's C++ allocations via jemalloc-sys's override_allocator_on_supported_platforms feature — allocator experiments must go through this mechanism, not #[global_allocator], or C/Rust allocator mixing occurs across the rustc<->llvm dylib boundary.
Extension points
rustc is unusually extensible: the CodegenBackend trait supports drop-in backends loaded as dylibs, Config exposes override_queries/register_lints/file_loader/make_codegen_backend/track_state/psess_created hooks for custom drivers, and the query system is a registry where adding a query is a declaration plus a provider. Bootstrap adds steps via the Step trait + describe! macro; compiletest adds modes via the TestMode enum + a runtest module + directives; tidy adds checks as modules; new targets are TOML-less spec modules; lints, features, attributes, and diagnostics are all declare-and-register tables.
- New codegen backend: implement rustc_codegen_ssa::traits::CodegenBackend (name, init, target_config, provide, codegen/link methods) and expose it via the __rustc_codegen_backend symbol in a dylib loadable by -Zcodegen-backend, or inject it via Config::make_codegen_backend in a custom driver.
- Custom drivers can override individual queries through Config::override_queries (fn(&Session, &mut Providers)) invoked after codegen_backend.provide in create_and_enter_global_ctxt — the mechanism rustc tools use to intercept analysis.
- New queries: add a `query` block in compiler/rustc_middle/src/queries.rs with key/value types and modifiers; rustc_macros::rustc_queries generates the TyCtxt accessor and Providers field; implement the provider fn and register it in the owning crate's provide() chained into DEFAULT_QUERY_PROVIDERS.
- New lints: declare_lint!/declare_lint_pass!/impl_lint_pass from rustc_lint_defs, implement an EarlyLintPass or LateLintPass in rustc_lint, and register via register_builtins' lint_vec() lists; drivers can add out-of-tree lints through Config::register_lints.
- Driver hooks in interface::Config: file_loader (custom source loading, designed for rust-analyzer's VFS), psess_created (mutate ParseSess), track_state (record env/file deps into sess.env_depinfo/file_depinfo), extra_symbols (pre-interned symbols after PREDEFINED_SYMBOLS_COUNT), using_internal_features.
- New bootstrap step: implement the Step trait (run/should_run/make_run metadata) and list it in Builder::get_step_descriptions' describe! macro for the relevant Kind; step bodies live in src/bootstrap/src/core/build_steps/.
- New compiletest suite/mode: add a TestMode variant in common.rs, a runner module under runtest/ (mod list is tidy-alphabetized), directive names in directives/directive_names.rs, and handlers in directives/handlers.rs' DIRECTIVE_HANDLERS_MAP.
- New tidy check: add a module in src/tools/tidy/src/ and spawn it from main.rs' scoped-thread section; existing examples cover style, deps, extdeps allowlists, ui_tests conventions, target_policy, edition, and alphabetical ordering.
- New compiler flag: add entries in rustc_session's options table (compiler/rustc_session/src/options.rs and options/ submodules); dep_tracking macros (hash_opt!/insert!) tie each option into incremental-crate-hash computation, and untracked options are marked [UNTRACKED]/[TRACKED_NO_CRATE_HASH].
- New target: add a spec module under compiler/rustc_target/src/spec/targets/ (335 existing target modules) — spec/json.rs also supports JSON target descriptions loaded at runtime.
- New language feature: register it in rustc_feature/src/unstable.rs (and move to accepted.rs/removed.rs on stabilization/removal); builtin attributes live in builtin_attrs.rs.
- New diagnostics: derive Diagnostic/Subdiagnostic via rustc_macros' diagnostics module and use inline Fluent DiagMessage strings; rustc_error_messages::register_functions exposes custom Fluent functions (e.g. STREQ).
Contributor handoff
AGENTS.md is the controlling document and is unusually strict: a named human reviewer must be named in-conversation before any edit, certain text categories (PR text, diagnostics, doc prose) are prohibited for LLMs, bug fixes require an observed failing test first, and all soundness-sensitive implementation is banned outright — test-only work is allowed there. External subtrees must be routed upstream. Operationally: use ./x for everything (never cargo directly), ./x fmt for formatting, ./x test tidy for style gates, bootstrap.toml for config, and expect builds/tests to run under build/. Read the in-tree rustc-dev-guide (src/doc/rustc-dev-guide) for architecture.
- Read AGENTS.md first: it defines a gating protocol — external-repo routing check, prohibited-text check, named-reviewer requirement — that must be applied before ANY repository edit, including tests, plus a test-first rule and a soundness classification before implementation.
- Never invoke cargo directly for builds/tests in this repo; ./x (x.py/x/x.ps1) is the entry point per AGENTS.md and src/bootstrap/README.md. Formatting is `./x fmt`, not rustfmt; mechanical rewrites must use an existing tool (e.g. `./x test tidy --bless`).
- Do not edit externally maintained subtrees/submodules in place — Cargo, Clippy, rustfmt, Miri, rust-analyzer, rustc_codegen_cranelift/gcc, src/llvm-project; CONTRIBUTING.md's 'Making changes to subtrees and submodules' section routes those changes to their owning repositories.
- Configuration: copy bootstrap.example.toml to bootstrap.toml (or run ./configure / ./x setup); the change-id field maps to src/bootstrap/src/utils/change_tracker.rs and warnings appear when it lags; profiles live in src/bootstrap/defaults.
- Architecture orientation docs live in-tree at src/doc/rustc-dev-guide (overview.md covers the compile pipeline); tests/COMPILER_TESTS.md redirects test-harness questions to the dev-guide's testing chapters.
- For bug fixes: add or find a failing test and observe the failure (no --bless) before touching implementation; if the affected area is soundness-sensitive (queries, typeck, traits, MIR, borrowck, const eval, layout, codegen), STOP after the test and route to #llm-mentoring on Zulip.
- Diagnostic-message edits are prohibited text: an agent may not author or rewrite user-facing diagnostic wording or .stderr expectations; after a human writes the message, snapshots may be regenerated mechanically with the existing --bless flow.
- Keep tidy-alphabetical-start/end regions sorted (seen in Cargo.toml, lib.rs files, runtest.rs mod lists); tidy enforces this plus style/edition/deps rules — run ./x test tidy before considering a change done.
- Bootstrap acquires a lock at build-dir `out/lock` (with holder PID) so concurrent ./x invocations serialize; bypass_bootstrap_lock exists but concurrent builds otherwise block.
- When adding rustc flags/queries/lints/targets, the conventions are registry-style: options.rs tables, queries.rs blocks + provide(), lint_vec() lists in rustc_lint, spec/targets modules — follow the surrounding pattern rather than inventing new wiring.
- First files to read for compiler work: compiler/rustc_driver_impl/src/lib.rs (pipeline order), compiler/rustc_interface/src/interface.rs (Config/hooks/session build), compiler/rustc_interface/src/passes.rs (providers/GlobalCtxt), compiler/rustc_middle/src/queries.rs (query registry).
- CLAUDE.md simply defers to AGENTS.md (@AGENTS.md); the LLM usage policy it cites (forge.rust-lang.org/policies/llm-usage.html) requires disclosure authored by the human and forbids Co-Authored-By trailers.
Languages
| Language | Files | Share of source |
|---|---|---|
| Rust | 38944 | 97% |
| Markdown | 1485 | docs/config |
| TOML | 631 | 2% |
| JavaScript | 166 | 0% |
| HTML | 140 | docs/config |
| Shell | 139 | 0% |
| C | 131 | 0% |
| YAML | 78 | docs/config |
Start reading here
Probable source entrypoint: Cargo.toml — inferred from the directory tree and manifest, not the upstream docs.
Source roots
src/ (985 files)
Repository structure
| Top-level path | Files |
|---|---|
src/ | 985 |
compiler/ | 985 |
library/ | 985 |
tests/ | 984 |
.github/ | 18 |
LICENSES/ | 12 |
Docs found: AGENTS.mdCLAUDE.mdCONTRIBUTING.mdREADME.md
Package
Cargo.toml — , 0 declared dependencies.
CI & config entrypoints
README.md— Repository readmeAGENTS.md— Agent instructionsCLAUDE.md— Claude instructions.github/workflows/ci.yml— GitHub Actions workflow.github/workflows/ghcr.yml— GitHub Actions workflow.github/workflows/post-merge.yml— GitHub Actions workflowcompiler/rustc/src/main.rs— Rust binary entrypointcompiler/rustc_codegen_gcc/build_system/asm-tester/src/main.rs— Rust binary entrypointcompiler/rustc_codegen_gcc/build_system/src/main.rs— Rust binary entrypointcompiler/rustc_codegen_gcc/tests/cross_lang_lto/src/main.rs— Rust binary entrypoint
Structural health signals
Average score 7.4/10 across 96 analyzed source files; 30 hotspots surfaced.
compiler/rustc_errors/src/diagnostic.rs— 1335 lines, score 4.7 (Large file, Deep nesting)compiler/rustc_builtin_macros/src/deriving/generic/mod.rs— 1421 lines, score 5 (Large file, Deep nesting)compiler/rustc_errors/src/lib.rs— 1274 lines, score 5.2 (Large file, Deep nesting)
These are deterministic review leads — size, churn, and structural signals — not proof of a bug in this project.
Recent history
c64de18c55c72026-09-22 — Auto merge of #162499 - GuillaumeGomez:subtree-update_cg_gcc_2026-09-08, r=antoyoe5b95097d9a12026-09-22 — Auto merge of #163142 - ytmimi:rustfmt-subtree-update, r=jieyouxu51aa65eabb4b2026-09-21 — chore: bump rustfmt version to v1.11.09df11a5f25a42026-09-21 — Merge commit 'e47f161c8476418e8b55b61db3bbf0338e0ab827' into rustfmt-subtree-updatee47f161c84762026-09-22 — Merge pull request #7128 from ytmimi/changelog-2026-09-21