Skip to content

Comments

rustc_queries simplifications#152958

Merged
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
nnethercote:rustc_queries-fixes
Feb 22, 2026
Merged

rustc_queries simplifications#152958
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
nnethercote:rustc_queries-fixes

Conversation

@nnethercote
Copy link
Contributor

Queries have two ways of specifying code snippets, in desc and cache_on_disk_if blocks. An example:

query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
    arena_cache
    desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
    cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}

If you need to use tcx in the snippet, you can use an explicit binding. But there are multiple problems with this.

  • The syntax used is different in the two snippets: |tcx| within the block vs. (tcx) outside the block. (!!)
  • Bug 1: In desc snippets you can leave out the |tcx| and still use tcx. Several existing queries do this.
  • Bug 2: In desc snippets you can always use key in the snippet to refer to the key, even if that's not the identifier used in the query head.
  • Finally, you can bind tcx and not use it, without a warning. Several existing queries do this.

I think explicit tcx binding is silly. Many queries need tcx and this macro is already super-magical, so just making tcx implicitly available seems fine, rather than making the query writer jump through a little syntactic hoop. This makes both the query definitions and the proc macro simpler.

r? @petrochenkov

Due to a bug, you can currently use `key` within the `desc` block and
it'll just work regardless of what actual key name you specified. A
subsequent commit will fix this, so let's correct the affected queries
first.
Due to a bug they aren't actually necessary! (A few queries already take
advantage of this, probably unintentionally.) And the next commit will
remove support for explicit `tcx` bindings in favour of implicit.
@rustbot rustbot added A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 22, 2026
@nnethercote
Copy link
Contributor Author

nnethercote commented Feb 22, 2026

If you want to understand the two bugs in the desc implementation, consider these following examples and the code generated for them.

// no key, no tcx: ok
query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet<LocalDefId> {
    arena_cache
    desc { "getting a list of all mir_keys" }
}
#[allow(unused_variables)]
pub fn mir_keys<'tcx>(tcx: TyCtxt<'tcx>, key: ()) -> String {
    let (_, _) = (tcx, key);
    format! ("getting a list of all mir_keys")
}

// key, no tcx: ok
query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> {
    desc { "computing the symbol for `{}`", key }
    cache_on_disk_if { true }
}
#[allow(unused_variables)]
pub fn symbol_name<'tcx>(tcx: TyCtxt<'tcx>, key: ty::Instance<'tcx>) -> String { 
    let (_, key) = (tcx, key);
    format!("computing the symbol for `{}`", key)
}

// key (with name other than `key`), tcx: good
query defaultness(def_id: DefId) -> hir::Defaultness {
    desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) }
    separate_provide_extern
    feedable
}
#[allow(unused_variables)]
pub fn defaultness<'tcx>(tcx: TyCtxt<'tcx>, key: DefId) -> String {
    let (tcx, def_id) = (tcx, key);
    format!("looking up whether `{}` has `default`", tcx.def_path_str(def_id))
}

// no key, no tcx: doubly bad, but works anyway        
query representability(_: LocalDefId) -> rustc_middle::ty::Representability {
    desc { "checking if `{}` is representable", tcx.def_path_str(key) }
    cycle_delay_bug                                    
    anon                                               
}                                                      
#[allow(unused_variables)]                             
pub fn representability<'tcx>(tcx: TyCtxt<'tcx>, key: LocalDefId) -> String {
    let (_, _) = (tcx, key);                           
    format!("checking if `{}` is representable", tcx.def_path_str(key))
}                                                      

The let line is part of the problem. It seems the macro is trying to ensure the function arguments are used, presumably to avoid warnings. But tcx and key end up always being available. And the allow(unused_variables) means that all this is pointless anyway.

A simple fix is to remove the let line, always use the given key identifier for the key (instead of hardwiring key), and make tcx implicitly available. That fixes the problem and makes the macro simpler, and it's what this PR does.

@nnethercote
Copy link
Contributor Author

Best reviewed one commit at a time.

cc @Zalathar @oli-obk @cjgillot @Zoxc

@rust-log-analyzer

This comment has been minimized.

As currently written, these have big problems.
- `desc` and `cache_on_disk_if` modifiers use different syntaxes to
  introduce `tcx`.
- `desc` is mis-implemented such that the explicit binding isn't even
  necessary and the key name can be botched, as the previous two commits
  showed. (It's the `let (#tcx, #key) = (tcx, key);` line that messes
  things up.)

It's simpler and less error-prone to simply not require explicit `tcx`
bindings, and instead just make it implicitly available to these code
snippets.
@oli-obk
Copy link
Contributor

oli-obk commented Feb 22, 2026

r? @oli-obk

@bors r+

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 22, 2026

📌 Commit ecb778f has been approved by oli-obk

It is now in the queue for this repository.

@rust-bors rust-bors bot added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Feb 22, 2026
@rust-bors rust-bors bot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 22, 2026
@oli-obk
Copy link
Contributor

oli-obk commented Feb 22, 2026

  • In desc snippets you can leave out the |tcx| and still use tcx. Several existing queries do this.

Heh I noticed this before but didn't investigate

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 22, 2026
…=oli-obk

`rustc_queries` simplifications

Queries have two ways of specifying code snippets, in `desc` and `cache_on_disk_if` blocks. An example:
```rust
query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
    arena_cache
    desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
    cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}
```
If you need to use `tcx` in the snippet, you can use an explicit binding. But there are multiple problems with this.

- The syntax used is different in the two snippets: `|tcx|` within the block vs. `(tcx)` outside the block. (!!)
- Bug 1: In `desc` snippets you can leave out the `|tcx|` and still use `tcx`. Several existing queries do this.
- Bug 2: In `desc` snippets you can always use `key` in the snippet to refer to the key, even if that's not the identifier used in the query head.
- Finally, you can bind `tcx` and not use it, without a warning. Several existing queries do this.

I think explicit `tcx` binding is silly. Many queries need `tcx` and this macro is already super-magical, so just making `tcx` implicitly available seems fine, rather than making the query writer jump through a little syntactic hoop. This makes both the query definitions and the proc macro simpler.

r? @petrochenkov
rust-bors bot pushed a commit that referenced this pull request Feb 22, 2026
…uwer

Rollup of 5 pull requests

Successful merges:

 - #149366 (GVN: consider constants of primitive types as deterministic)
 - #152779 (Clarify aspects of query macros)
 - #152958 (`rustc_queries` simplifications)
 - #149783 (stabilize `cfg_select!`)
 - #152708 (Build: Add `stdenv.cc.cc.lib` to Nix dependencies)
rust-bors bot pushed a commit that referenced this pull request Feb 22, 2026
…uwer

Rollup of 5 pull requests

Successful merges:

 - #149366 (GVN: consider constants of primitive types as deterministic)
 - #152779 (Clarify aspects of query macros)
 - #152958 (`rustc_queries` simplifications)
 - #149783 (stabilize `cfg_select!`)
 - #152708 (Build: Add `stdenv.cc.cc.lib` to Nix dependencies)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 22, 2026
…=oli-obk

`rustc_queries` simplifications

Queries have two ways of specifying code snippets, in `desc` and `cache_on_disk_if` blocks. An example:
```rust
query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
    arena_cache
    desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
    cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}
```
If you need to use `tcx` in the snippet, you can use an explicit binding. But there are multiple problems with this.

- The syntax used is different in the two snippets: `|tcx|` within the block vs. `(tcx)` outside the block. (!!)
- Bug 1: In `desc` snippets you can leave out the `|tcx|` and still use `tcx`. Several existing queries do this.
- Bug 2: In `desc` snippets you can always use `key` in the snippet to refer to the key, even if that's not the identifier used in the query head.
- Finally, you can bind `tcx` and not use it, without a warning. Several existing queries do this.

I think explicit `tcx` binding is silly. Many queries need `tcx` and this macro is already super-magical, so just making `tcx` implicitly available seems fine, rather than making the query writer jump through a little syntactic hoop. This makes both the query definitions and the proc macro simpler.

r? @petrochenkov
rust-bors bot pushed a commit that referenced this pull request Feb 22, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - #149366 (GVN: consider constants of primitive types as deterministic)
 - #152779 (Clarify aspects of query macros)
 - #152958 (`rustc_queries` simplifications)
 - #152385 (Feature gate for defaulted associated type_consts with associated_type_defaults )
 - #152708 (Build: Add `stdenv.cc.cc.lib` to Nix dependencies)
 - #152921 (Add build.rustdoc option to bootstrap config)
 - #152926 (Fix ICE when an associated type is wrongly marked as `final`)
 - #152927 (Index expressions rendered the index: subexpression as the id, instea…)
rust-bors bot pushed a commit that referenced this pull request Feb 22, 2026
…uwer

Rollup of 7 pull requests

Successful merges:

 - #152779 (Clarify aspects of query macros)
 - #152958 (`rustc_queries` simplifications)
 - #152385 (Feature gate for defaulted associated type_consts with associated_type_defaults )
 - #152708 (Build: Add `stdenv.cc.cc.lib` to Nix dependencies)
 - #152921 (Add build.rustdoc option to bootstrap config)
 - #152926 (Fix ICE when an associated type is wrongly marked as `final`)
 - #152927 (Index expressions rendered the index: subexpression as the id, instea…)
@rust-bors rust-bors bot merged commit 85cc4b2 into rust-lang:main Feb 22, 2026
11 checks passed
@rustbot rustbot added this to the 1.95.0 milestone Feb 22, 2026
rust-timer added a commit that referenced this pull request Feb 22, 2026
Rollup merge of #152958 - nnethercote:rustc_queries-fixes, r=oli-obk

`rustc_queries` simplifications

Queries have two ways of specifying code snippets, in `desc` and `cache_on_disk_if` blocks. An example:
```rust
query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
    arena_cache
    desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
    cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}
```
If you need to use `tcx` in the snippet, you can use an explicit binding. But there are multiple problems with this.

- The syntax used is different in the two snippets: `|tcx|` within the block vs. `(tcx)` outside the block. (!!)
- Bug 1: In `desc` snippets you can leave out the `|tcx|` and still use `tcx`. Several existing queries do this.
- Bug 2: In `desc` snippets you can always use `key` in the snippet to refer to the key, even if that's not the identifier used in the query head.
- Finally, you can bind `tcx` and not use it, without a warning. Several existing queries do this.

I think explicit `tcx` binding is silly. Many queries need `tcx` and this macro is already super-magical, so just making `tcx` implicitly available seems fine, rather than making the query writer jump through a little syntactic hoop. This makes both the query definitions and the proc macro simpler.

r? @petrochenkov
@nnethercote nnethercote deleted the rustc_queries-fixes branch February 22, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants