From f38bdb42581d4cc7c50845f9f43fc79119e6f173 Mon Sep 17 00:00:00 2001 From: Makro Date: Mon, 13 Jul 2026 19:31:38 +0000 Subject: [PATCH] perf: skip span hashing in non-incremental builds --- compiler/rustc_middle/src/ich.rs | 22 +++++++++++++--------- compiler/rustc_query_impl/src/plumbing.rs | 7 ++++++- compiler/rustc_span/src/lib.rs | 5 +++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ich.rs b/compiler/rustc_middle/src/ich.rs index 80db9a95c918a..fb2ed2b6d1312 100644 --- a/compiler/rustc_middle/src/ich.rs +++ b/compiler/rustc_middle/src/ich.rs @@ -22,9 +22,9 @@ enum CachingSourceMap<'a> { /// things (e.g., each `DefId`/`DefPath` is only hashed once). pub struct StableHashState<'a> { untracked: &'a Untracked, - // The value of `-Z incremental-ignore-spans`. - // This field should only be used by `unstable_opts_incremental_ignore_span` - incremental_ignore_spans: bool, + // The session-wide default for `hash_spans`, computed in `Self::new`. Only + // used by `assert_default_stable_hash_controls`. + default_hash_spans: bool, caching_source_map: CachingSourceMap<'a>, stable_hash_controls: StableHashControls, } @@ -32,11 +32,15 @@ pub struct StableHashState<'a> { impl<'a> StableHashState<'a> { #[inline] pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self { - let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans; + // Only hash spans for incremental and coverage, where hashes must react to + // code moving around; otherwise skip them and their source map lookups. + // Spans are also skipped if `-Z incremental-ignore-spans` is set. + let hash_spans_initial = (sess.opts.incremental.is_some() || sess.instrument_coverage()) + && !sess.opts.unstable_opts.incremental_ignore_spans; StableHashState { untracked, - incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, + default_hash_spans: hash_spans_initial, caching_source_map: CachingSourceMap::Unused(sess.source_map()), stable_hash_controls: StableHashControls { hash_spans: hash_spans_initial }, } @@ -178,15 +182,15 @@ impl<'a> StableHashCtxt for StableHashState<'a> { let stable_hash_controls = self.stable_hash_controls; let StableHashControls { hash_spans } = stable_hash_controls; - // Note that we require that `hash_spans` be the inverse of the global `-Z - // incremental-ignore-spans` option. Normally, this option is disabled, in which case - // `hash_spans` must be true. + // Note that we require that `hash_spans` matches the session-wide default computed in + // `StableHashState::new` from the compilation mode and the global `-Z + // incremental-ignore-spans` option. // // Span hashing can also be disabled without `-Z incremental-ignore-spans`. This is the // case for instance when building a hash for name mangling. Such configuration must not be // used for metadata. assert_eq!( - hash_spans, !self.incremental_ignore_spans, + hash_spans, self.default_hash_spans, "Attempted hashing of {msg} with non-default StableHashControls: {stable_hash_controls:?}" ); } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 8b7a2ccb232d0..4e21e4e14b8f5 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -100,7 +100,12 @@ fn encode_query_values_inner<'a, 'tcx, C, V>( } pub(crate) fn verify_query_key_hashes<'tcx>(tcx: TyCtxt<'tcx>) { - if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { + // Only run this if the dep graph is enabled. Otherwise there are no `DepNode`s + // to collide, and non-incremental builds skip span hashing, so keys differing + // only in spans collide by design. + if tcx.dep_graph.is_fully_enabled() + && (tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions)) + { tcx.sess.time("verify_query_key_hashes", || { for_each_query_vtable!(ALL, tcx, |query| { verify_query_key_hashes_inner(query, tcx); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 5015741f10c5f..05095a0d99404 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1983,8 +1983,9 @@ impl Encodable for SourceFile { self.normalized_source_len.encode(s); self.unnormalized_source_len.encode(s); - // We are always in `Lines` form by the time we reach here. - assert!(self.lines.read().is_lines()); + // Imported files may still be in compressed `Diffs` form if nothing needed + // their line table (non-incremental builds do not force the conversion by + // hashing spans). `lines()` converts on demand. let lines = self.lines(); // Store the length. s.emit_u32(lines.len() as u32);