diff --git a/src/query.md b/src/query.md index aaf083178..9ae6baa9e 100644 --- a/src/query.md +++ b/src/query.md @@ -76,8 +76,8 @@ dependencies of the local crate). Note that what determines the crate that a query is targeting is not the *kind* of query, but the *key*. For example, when you invoke `tcx.type_of(def_id)`, that could be a local query or an external query, depending on what crate the `def_id` -is referring to (see the `self::keys::Key` trait for more information -on how that works). +is referring to (see the [`self::keys::Key`][Key] trait for more +information on how that works). Providers always have the same signature: @@ -96,8 +96,10 @@ They return the result of the query. #### How providers are setup When the tcx is created, it is given the providers by its creator using -the `Providers` struct. This struct is generated by the macros here, but it -is basically a big list of function pointers: +the [`Providers`][providers_struct] struct. This struct is generated by +the macros here, but it is basically a big list of function pointers: + +[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/query/struct.Providers.html ```rust,ignore struct Providers { @@ -110,11 +112,13 @@ 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. -These `Provider` structs are ultimately created and populated by +These `Providers` structs are ultimately created and populated by `librustc_driver`, but it does this by distributing the work throughout the other `rustc_*` crates. This is done by invoking -various `provide` functions. These functions tend to look something -like this: +various [`provide`][provide_fn] functions. These functions tend to look +something like this: + +[provide_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/hir/fn.provide.html ```rust,ignore pub fn provide(providers: &mut Providers) { @@ -147,13 +151,16 @@ fn fubar<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> Fubar<'tcx> { ... } 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 that `rustc_driver` can -invoke. +[`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`][ext_provide] and a +[`provide_extern`][ext_provide_extern] function that `rustc_driver` +can invoke. [rustc_metadata]: https://github.com/rust-lang/rust/tree/master/src/librustc_metadata +[ext_provide]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/attributes/fn.provide.html +[ext_provide_extern]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/attributes/fn.provide_extern.html ### Adding a new kind of query @@ -205,7 +212,7 @@ Let's go over them one by one: (`ty::queries::type_of`) that will be generated to represent this query. - **Query key type:** the type of the argument to this query. - This type must implement the `ty::query::keys::Key` trait, which + This type must implement the [`ty::query::keys::Key`][Key] trait, which defines (for example) how to map it to a crate, and so forth. - **Result type of query:** the type produced by this query. This type should (a) not use `RefCell` or other interior mutability and (b) be @@ -218,6 +225,8 @@ Let's go over them one by one: - **Query modifiers:** various flags and options that customize how the query is processed. +[Key]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/query/keys/trait.Key.html + So, to add a query: - Add an entry to `rustc_queries!` using the format above. @@ -229,7 +238,7 @@ So, to add a query: For each kind, the `rustc_queries` macro will generate a "query struct" named after the query. This struct is a kind of a place-holder describing the query. Each such struct implements the -`self::config::QueryConfig` trait, which has associated types for the +[`self::config::QueryConfig`][QueryConfig] trait, which has associated types for the key/value of that particular query. Basically the code generated looks something like this: @@ -247,13 +256,16 @@ impl<'tcx> QueryConfig for type_of<'tcx> { ``` There is an additional trait that you may wish to implement called -`self::config::QueryDescription`. This trait is used during cycle -errors to give a "human readable" name for the query, so that we can -summarize what was happening when the cycle occurred. Implementing -this trait is optional if the query key is `DefId`, but if you *don't* -implement it, you get a pretty generic error ("processing `foo`..."). +[`self::config::QueryDescription`][QueryDescription]. This trait is +used during cycle errors to give a "human readable" name for the query, +so that we can summarize what was happening when the cycle occurred. +Implementing this trait is optional if the query key is `DefId`, but +if you *don't* implement it, you get a pretty generic error ("processing `foo`..."). You can put new impls into the `config` module. They look something like this: +[QueryConfig]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/query/trait.QueryConfig.html +[QueryDescription]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/query/config/trait.QueryDescription.html + ```rust,ignore impl<'tcx> QueryDescription for queries::type_of<'tcx> { fn describe(tcx: TyCtxt, key: DefId) -> String {