diff --git a/src/parallel-rustc.md b/src/parallel-rustc.md
index c4e066306..a023deb57 100644
--- a/src/parallel-rustc.md
+++ b/src/parallel-rustc.md
@@ -1,25 +1,26 @@
# Parallel compilation
-As of November 2024,
-the parallel front-end is undergoing significant changes,
-so this page contains quite a bit of outdated information.
+As of August 2026, the parallel front-end remains under
+active development, so implementation details on this page may change.
Tracking issue:
-As of November 2024, most of the rust compiler is now
-parallelized.
-
-- The codegen part is executed concurrently by default.
- You can use the `-C
- codegen-units=n` option to control the number of concurrent tasks.
-- The parts after HIR lowering to codegen such as type checking, borrowing
- checking, and mir optimization are parallelized in the nightly version.
- Currently, they are executed in serial by default, and parallelization is
- manually enabled by the user using the `-Z threads = n` option.
-- Other parts, such as lexical parsing, HIR lowering, and macro expansion, are
- still executed in serial mode.
+As of August 2026, `rustc` is always built with support for
+parallel front-end work. The front-end covers compilation from lexing through
+the generation of backend IR. It uses one job by default; `-j`/`--jobs` or
+`--jobs-frontend` can be used to request more. See the
+[compiler job options][compiler-job-options] for details.
+
+- Within the front-end, query evaluation and several intra-query loops can run
+ concurrently. Individual stages that have not been parallelized still run
+ serially.
+- Code generation is executed concurrently by default. The `-C
+ codegen-units=n` option controls how many codegen units a crate is split into,
+ while `--jobs-backend` limits concurrent backend work.
+- The linker has a separate `--jobs-linker` limit when the selected linker
+ supports configuring its parallelism.
The following sections are kept for now but are quite outdated.
@@ -44,90 +45,62 @@ This process occurs in the [`rustc_codegen_ssa::base`] module.
The underlying thread-safe data-structures used in the parallel compiler
can be found in the [`rustc_data_structures::sync`] module.
-These data structures
-are implemented differently depending on whether `parallel-compiler` is true.
-
-| data structure | parallel | non-parallel |
-| -------------------------------- | --------------------------------------------------- | ------------ |
-| Lock\ | (parking_lot::Mutex\) | (std::cell::RefCell) |
-| RwLock\ | (parking_lot::RwLock\) | (std::cell::RefCell) |
-| ReadGuard | parking_lot::RwLockReadGuard | std::cell::Ref |
-| MappedReadGuard | parking_lot::MappedRwLockReadGuard | std::cell::Ref |
-| WriteGuard | parking_lot::RwLockWriteGuard | std::cell::RefMut |
-| MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut |
-| LockGuard | parking_lot::MutexGuard | std::cell::RefMut |
-
-- These thread-safe data structures are interspersed during compilation which
- can cause lock contention resulting in degraded performance as the number of
- threads increases beyond 4. So we audit the use of these data structures
- which leads to either a refactoring so as to reduce the use of shared state,
- or the authoring of persistent documentation covering the specific of the
- invariants, the atomicity, and the lock orderings.
-
-- On the other hand, we still need to figure out what other invariants
- during compilation might not hold in parallel compilation.
+
+The compiler no longer has separate `parallel-compiler` and non-parallel build
+configurations. Instead, `Lock` selects its synchronization mode at runtime.
+When front-end parallelism has not been requested, it uses an unsynchronized
+cell-based guard. Otherwise, it uses a `parking_lot` raw mutex. `RwLock`
+always wraps `parking_lot::RwLock`. This keeps one API while avoiding mutex
+overhead in the usual single-job front-end.
+
+Thread-safe data structures can introduce contention as the number of jobs
+increases. Uses of shared state are therefore audited and may be refactored to
+reduce sharing or documented with their invariants, atomicity, and lock order.
[`rustc_data_structures::sync`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/sync/index.html
### WorkerLocal
[`WorkerLocal`] is a special data structure implemented for parallel compilers.
-It holds worker-locals values for each thread in a thread pool.
-You can only
-access the worker local value through the `Deref` `impl` on the thread pool it
-was constructed on.
-It panics otherwise.
-
-`WorkerLocal` is used to implement the `Arena` allocator in the parallel
-environment, which is critical in parallel queries.
-Its implementation is
-located in the [`rustc_data_structures::sync::worker_local`] module.
-However,
-in the non-parallel compiler, it is implemented as `(OneThread)`, whose `T`
-can be accessed directly through `Deref::deref`.
+It holds one value for each possible thread in the current front-end worker
+registry. The `Deref` implementation selects the value for the registered
+current thread and panics when called from a thread outside that registry.
+
+`WorkerLocal` is used for the compiler arenas and for per-worker query and
+dependency-graph state. Its implementation is located in the
+[`rustc_data_structures::sync::worker_local`] module.
[`rustc_data_structures::sync::worker_local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/sync/worker_local/index.html
[`WorkerLocal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/sync/worker_local/struct.WorkerLocal.html
-## Parallel iterator
+## Parallel helpers
-The parallel iterators provided by the [`rayon`] crate are easy ways to
-implement parallelism.
-In the current implementation of the parallel compiler,
-we use [a custom fork of `rayon`][rustc-rayon] to run tasks in parallel.
+The compiler contains an in-tree [`rustc_thread_pool`], a fork of Rayon core.
+Helpers in [`rustc_data_structures::sync`] use that pool when front-end
+parallelism is enabled and preserve serial behavior otherwise.
-Some iterator functions are implemented to run loops in parallel
-when `parallel-compiler` is true.
+Some of the main helpers are:
-| Function(Omit `Send` and `Sync`) | Introduction | Owning Module |
-| ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------------- |
-| **par_iter**(t: T) -> T::Iter | generate a parallel iterator | rustc_data_structure::sync |
-| **par_for_each_in**(t: T, for_each: impl Fn(T::Item)) | generate a parallel iterator and run `for_each` on each element | rustc_data_structure::sync |
-| **Map::par_body_owners**(self, f: impl Fn(LocalDefId)) | run `f` on all hir owners in the crate | rustc_middle::hir::map |
-| **Map::par_for_each_module**(self, f: impl Fn(LocalDefId)) | run `f` on all modules and sub modules in the crate | rustc_middle::hir::map |
-| **ModuleItems::par_items**(&self, f: impl Fn(ItemId)) | run `f` on all items in the module | rustc_middle::hir |
-| **ModuleItems::par_trait_items**(&self, f: impl Fn(TraitItemId)) | run `f` on all trait items in the module | rustc_middle::hir |
-| **ModuleItems::par_impl_items**(&self, f: impl Fn(ImplItemId)) | run `f` on all impl items in the module | rustc_middle::hir |
-| **ModuleItems::par_foreign_items**(&self, f: impl Fn(ForeignItemId)) | run `f` on all foreign items in the module | rustc_middle::hir |
+| Helper (simplified) | Purpose | Owning module |
+| ------------------- | ------- | ------------- |
+| `par_fns(&mut [f])` | Run a fixed set of functions concurrently | `rustc_data_structures::sync` |
+| `par_join(a, b)` | Run two functions concurrently | `rustc_data_structures::sync` |
+| `par_for_each_in(iter, f)` | Run `f` for each item | `rustc_data_structures::sync` |
+| `TyCtxt::par_hir_body_owners(f)` | Run `f` for every HIR body owner | `rustc_middle::hir::map` |
+| `TyCtxt::par_hir_for_each_module(f)` | Run `f` for every HIR module | `rustc_middle::hir::map` |
+| `ModuleItems::par_*` | Visit item, trait item, impl item, foreign item, nested body, or opaque collections | `rustc_middle::hir` |
There are a lot of loops in the compiler which can possibly be parallelized
-using these functions. As of August 2022, scenarios where
-the parallel iterator function has been used are as follows:
+using these functions. As of August 2026, examples include:
| caller | scenario | callee |
| ------------------------------------------------------- | ------------------------------------------------------------ | ------------------------ |
-| rustc_metadata::rmeta::encoder::prefetch_mir | Prefetch queries which will be needed later by metadata encoding | par_iter |
+| rustc_metadata::rmeta::encoder::prefetch_mir | Prefetch queries which will be needed later by metadata encoding | par_for_each_in |
| rustc_monomorphize::collector::collect_crate_mono_items | Collect monomorphized items reachable from non-generic items | par_for_each_in |
-| rustc_interface::passes::analysis | Check the validity of the match statements | Map::par_body_owners |
-| rustc_interface::passes::analysis | MIR borrow check | Map::par_body_owners |
-| rustc_typeck::check::typeck_item_bodies | Type check | Map::par_body_owners |
-| rustc_interface::passes::hir_id_validator::check_crate | Check the validity of hir | Map::par_for_each_module |
-| rustc_interface::passes::analysis | Check the validity of loops body, attributes, naked functions, unstable abi, const bodys | Map::par_for_each_module |
-| rustc_interface::passes::analysis | Liveness and intrinsic checking of MIR | Map::par_for_each_module |
-| rustc_interface::passes::analysis | Deathness checking | Map::par_for_each_module |
-| rustc_interface::passes::analysis | Privacy checking | Map::par_for_each_module |
-| rustc_lint::late::check_crate | Run per-module lints | Map::par_for_each_module |
-| rustc_typeck::check_crate | Well-formedness checking | Map::par_for_each_module |
+| rustc_interface::passes::run_required_analyses | MIR borrow checking and related analyses | TyCtxt::par_hir_body_owners |
+| rustc_passes::hir_id_validator::check_crate | Check the validity of HIR IDs | TyCtxt::par_hir_for_each_module |
+| rustc_lint::late::check_crate | Run per-module lints | TyCtxt::par_hir_for_each_module |
+| rustc_hir_analysis::check::wfcheck::check_type_wf | Run well-formedness checks over HIR item collections | ModuleItems::par_* |
There are still many loops that have the potential to use parallel iterators.
@@ -158,15 +131,16 @@ When a query `foo` is evaluated, the cache table for `foo` is locked.
the compiler uses an extra thread *(named deadlock handler)* to detect, remove and
report the cycle error.
-The parallel query feature still has implementation to do, most of which is
-related to the previous `Data Structures` and `Parallel Iterators`.
-See [this open feature tracking issue][tracking].
+The original [query-parallelization tracking issue][query-tracking] is closed
+as completed. Remaining parallel front-end work is tracked in the current
+[parallel front-end tracking issue][tracking].
## Rustdoc
-As of November 2022, there are still a number of steps to
-complete before `rustdoc` rendering can be made parallel (see a open discussion
-of [parallel `rustdoc`][parallel-rustdoc]).
+As of August 2026, `rustdoc` HTML rendering remains serial.
+The [parallel `rustdoc` tracking issue][parallel-rustdoc] is still open; several
+fields in the rendering `SharedContext` still use `RefCell`, and module items
+are rendered sequentially.
## Resources
@@ -176,11 +150,12 @@ Here are some resources that can be used to learn more:
- [This IRLO thread by Zoxc, one of the pioneers of the effort][irlo0]
- [This list of interior mutability in the compiler by nikomatsakis][imlist]
-[`rayon`]: https://crates.io/crates/rayon
+[compiler-job-options]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-jobs
[imlist]: https://github.com/nikomatsakis/rustc-parallelization/blob/master/interior-mutability-list.md
[irlo0]: https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606
[irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503
[monomorphization]: backend/monomorph.md
[parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741
-[rustc-rayon]: https://github.com/rust-lang/rustc-rayon
-[tracking]: https://github.com/rust-lang/rust/issues/48685
+[query-tracking]: https://github.com/rust-lang/rust/issues/48685
+[`rustc_thread_pool`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_thread_pool/index.html
+[tracking]: https://github.com/rust-lang/rust/issues/113349