Skip to content

Also hash spans inside the same file as relative. #143882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
51 changes: 34 additions & 17 deletions compiler/rustc_middle/src/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -659,6 +660,19 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> {
parent,
);

return span;
} else if tag == 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 span = Span::new(
BytePos::from_usize((enclosing.lo.to_u32() as isize + dlo) as usize),
BytePos::from_usize((enclosing.lo.to_u32() as isize + dto) as usize),
ctxt,
parent,
);

return span;
} else {
debug_assert_eq!(tag, TAG_FULL_SPAN);
Expand Down Expand Up @@ -897,30 +911,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);
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_query_system/src/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
}

Expand Down
36 changes: 17 additions & 19 deletions compiler/rustc_span/src/caching_source_map_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand All @@ -123,27 +123,25 @@ impl<'sm> CachingSourceMapView<'sm> {

if lo_cache_idx != -1 && hi_cache_idx != -1 {
// Cache hit for span lo and hi. Check if they belong to the same file.
let result = {
let lo = &self.line_cache[lo_cache_idx as usize];
let hi = &self.line_cache[hi_cache_idx as usize];
let lo_file_index = self.line_cache[lo_cache_idx as usize].file_index;
let hi_file_index = self.line_cache[hi_cache_idx as usize].file_index;

if lo.file_index != hi.file_index {
return None;
}

(
lo.file.stable_id,
lo.line_number,
span_data.lo - lo.line.start,
hi.line_number,
span_data.hi - hi.line.start,
)
};
if lo_file_index != hi_file_index {
return None;
}

self.line_cache[lo_cache_idx as usize].touch(self.time_stamp);
self.line_cache[hi_cache_idx as usize].touch(self.time_stamp);

return Some(result);
let lo = &self.line_cache[lo_cache_idx as usize];
let hi = &self.line_cache[hi_cache_idx as usize];
return Some((
&*lo.file,
lo.line_number,
span_data.lo - lo.line.start,
hi.line_number,
span_data.hi - hi.line.start,
));
}

// No cache hit or cache hit for only one of span lo and hi.
Expand Down Expand Up @@ -226,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,
Expand Down
36 changes: 25 additions & 11 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2623,7 +2623,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;
}

Expand All @@ -2641,6 +2641,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;
Expand All @@ -2659,15 +2660,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
Expand All @@ -2680,7 +2681,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
Expand Down
Loading