From 910ec5a8d0e8af22eebcf9f1664826f20844783c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Aug 2026 20:05:43 +1000 Subject: [PATCH 1/3] Simplify `DepKind` constants This commit changes `DEP_KIND_NUM_VARIANTS` so it's an associated const (renamed as `DepKind::NUM_VARIANTS`) obtained via `std::mem::variant_count`, removing the paranoid consecutiveness check. The commit also replaces multiple `DepKind::MAX as usize + 1` occurrences with `DepKind::NUM_VARIANTS`. --- .../rustc_middle/src/dep_graph/dep_node.rs | 33 +++++++------------ .../rustc_middle/src/dep_graph/serialized.rs | 8 ++--- compiler/rustc_middle/src/lib.rs | 1 + 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index b6fda22775c2a..c59d9620b5e53 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -69,7 +69,8 @@ impl DepKind { if u > Self::MAX { panic!("Invalid DepKind {u}"); } - // SAFETY: See comment on DEP_KIND_NUM_VARIANTS + // SAFETY: `DepKind` is `repr(u16)`, its variants are `0..=MAX`, and `u` was checked + // against `MAX` above. unsafe { std::mem::transmute(u) } } @@ -83,9 +84,16 @@ impl DepKind { *self as usize } + /// The number of dep kind variants. + pub(crate) const NUM_VARIANTS: usize = std::mem::variant_count::(); + /// This is the highest value a `DepKind` can have. It's used during encoding to - /// pack information into the unused bits. - pub(crate) const MAX: u16 = DEP_KIND_NUM_VARIANTS - 1; + /// pack information into the unused bits. u16 matches the `repr(u16)` on `DepKind`. + pub(crate) const MAX: u16 = { + let max = Self::NUM_VARIANTS - 1; + assert!(max < u16::MAX as usize); + max as u16 + }; } /// Combination of a [`DepKind`] and a key fingerprint that uniquely identifies @@ -279,25 +287,6 @@ macro_rules! define_dep_nodes { $( $(#[$q_attr])* $q_name, )* } - // This computes the number of dep kind variants. Along the way, it sanity-checks that the - // discriminants of the variants have been assigned consecutively from 0 so that they can - // be used as a dense index, and that all discriminants fit in a `u16`. - pub(crate) const DEP_KIND_NUM_VARIANTS: u16 = { - let deps = &[ - $(DepKind::$nq_name,)* - $(DepKind::$q_name,)* - ]; - let mut i = 0; - while i < deps.len() { - if i != deps[i].as_usize() { - panic!(); - } - i += 1; - } - assert!(deps.len() <= u16::MAX as usize); - deps.len() as u16 - }; - pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { $( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )* diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index daebc887055ac..1c476fc91697e 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -387,9 +387,9 @@ impl SerializedDepGraph { // Read the number of nodes of each dep kind, and perform // counting sort for `LazyNodeIndex`. - let mut kinds = Vec::with_capacity(DepKind::MAX as usize + 1); + let mut kinds = Vec::with_capacity(DepKind::NUM_VARIANTS); let mut offset = 0u32; - for _ in 0..(DepKind::MAX + 1) { + for _ in 0..(DepKind::NUM_VARIANTS) { let len = d.read_u32(); kinds.push(LazyKindIndex { start: offset, len, map: OnceLock::new() }); offset += len; @@ -654,7 +654,7 @@ impl EncoderState { edge_count: 0, node_count: 0, encoder: MemEncoder::new(), - kind_stats: iter::repeat_n(0, DepKind::MAX as usize + 1).collect(), + kind_stats: iter::repeat_n(0, DepKind::NUM_VARIANTS).collect(), }) }), } @@ -792,7 +792,7 @@ impl EncoderState { let mut encoder = self.file.lock().take().unwrap(); - let mut kind_stats: Vec = iter::repeat_n(0, DepKind::MAX as usize + 1).collect(); + let mut kind_stats: Vec = iter::repeat_n(0, DepKind::NUM_VARIANTS).collect(); let mut node_max = 0; let mut node_count = 0; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 69c2e099080c9..ed1a2f7a831b1 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -56,6 +56,7 @@ #![feature(try_trait_v2_residual)] #![feature(try_trait_v2_yeet)] #![feature(type_alias_impl_trait)] +#![feature(variant_count)] #![feature(yeet_expr)] #![recursion_limit = "256"] // tidy-alphabetical-end From c4e9932cacd4508b4fde4e84bc76e177bfd0229d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Aug 2026 20:39:31 +1000 Subject: [PATCH 2/3] Remove `DepKind::label_strs` It contains pre-stringified versions of all the `DepKind` variants. But we can just stringify on demand using `format!("{:?}")`. --- .../rustc_incremental/src/persist/clean.rs | 59 +++++++++---------- .../rustc_middle/src/dep_graph/dep_node.rs | 8 --- compiler/rustc_middle/src/dep_graph/mod.rs | 4 +- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index d3a04ab5946b7..a311832e62d96 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -27,7 +27,7 @@ use rustc_hir::{ Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, intravisit, }; -use rustc_middle::dep_graph::{DepNode, dep_kind_from_label, label_strs}; +use rustc_middle::dep_graph::{DepKind, DepNode, dep_kind_from_label}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, Symbol}; @@ -38,81 +38,78 @@ use crate::diagnostics; // Base and Extra labels to build up the labels /// For typedef, constants, and statics -const BASE_CONST: &[&str] = &[label_strs::type_of]; +const BASE_CONST: &[DepKind] = &[DepKind::type_of]; /// DepNodes for functions + methods -const BASE_FN: &[&str] = &[ +const BASE_FN: &[DepKind] = &[ // Callers will depend on the signature of these items, so we better test - label_strs::fn_sig, - label_strs::generics_of, - label_strs::clauses_of, - label_strs::type_of, + DepKind::fn_sig, + DepKind::generics_of, + DepKind::clauses_of, + DepKind::type_of, // And a big part of compilation (that we eventually want to cache) is type inference // information: - label_strs::typeck_root, + DepKind::typeck_root, ]; /// DepNodes for Hir, which is pretty much everything -const BASE_HIR: &[&str] = &[ +const BASE_HIR: &[DepKind] = &[ // hir_owner should be computed for all nodes - label_strs::hir_owner, + DepKind::hir_owner, ]; /// `impl` implementation of struct/trait -const BASE_IMPL: &[&str] = - &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header]; +const BASE_IMPL: &[DepKind] = + &[DepKind::associated_item_def_ids, DepKind::generics_of, DepKind::impl_trait_header]; /// DepNodes for exported mir bodies, which is relevant in "executable" /// code, i.e., functions+methods -const BASE_MIR: &[&str] = &[label_strs::optimized_mir, label_strs::promoted_mir]; +const BASE_MIR: &[DepKind] = &[DepKind::optimized_mir, DepKind::promoted_mir]; /// Struct, Enum and Union DepNodes /// /// Note that changing the type of a field does not change the type of the struct or enum, but /// adding/removing fields or changing a fields name or visibility does. -const BASE_STRUCT: &[&str] = - &[label_strs::generics_of, label_strs::clauses_of, label_strs::type_of]; +const BASE_STRUCT: &[DepKind] = &[DepKind::generics_of, DepKind::clauses_of, DepKind::type_of]; /// Trait definition `DepNode`s. /// Extra `DepNode`s for functions and methods. -const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item]; +const EXTRA_ASSOCIATED: &[DepKind] = &[DepKind::associated_item]; -const EXTRA_TRAIT: &[&str] = &[]; +const EXTRA_TRAIT: &[DepKind] = &[]; // Fully Built Labels -const LABELS_CONST: &[&[&str]] = &[BASE_HIR, BASE_CONST]; +const LABELS_CONST: &[&[DepKind]] = &[BASE_HIR, BASE_CONST]; /// Constant/Typedef in an impl -const LABELS_CONST_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED]; +const LABELS_CONST_IN_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED]; /// Trait-Const/Typedef DepNodes -const LABELS_CONST_IN_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, EXTRA_TRAIT]; +const LABELS_CONST_IN_TRAIT: &[&[DepKind]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, EXTRA_TRAIT]; /// Function `DepNode`s. -const LABELS_FN: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN]; +const LABELS_FN: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN]; /// Method `DepNode`s. -const LABELS_FN_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED]; +const LABELS_FN_IN_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED]; /// Trait method `DepNode`s. -const LABELS_FN_IN_TRAIT: &[&[&str]] = +const LABELS_FN_IN_TRAIT: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED, EXTRA_TRAIT]; /// For generic cases like inline-assembly, modules, etc. -const LABELS_HIR_ONLY: &[&[&str]] = &[BASE_HIR]; +const LABELS_HIR_ONLY: &[&[DepKind]] = &[BASE_HIR]; /// Impl `DepNode`s. -const LABELS_TRAIT: &[&[&str]] = &[ - BASE_HIR, - &[label_strs::associated_item_def_ids, label_strs::clauses_of, label_strs::generics_of], -]; +const LABELS_TRAIT: &[&[DepKind]] = + &[BASE_HIR, &[DepKind::associated_item_def_ids, DepKind::clauses_of, DepKind::generics_of]]; /// Impl `DepNode`s. -const LABELS_IMPL: &[&[&str]] = &[BASE_HIR, BASE_IMPL]; +const LABELS_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_IMPL]; /// Abstract data type (struct, enum, union) `DepNode`s. -const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; +const LABELS_ADT: &[&[DepKind]] = &[BASE_HIR, BASE_STRUCT]; // FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these) // @@ -289,7 +286,7 @@ impl<'tcx> CleanVisitor<'tcx> { .emit_fatal(diagnostics::UndefinedCleanDirty { span, kind: format!("{node:?}") }), }; let labels = - Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); + Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| format!("{l:?}")))); (name, labels) } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index c59d9620b5e53..e2a2bb8f2a552 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -294,14 +294,6 @@ macro_rules! define_dep_nodes { _ => Err(()), } } - - /// Contains variant => str representations for constructing - /// DepNode groups for tests. - #[expect(non_upper_case_globals)] - pub mod label_strs { - $( pub const $nq_name: &str = stringify!($nq_name); )* - $( pub const $q_name: &str = stringify!($q_name); )* - } }; } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 4f9cb03ff663e..3389c3ec91a5a 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -2,9 +2,7 @@ use std::panic; use tracing::instrument; -pub use self::dep_node::{ - DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label, label_strs, -}; +pub use self::dep_node::{DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label}; pub use self::dep_node_key::DepNodeKey; pub use self::graph::{ DepGraph, DepGraphData, DepNodeIndex, QuerySideEffect, TaskDepsRef, WorkProduct, From a707cbff5b5089982d7aaf471c636b2f6de5166c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Aug 2026 07:23:11 +1000 Subject: [PATCH 3/3] Document `dep_kind_from_label_string` --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index e2a2bb8f2a552..6abec9a4ff465 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -287,7 +287,9 @@ macro_rules! define_dep_nodes { $( $(#[$q_attr])* $q_name, )* } - pub(super) fn dep_kind_from_label_string(label: &str) -> Result { + /// Converts a string to a `DepKind`. Used for handling attributes like `rustc_clean` that + /// name dep kinds. + fn dep_kind_from_label_string(label: &str) -> Result { match label { $( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )* $( stringify!($q_name) => Ok(self::DepKind::$q_name), )*