Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 28 additions & 31 deletions compiler/rustc_incremental/src/persist/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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)
//
Expand Down Expand Up @@ -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)
}

Expand Down
45 changes: 14 additions & 31 deletions compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}

Expand All @@ -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::<DepKind>();

/// 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);

@cjgillot cjgillot Aug 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we bother asserting? If the subtraction underflows, the constant won't compile, will it?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NUM_VARIANTS is a usize. The intent here isn't to detect underflow, but to ensure there aren't more than 64K variants.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And while the variant count is presumably capped by #[repr(u16)] on the enum, this assertion has the benefit of making max as u16 obviously correct.

max as u16
};
}

/// Combination of a [`DepKind`] and a key fingerprint that uniquely identifies
Expand Down Expand Up @@ -279,40 +287,15 @@ 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<DepKind, ()> {
/// 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<DepKind, ()> {
match label {
$( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )*
$( stringify!($q_name) => Ok(self::DepKind::$q_name), )*
_ => 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); )*
}
};
}

Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/dep_graph/serialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
})
}),
}
Expand Down Expand Up @@ -792,7 +792,7 @@ impl EncoderState {

let mut encoder = self.file.lock().take().unwrap();

let mut kind_stats: Vec<u32> = iter::repeat_n(0, DepKind::MAX as usize + 1).collect();
let mut kind_stats: Vec<u32> = iter::repeat_n(0, DepKind::NUM_VARIANTS).collect();

let mut node_max = 0;
let mut node_count = 0;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading