From 42fd1853f7bafbdae604c885d8584d764b97d5da Mon Sep 17 00:00:00 2001 From: xmakro Date: Tue, 8 Sep 2026 21:41:22 -0700 Subject: [PATCH] Try a checked recent source-file index before binary search [skip ci] --- compiler/rustc_span/src/source_map.rs | 15 ++++++++++++++- compiler/rustc_span/src/source_map/tests.rs | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f394765ab9f8e..126272f6bec16 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -11,6 +11,7 @@ use std::fs::File; use std::io::{self, BorrowedBuf, Read}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::{fs, path}; use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock}; @@ -196,6 +197,7 @@ pub struct SourceMapInputs { pub struct SourceMap { files: RwLock, + recent_file_index: AtomicUsize, file_loader: IntoDynSyncSend>, // This is used to apply the file path remapping as specified via @@ -219,6 +221,7 @@ impl std::fmt::Debug for SourceMap { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let SourceMap { files, + recent_file_index: _, file_loader, path_mapping, working_dir, @@ -257,6 +260,7 @@ impl SourceMap { debug!(?working_dir); SourceMap { files: Default::default(), + recent_file_index: AtomicUsize::new(usize::MAX), working_dir, file_loader: IntoDynSyncSend(file_loader), path_mapping, @@ -1086,7 +1090,16 @@ impl SourceMap { /// This index is guaranteed to be valid for the lifetime of this `SourceMap`, /// since `source_files` is a `MonotonicVec` pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { - self.files.borrow().source_files.partition_point(|x| x.start_pos <= pos) - 1 + let files = self.files.borrow(); + let recent = self.recent_file_index.load(Ordering::Relaxed); + // Files are append-only and their inclusive position ranges never overlap. + // The hint carries no synchronization: validate it against the borrowed table. + if files.source_files.get(recent).is_some_and(|file| file.contains(pos)) { + return recent; + } + let index = files.source_files.partition_point(|x| x.start_pos <= pos) - 1; + self.recent_file_index.store(index, Ordering::Relaxed); + index } pub fn count_lines(&self) -> usize { diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 4cc243667f224..052d6fd623ae6 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -797,3 +797,20 @@ fn read_binary_file_handles_lying_stat() { let bin = RealFileLoader.read_binary_file(kernel_max).unwrap(); assert_eq!(&real[..], &bin[..]); } + +#[test] +fn lookup_source_file_hint_matches_search_after_append() { + create_default_session_globals_then(|| { + let sm = init_source_map(); + for extra in ["", "aƩ\nb", "last"] { + let end = sm.files().last().unwrap().end_position().0; + for pos in (0..=end + 4).chain((0..=end + 4).rev()) { + let pos = BytePos(pos); + let expected = sm.files().partition_point(|file| file.start_pos <= pos) - 1; + assert_eq!(sm.lookup_source_file_idx(pos), expected); + assert_eq!(sm.lookup_source_file_idx(pos), expected); + } + sm.new_source_file(filename(&sm, &format!("extra-{end}.rs")), extra.into()); + } + }); +}