diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 546791135ba61..c030574a89bf6 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -38,6 +38,7 @@ const TAG_FULL_SPAN: u8 = 0; // A partial span with no location information, encoded only with a `SyntaxContext` const TAG_PARTIAL_SPAN: u8 = 1; const TAG_RELATIVE_SPAN: u8 = 2; +const TAG_RELATIVE_OUTER_SPAN: u8 = 3; const TAG_SYNTAX_CONTEXT: u8 = 0; const TAG_EXPN_DATA: u8 = 1; @@ -654,6 +655,16 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { let enclosing = self.tcx.source_span_untracked(parent.unwrap()).data_untracked(); (enclosing.lo + BytePos::from_u32(dlo), enclosing.lo + BytePos::from_u32(dto)) } + TAG_RELATIVE_OUTER_SPAN => { + let dlo = isize::decode(self); + let dto = isize::decode(self); + + let enclosing = self.tcx.source_span_untracked(parent.unwrap()).data_untracked(); + let reference = enclosing.lo.to_u32() as isize; + let lo = BytePos::from_usize((reference + dlo) as usize); + let hi = BytePos::from_usize((reference + dto) as usize); + (lo, hi) + } TAG_FULL_SPAN => { let file_lo_index = SourceFileIndex::decode(self); let line_lo = usize::decode(self); @@ -892,30 +903,33 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { return TAG_PARTIAL_SPAN.encode(self); } - if let Some(parent) = span_data.parent { - let enclosing = self.tcx.source_span_untracked(parent).data_untracked(); - if enclosing.contains(span_data) { - TAG_RELATIVE_SPAN.encode(self); - (span_data.lo - enclosing.lo).to_u32().encode(self); - (span_data.hi - enclosing.lo).to_u32().encode(self); - return; - } + let parent = + span_data.parent.map(|parent| self.tcx.source_span_untracked(parent).data_untracked()); + if let Some(parent) = parent + && parent.contains(span_data) + { + TAG_RELATIVE_SPAN.encode(self); + (span_data.lo - parent.lo).to_u32().encode(self); + (span_data.hi - parent.lo).to_u32().encode(self); + return; } - let pos = self.source_map.byte_pos_to_line_and_col(span_data.lo); - let partial_span = match &pos { - Some((file_lo, _, _)) => !file_lo.contains(span_data.hi), - None => true, + let Some((file_lo, line_lo, col_lo)) = + self.source_map.byte_pos_to_line_and_col(span_data.lo) + else { + return TAG_PARTIAL_SPAN.encode(self); }; - if partial_span { - return TAG_PARTIAL_SPAN.encode(self); + if let Some(parent) = parent + && file_lo.contains(parent.lo) + { + TAG_RELATIVE_OUTER_SPAN.encode(self); + (span_data.lo.to_u32() as isize - parent.lo.to_u32() as isize).encode(self); + (span_data.hi.to_u32() as isize - parent.lo.to_u32() as isize).encode(self); + return; } - let (file_lo, line_lo, col_lo) = pos.unwrap(); - let len = span_data.hi - span_data.lo; - let source_file_index = self.source_file_index(file_lo); TAG_FULL_SPAN.encode(self); diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index be838f689e536..840f0b35266d0 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -5,9 +5,7 @@ use rustc_hir::definitions::DefPathHash; use rustc_session::Session; use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; -use rustc_span::{ - BytePos, CachingSourceMapView, DUMMY_SP, Span, SpanData, StableSourceFileId, Symbol, -}; +use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData, Symbol}; use crate::ich; @@ -118,7 +116,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { fn span_data_to_lines_and_cols( &mut self, span: &SpanData, - ) -> Option<(StableSourceFileId, usize, BytePos, usize, BytePos)> { + ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)> { self.source_map().span_data_to_lines_and_cols(span) } diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs index 41cfaa3ee34e5..6cf0dbb9f130f 100644 --- a/compiler/rustc_span/src/caching_source_map_view.rs +++ b/compiler/rustc_span/src/caching_source_map_view.rs @@ -2,7 +2,7 @@ use std::ops::Range; use std::sync::Arc; use crate::source_map::SourceMap; -use crate::{BytePos, Pos, RelativeBytePos, SourceFile, SpanData, StableSourceFileId}; +use crate::{BytePos, Pos, RelativeBytePos, SourceFile, SpanData}; #[derive(Clone)] struct CacheEntry { @@ -114,7 +114,7 @@ impl<'sm> CachingSourceMapView<'sm> { pub fn span_data_to_lines_and_cols( &mut self, span_data: &SpanData, - ) -> Option<(StableSourceFileId, usize, BytePos, usize, BytePos)> { + ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)> { self.time_stamp += 1; // Check if lo and hi are in the cached lines. @@ -136,7 +136,7 @@ impl<'sm> CachingSourceMapView<'sm> { let lo = &self.line_cache[lo_cache_idx as usize]; let hi = &self.line_cache[hi_cache_idx as usize]; return Some(( - lo.file.stable_id, + &*lo.file, lo.line_number, span_data.lo - lo.line.start, hi.line_number, @@ -224,7 +224,7 @@ impl<'sm> CachingSourceMapView<'sm> { assert_eq!(lo.file_index, hi.file_index); Some(( - lo.file.stable_id, + &*lo.file, lo.line_number, span_data.lo - lo.line.start, hi.line_number, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index d647ec28aae5c..61bff125cc083 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2635,7 +2635,7 @@ pub trait HashStableContext { fn span_data_to_lines_and_cols( &mut self, span: &SpanData, - ) -> Option<(StableSourceFileId, usize, BytePos, usize, BytePos)>; + ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)>; fn hashing_controls(&self) -> HashingControls; } @@ -2653,6 +2653,7 @@ where /// codepoint offsets. For the purpose of the hash that's sufficient. /// Also, hashing filenames is expensive so we avoid doing it twice when the /// span starts and ends in the same file, which is almost always the case. + // Important: changes to this method should be reflected in implementations of `SpanEncoder`. fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; @@ -2671,15 +2672,15 @@ where return; } - if let Some(parent) = span.parent { - let def_span = ctx.def_span(parent).data_untracked(); - if def_span.contains(span) { - // This span is enclosed in a definition: only hash the relative position. - Hash::hash(&TAG_RELATIVE_SPAN, hasher); - (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher); - (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher); - return; - } + let parent = span.parent.map(|parent| ctx.def_span(parent).data_untracked()); + if let Some(parent) = parent + && parent.contains(span) + { + // This span is enclosed in a definition: only hash the relative position. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + Hash::hash(&(span.lo - parent.lo), hasher); + Hash::hash(&(span.hi - parent.lo), hasher); + return; } // If this is not an empty or invalid span, we want to hash the last @@ -2692,7 +2693,20 @@ where }; Hash::hash(&TAG_VALID_SPAN, hasher); - Hash::hash(&file, hasher); + Hash::hash(&file.stable_id, hasher); + + if let Some(parent) = parent + && file.contains(parent.lo) + { + // This span is relative to another span in the same file, + // only hash the relative position. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + // Use signed difference as `span` may start before `parent`, + // for instance attributes start before their item's span. + Hash::hash(&(span.lo.to_u32() as isize - parent.lo.to_u32() as isize), hasher); + Hash::hash(&(span.hi.to_u32() as isize - parent.lo.to_u32() as isize), hasher); + return; + } // Hash both the length and the end location (line/column) of a span. If we // hash only the length, for example, then two otherwise equal spans with