about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorxizheyin <xizheyin@smail.nju.edu.cn>2025-06-13 22:32:33 +0800
committerxizheyin <xizheyin@smail.nju.edu.cn>2025-06-13 22:51:25 +0800
commita4c8ef9f341217b103dfd4d0d9d9a641cda6ef4c (patch)
tree33a851c4dc5422cf13a01dcc16c9efb79f428984 /src/doc/rustc-dev-guide
parent7db417754765c8ae74645deb41112b4a92d735df (diff)
downloadrust-a4c8ef9f341217b103dfd4d0d9d9a641cda6ef4c.tar.gz
rust-a4c8ef9f341217b103dfd4d0d9d9a641cda6ef4c.zip
Adjust some doc for Query System
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/src/query.md85
1 files changed, 46 insertions, 39 deletions
diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md
index 782c5b4b3c0..0c8e136b381 100644
--- a/src/doc/rustc-dev-guide/src/query.md
+++ b/src/doc/rustc-dev-guide/src/query.md
@@ -67,9 +67,15 @@ are cheaply cloneable; insert an `Rc` if necessary).
 ### Providers
 
 If, however, the query is *not* in the cache, then the compiler will
-try to find a suitable **provider**. A provider is a function that has
-been defined and linked into the compiler somewhere that contains the
-code to compute the result of the query.
+call the corresponding **provider** function. A provider is a function
+implemented in a specific module and **manually registered** into the
+[`Providers`][providers_struct] struct during compiler initialization.
+The macro system generates the [`Providers`][providers_struct] struct,
+which acts as a function table for all query implementations, where each
+field is a function pointer to the actual provider.
+
+**Note:** The `Providers` struct is generated by macros and acts as a function table for all query implementations.
+It is **not** a Rust trait, but a plain struct with function pointer fields.
 
 **Providers are defined per-crate.** The compiler maintains,
 internally, a table of providers for every crate, at least
@@ -97,7 +103,18 @@ fn provider<'tcx>(
 Providers take two arguments: the `tcx` and the query key.
 They return the result of the query.
 
-###  How providers are setup
+N.B. Most of the `rustc_*` crates only provide **local
+providers**. Almost all **extern providers** wind up going through the
+[`rustc_metadata` crate][rustc_metadata], which loads the information
+from the crate metadata. But in some cases there are crates that
+provide queries for *both* local and external crates, in which case
+they define both a `provide` and a `provide_extern` function, through
+[`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke.
+
+[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
+[wasm_import_module_map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
+
+### How providers are set up
 
 When the tcx is created, it is given the providers by its creator using
 the [`Providers`][providers_struct] struct. This struct is generated by
@@ -108,19 +125,16 @@ the macros here, but it is basically a big list of function pointers:
 ```rust,ignore
 struct Providers {
     type_of: for<'tcx> fn(TyCtxt<'tcx>, DefId) -> Ty<'tcx>,
-    ...
+    // ... one field for each query
 }
 ```
 
-At present, we have one copy of the struct for local crates, and one
-for external crates, though the plan is that we may eventually have
-one per crate.
+#### How are providers registered?
+
+The `Providers` struct is filled in during compiler initialization, mainly by the `rustc_driver` crate.  
+But the actual provider functions are implemented in various `rustc_*` crates (like `rustc_middle`, `rustc_hir_analysis`, etc).
 
-These `Providers` structs are ultimately created and populated by
-`rustc_driver`, but it does this by distributing the work
-throughout the other `rustc_*` crates. This is done by invoking
-various [`provide`][provide_fn] functions. These functions tend to look
-something like this:
+To register providers, each crate exposes a [`provide`][provide_fn] function that looks like this:
 
 [provide_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/fn.provide.html
 
@@ -128,41 +142,34 @@ something like this:
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         type_of,
+        // ... add more providers here
         ..*providers
     };
 }
 ```
 
-That is, they take an `&mut Providers` and mutate it in place. Usually
-we use the formulation above just because it looks nice, but you could
-as well do `providers.type_of = type_of`, which would be equivalent.
-(Here, `type_of` would be a top-level function, defined as we saw
-before.) So, if we want to add a provider for some other query,
-let's call it `fubar`, into the crate above, we might modify the `provide()`
-function like so:
+- This function takes a mutable reference to the `Providers` struct and sets the fields to point to the correct provider functions.
+- You can also assign fields individually, e.g. `providers.type_of = type_of;`.
 
-```rust,ignore
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        type_of,
-        fubar,
-        ..*providers
-    };
-}
+#### Adding a new provider
 
-fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
-```
+Suppose you want to add a new query called `fubar`. You would:
 
-N.B. Most of the `rustc_*` crates only provide **local
-providers**. Almost all **extern providers** wind up going through the
-[`rustc_metadata` crate][rustc_metadata], which loads the information
-from the crate metadata. But in some cases there are crates that
-provide queries for *both* local and external crates, in which case
-they define both a `provide` and a `provide_extern` function, through
-[`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke.
+1. Implement the provider function:
+    ```rust,ignore
+    fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... }
+    ```
+2. Register it in the `provide` function:
+    ```rust,ignore
+    pub fn provide(providers: &mut Providers) {
+        *providers = Providers {
+            fubar,
+            ..*providers
+        };
+    }
+    ```
 
-[rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html
-[wasm_import_module_map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/symbol_export/fn.wasm_import_module_map.html
+---
 
 ## Adding a new query