Skip to content

Commit 562dee4

Browse files
committed
Auto merge of rust-lang#154122 - Zalathar:no-anon, r=nnethercote
Remove the `anon` query modifier Prior experiments: - rust-lang#152268 - rust-lang#153996 [Zulip thread: *Removing the `anon` query modifier*](https://rust-lang.zulipchat.com/#narrow/channel/582699-t-compiler.2Fquery-system/topic/Removing.20the.20.60anon.60.20query.20modifier/with/580760962) --- There are currently three queries that use the `anon` modifier: - `check_representability` - `check_representability_adt_ty` - `erase_and_anonymize_regions_ty` It seems that none of them are using `anon` in an essential way. According to comments and tests, the *representability* queries mainly care about not being eligible for forcing (despite having a recoverable key type), so that if a cycle does occur then the entire cycle will be on the query stack. Replacing `anon` with a new `no_force` modifier gives a modest perf improvement. The `erase_and_anonymize_regions_ty` query appears to be using `anon` to reduce the dep-graph overhead of a query that is expected to not call any other queries (and thus have no dependencies). Replacing `anon` with either `no_hash` or nothing appears to give only a very small perf hit on `cargo` benchmarks, which is justified by the fact that it lets us remove a lot of machinery for anonymous queries. We still need to retain some of the machinery for anonymous *tasks*, because the non-query task `DepKind::TraitSelect` still uses it. --- I have some ideas for a follow-up that will reduce dep-graph overhead by replacing *all* zero-dependency nodes with a singleton node, but I want to keep that separate in case it causes unexpected issues and needs to be bisected or reverted.
2 parents 20f19f4 + 3a62e89 commit 562dee4

File tree

14 files changed

+64
-83
lines changed

14 files changed

+64
-83
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ fn check_type_defn<'tcx>(
998998
item: &hir::Item<'tcx>,
999999
all_sized: bool,
10001000
) -> Result<(), ErrorGuaranteed> {
1001-
let _ = tcx.check_representability(item.owner_id.def_id);
1001+
tcx.ensure_ok().check_representability(item.owner_id.def_id);
10021002
let adt_def = tcx.adt_def(item.owner_id);
10031003

10041004
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {

compiler/rustc_macros/src/query.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,13 @@ struct CacheOnDiskIf {
140140
/// See `rustc_middle::query::modifiers` for documentation of each query modifier.
141141
struct QueryModifiers {
142142
// tidy-alphabetical-start
143-
anon: Option<Ident>,
144143
arena_cache: Option<Ident>,
145144
cache_on_disk_if: Option<CacheOnDiskIf>,
146145
depth_limit: Option<Ident>,
147146
desc: Desc,
148147
eval_always: Option<Ident>,
149148
feedable: Option<Ident>,
149+
no_force: Option<Ident>,
150150
no_hash: Option<Ident>,
151151
separate_provide_extern: Option<Ident>,
152152
// tidy-alphabetical-end
@@ -156,8 +156,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
156156
let mut arena_cache = None;
157157
let mut cache_on_disk_if = None;
158158
let mut desc = None;
159+
let mut no_force = None;
159160
let mut no_hash = None;
160-
let mut anon = None;
161161
let mut eval_always = None;
162162
let mut depth_limit = None;
163163
let mut separate_provide_extern = None;
@@ -189,10 +189,10 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
189189
try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
190190
} else if modifier == "arena_cache" {
191191
try_insert!(arena_cache = modifier);
192+
} else if modifier == "no_force" {
193+
try_insert!(no_force = modifier);
192194
} else if modifier == "no_hash" {
193195
try_insert!(no_hash = modifier);
194-
} else if modifier == "anon" {
195-
try_insert!(anon = modifier);
196196
} else if modifier == "eval_always" {
197197
try_insert!(eval_always = modifier);
198198
} else if modifier == "depth_limit" {
@@ -212,8 +212,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
212212
arena_cache,
213213
cache_on_disk_if,
214214
desc,
215+
no_force,
215216
no_hash,
216-
anon,
217217
eval_always,
218218
depth_limit,
219219
separate_provide_extern,
@@ -243,24 +243,24 @@ fn returns_error_guaranteed(ret_ty: &ReturnType) -> bool {
243243
fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
244244
let QueryModifiers {
245245
// tidy-alphabetical-start
246-
anon,
247246
arena_cache,
248247
cache_on_disk_if,
249248
depth_limit,
250249
desc: _,
251250
eval_always,
252251
feedable,
252+
no_force,
253253
no_hash,
254254
separate_provide_extern,
255255
// tidy-alphabetical-end
256256
} = &query.modifiers;
257257

258-
let anon = anon.is_some();
259258
let arena_cache = arena_cache.is_some();
260259
let cache_on_disk = cache_on_disk_if.is_some();
261260
let depth_limit = depth_limit.is_some();
262261
let eval_always = eval_always.is_some();
263262
let feedable = feedable.is_some();
263+
let no_force = no_force.is_some();
264264
let no_hash = no_hash.is_some();
265265
let returns_error_guaranteed = returns_error_guaranteed(&query.return_ty);
266266
let separate_provide_extern = separate_provide_extern.is_some();
@@ -273,12 +273,12 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
273273
query_name_span =>
274274
// Search for (QMODLIST) to find all occurrences of this query modifier list.
275275
// tidy-alphabetical-start
276-
anon: #anon,
277276
arena_cache: #arena_cache,
278277
cache_on_disk: #cache_on_disk,
279278
depth_limit: #depth_limit,
280279
eval_always: #eval_always,
281280
feedable: #feedable,
281+
no_force: #no_force,
282282
no_hash: #no_hash,
283283
returns_error_guaranteed: #returns_error_guaranteed,
284284
separate_provide_extern: #separate_provide_extern,
@@ -387,13 +387,15 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
387387
}
388388

389389
doc_link!(
390+
// tidy-alphabetical-start
390391
arena_cache,
391-
no_hash,
392-
anon,
393-
eval_always,
394392
depth_limit,
395-
separate_provide_extern,
393+
eval_always,
396394
feedable,
395+
no_force,
396+
no_hash,
397+
separate_provide_extern,
398+
// tidy-alphabetical-end
397399
);
398400

399401
let name = &query.name;
@@ -476,11 +478,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
476478
});
477479

478480
if let Some(feedable) = &modifiers.feedable {
479-
assert!(
480-
modifiers.anon.is_none(),
481-
feedable.span(),
482-
"Query {name} cannot be both `feedable` and `anon`."
483-
);
484481
assert!(
485482
modifiers.eval_always.is_none(),
486483
feedable.span(),

compiler/rustc_middle/src/dep_graph/dep_node.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,14 @@ impl DepKind {
9494
pub struct DepNode {
9595
pub kind: DepKind,
9696

97-
/// This is _typically_ a hash of the query key, but sometimes not.
97+
/// If `kind` is a query method, then its "key fingerprint" is always a
98+
/// stable hash of the query key.
9899
///
99-
/// For example, `anon` nodes have a fingerprint that is derived from their
100-
/// dependencies instead of a key.
100+
/// For non-query nodes, the content of this field varies:
101+
/// - Some dep kinds always use a dummy `ZERO` fingerprint.
102+
/// - Some dep kinds use the stable hash of some relevant key-like value.
103+
/// - Some dep kinds use the `with_anon_task` mechanism, and set their key
104+
/// fingerprint to a hash derived from the task's dependencies.
101105
///
102106
/// In some cases the key value can be reconstructed from this fingerprint;
103107
/// see [`KeyFingerprintStyle`].

compiler/rustc_middle/src/dep_graph/graph.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,8 @@ impl DepGraphData {
375375
/// incorrectly marked green.
376376
///
377377
/// FIXME: This could perhaps return a `WithDepNode` to ensure that the
378-
/// user of this function actually performs the read; we'll have to see
379-
/// how to make that work with `anon` in `execute_job_incr`, though.
380-
pub fn with_anon_task_inner<'tcx, OP, R>(
378+
/// user of this function actually performs the read.
379+
fn with_anon_task_inner<'tcx, OP, R>(
381380
&self,
382381
tcx: TyCtxt<'tcx>,
383382
dep_kind: DepKind,

compiler/rustc_middle/src/queries.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -585,16 +585,15 @@ rustc_queries! {
585585
desc { "checking if `{}` is representable", tcx.def_path_str(key) }
586586
// We don't want recursive representability calls to be forced with
587587
// incremental compilation because, if a cycle occurs, we need the
588-
// entire cycle to be in memory for diagnostics. This means we can't
589-
// use `ensure_ok()` with this query.
590-
anon
588+
// entire cycle to be in memory for diagnostics.
589+
no_force
591590
}
592591

593592
/// An implementation detail for the `check_representability` query. See that query for more
594593
/// details, particularly on the modifiers.
595594
query check_representability_adt_ty(key: Ty<'tcx>) {
596595
desc { "checking if `{}` is representable", key }
597-
anon
596+
no_force
598597
}
599598

600599
/// Set of param indexes for type params that are in the type's representation
@@ -768,14 +767,10 @@ rustc_queries! {
768767
/// Normally you would just use `tcx.erase_and_anonymize_regions(value)`,
769768
/// however, which uses this query as a kind of cache.
770769
query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
771-
// This query is not expected to have input -- as a result, it
772-
// is not a good candidates for "replay" because it is essentially a
773-
// pure function of its input (and hence the expectation is that
774-
// no caller would be green **apart** from just these
775-
// queries). Making it anonymous avoids hashing the result, which
776-
// may save a bit of time.
777-
anon
778770
desc { "erasing regions from `{}`", ty }
771+
// Not hashing the return value appears to give marginally better perf for this query,
772+
// which should always be marked green for having no dependencies anyway.
773+
no_hash
779774
}
780775

781776
query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap<String> {

compiler/rustc_middle/src/query/modifiers.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77

88
// tidy-alphabetical-start
99
//
10-
/// # `anon` query modifier
11-
///
12-
/// Generate a dep node based not on the query key, but on the query's dependencies.
13-
pub(crate) struct anon;
14-
1510
/// # `arena_cache` query modifier
1611
///
1712
/// Query return values must impl `Copy` and be small, but some queries must return values that
@@ -59,6 +54,16 @@ pub(crate) struct eval_always;
5954
/// Generate a `feed` method to set the query's value from another query.
6055
pub(crate) struct feedable;
6156

57+
/// # `no_force` query modifier
58+
///
59+
/// Dep nodes of queries with this modifier will never be "forced" when trying
60+
/// to mark their dependents green, even if their key is recoverable from the
61+
/// key fingerprint.
62+
///
63+
/// Used by some queries with custom cycle-handlers to ensure that if a cycle
64+
/// occurs, all of the relevant query calls will be on the query stack.
65+
pub(crate) struct no_force;
66+
6267
/// # `no_hash` query modifier
6368
///
6469
/// Do not hash the query's return value for incremental compilation. If the value needs to be

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ pub enum EnsureMode {
7777
pub struct QueryVTable<'tcx, C: QueryCache> {
7878
pub name: &'static str,
7979

80-
/// True if this query has the `anon` modifier.
81-
pub anon: bool,
8280
/// True if this query has the `eval_always` modifier.
8381
pub eval_always: bool,
8482
/// True if this query has the `depth_limit` modifier.
@@ -283,12 +281,12 @@ macro_rules! define_callbacks {
283281
fn $name:ident($($K:tt)*) -> $V:ty
284282
{
285283
// Search for (QMODLIST) to find all occurrences of this query modifier list.
286-
anon: $anon:literal,
287284
arena_cache: $arena_cache:literal,
288285
cache_on_disk: $cache_on_disk:literal,
289286
depth_limit: $depth_limit:literal,
290287
eval_always: $eval_always:literal,
291288
feedable: $feedable:literal,
289+
no_force: $no_force:literal,
292290
no_hash: $no_hash:literal,
293291
returns_error_guaranteed: $returns_error_guaranteed:literal,
294292
separate_provide_extern: $separate_provide_extern:literal,

compiler/rustc_middle/src/ty/inhabitedness/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) {
6161
/// requires calling [`InhabitedPredicate::instantiate`]
6262
fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
6363
if let Some(def_id) = def_id.as_local() {
64-
let _ = tcx.check_representability(def_id);
64+
tcx.ensure_ok().check_representability(def_id);
6565
}
6666

6767
let adt = tcx.adt_def(def_id);

compiler/rustc_query_impl/src/dep_kind_vtables.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,30 +96,23 @@ mod non_query {
9696
/// Shared implementation of the [`DepKindVTable`] constructor for queries.
9797
/// Called from macro-generated code for each query.
9898
pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
99-
is_anon: bool,
10099
is_cache_on_disk: bool,
101100
is_eval_always: bool,
101+
is_no_force: bool,
102102
) -> DepKindVTable<'tcx>
103103
where
104104
Q: GetQueryVTable<'tcx>,
105105
{
106-
let key_fingerprint_style = if is_anon {
107-
KeyFingerprintStyle::Opaque
108-
} else {
109-
<Q::Cache as QueryCache>::Key::key_fingerprint_style()
110-
};
111-
112106
// A query dep-node can only be forced or promoted if it can recover a key
113107
// from its key fingerprint.
108+
let key_fingerprint_style = <Q::Cache as QueryCache>::Key::key_fingerprint_style();
114109
let can_recover = key_fingerprint_style.is_maybe_recoverable();
115-
if is_anon {
116-
assert!(!can_recover);
117-
}
118110

119111
DepKindVTable {
120112
is_eval_always,
121113
key_fingerprint_style,
122-
force_from_dep_node_fn: can_recover.then_some(force_from_dep_node_inner::<Q>),
114+
force_from_dep_node_fn: (can_recover && !is_no_force)
115+
.then_some(force_from_dep_node_inner::<Q>),
123116
promote_from_disk_fn: (can_recover && is_cache_on_disk)
124117
.then_some(promote_from_disk_inner::<Q>),
125118
}
@@ -133,12 +126,12 @@ macro_rules! define_dep_kind_vtables {
133126
fn $name:ident($K:ty) -> $V:ty
134127
{
135128
// Search for (QMODLIST) to find all occurrences of this query modifier list.
136-
anon: $anon:literal,
137129
arena_cache: $arena_cache:literal,
138130
cache_on_disk: $cache_on_disk:literal,
139131
depth_limit: $depth_limit:literal,
140132
eval_always: $eval_always:literal,
141133
feedable: $feedable:literal,
134+
no_force: $no_force:literal,
142135
no_hash: $no_hash:literal,
143136
returns_error_guaranteed: $returns_error_guaranteed:literal,
144137
separate_provide_extern: $separate_provide_extern:literal,
@@ -165,9 +158,9 @@ macro_rules! define_dep_kind_vtables {
165158
$crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
166159
$crate::query_impl::$name::VTableGetter,
167160
>(
168-
$anon,
169161
$cache_on_disk,
170162
$eval_always,
163+
$no_force,
171164
)
172165
),*
173166
];

compiler/rustc_query_impl/src/execution.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ fn execute_job_incr<'tcx, C: QueryCache>(
424424
let dep_graph_data =
425425
tcx.dep_graph.data().expect("should always be present in incremental mode");
426426

427-
if !query.anon && !query.eval_always {
427+
if !query.eval_always {
428428
// `to_dep_node` is expensive for some `DepKind`s.
429429
let dep_node =
430430
dep_node_opt.get_or_insert_with(|| DepNode::construct(tcx, query.dep_kind, &key));
@@ -451,13 +451,6 @@ fn execute_job_incr<'tcx, C: QueryCache>(
451451
let prof_timer = tcx.prof.query_provider();
452452

453453
let (result, dep_node_index) = start_query(job_id, query.depth_limit, || {
454-
if query.anon {
455-
// Call the query provider inside an anon task.
456-
return dep_graph_data.with_anon_task_inner(tcx, query.dep_kind, || {
457-
(query.invoke_provider_fn)(tcx, key)
458-
});
459-
}
460-
461454
// `to_dep_node` is expensive for some `DepKind`s.
462455
let dep_node =
463456
dep_node_opt.unwrap_or_else(|| DepNode::construct(tcx, query.dep_kind, &key));
@@ -601,9 +594,6 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>(
601594
return EnsureCanSkip { skip_execution: false, dep_node: None };
602595
}
603596

604-
// Ensuring an anonymous query makes no sense
605-
assert!(!query.anon);
606-
607597
let dep_node = DepNode::construct(tcx, query.dep_kind, &key);
608598

609599
let serialized_dep_node_index = match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
@@ -703,8 +693,6 @@ pub(crate) fn force_query<'tcx, C: QueryCache>(
703693
return;
704694
}
705695

706-
debug_assert!(!query.anon);
707-
708696
ensure_sufficient_stack(|| {
709697
try_execute_query::<C, true>(query, tcx, DUMMY_SP, key, Some(dep_node))
710698
});

0 commit comments

Comments
 (0)