@@ -2635,7 +2635,7 @@ pub trait HashStableContext {
26352635 fn span_data_to_lines_and_cols (
26362636 & mut self ,
26372637 span : & SpanData ,
2638- ) -> Option < ( StableSourceFileId , usize , BytePos , usize , BytePos ) > ;
2638+ ) -> Option < ( & SourceFile , usize , BytePos , usize , BytePos ) > ;
26392639 fn hashing_controls ( & self ) -> HashingControls ;
26402640}
26412641
@@ -2653,6 +2653,7 @@ where
26532653 /// codepoint offsets. For the purpose of the hash that's sufficient.
26542654 /// Also, hashing filenames is expensive so we avoid doing it twice when the
26552655 /// span starts and ends in the same file, which is almost always the case.
2656+ // Important: changes to this method should be reflected in implementations of `SpanEncoder`.
26562657 fn hash_stable ( & self , ctx : & mut CTX , hasher : & mut StableHasher ) {
26572658 const TAG_VALID_SPAN : u8 = 0 ;
26582659 const TAG_INVALID_SPAN : u8 = 1 ;
@@ -2671,15 +2672,15 @@ where
26712672 return ;
26722673 }
26732674
2674- if let Some ( parent) = span. parent {
2675- let def_span = ctx . def_span ( parent) . data_untracked ( ) ;
2676- if def_span . contains ( span) {
2677- // This span is enclosed in a definition: only hash the relative position.
2678- Hash :: hash ( & TAG_RELATIVE_SPAN , hasher ) ;
2679- ( span . lo - def_span . lo ) . to_u32 ( ) . hash_stable ( ctx , hasher) ;
2680- ( span. hi - def_span . lo ) . to_u32 ( ) . hash_stable ( ctx , hasher) ;
2681- return ;
2682- }
2675+ let parent = span. parent . map ( |parent| ctx . def_span ( parent ) . data_untracked ( ) ) ;
2676+ if let Some ( parent ) = parent
2677+ && parent . contains ( span)
2678+ {
2679+ // This span is enclosed in a definition: only hash the relative position.
2680+ Hash :: hash ( & TAG_RELATIVE_SPAN , hasher) ;
2681+ Hash :: hash ( & ( span. lo - parent . lo ) , hasher) ;
2682+ Hash :: hash ( & ( span . hi - parent . lo ) , hasher ) ;
2683+ return ;
26832684 }
26842685
26852686 // If this is not an empty or invalid span, we want to hash the last
@@ -2692,7 +2693,20 @@ where
26922693 } ;
26932694
26942695 Hash :: hash ( & TAG_VALID_SPAN , hasher) ;
2695- Hash :: hash ( & file, hasher) ;
2696+ Hash :: hash ( & file. stable_id , hasher) ;
2697+
2698+ if let Some ( parent) = parent
2699+ && file. contains ( parent. lo )
2700+ {
2701+ // This span is relative to another span in the same file,
2702+ // only hash the relative position.
2703+ Hash :: hash ( & TAG_RELATIVE_SPAN , hasher) ;
2704+ // Use signed difference as `span` may start before `parent`,
2705+ // for instance attributes start before their item's span.
2706+ Hash :: hash ( & ( span. lo . to_u32 ( ) as isize - parent. lo . to_u32 ( ) as isize ) , hasher) ;
2707+ Hash :: hash ( & ( span. hi . to_u32 ( ) as isize - parent. lo . to_u32 ( ) as isize ) , hasher) ;
2708+ return ;
2709+ }
26962710
26972711 // Hash both the length and the end location (line/column) of a span. If we
26982712 // hash only the length, for example, then two otherwise equal spans with
0 commit comments