Skip to content

Commit 180fdff

Browse files
committed
Auto merge of rust-lang#80654 - Aaron1011:fix/dummy-span-ctxt, r=wesleywiser
Properly handle `SyntaxContext` of dummy spans in incr comp Fixes rust-lang#80336 Due to macro expansion, we may end up with spans with an invalid location and non-root `SyntaxContext`. This commits preserves the `SyntaxContext` of such spans in the incremental cache, and ensures that we always hash the `SyntaxContext` when computing the `Fingerprint` of a `Span` Previously, we would discard the `SyntaxContext` during serialization to the incremental cache, causing the span's `Fingerprint` to change across compilation sessions.
2 parents a62a760 + 482a67d commit 180fdff

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ use std::mem;
3232

3333
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
3434

35-
const TAG_VALID_SPAN: u8 = 0;
36-
const TAG_INVALID_SPAN: u8 = 1;
35+
// A normal span encoded with both location information and a `SyntaxContext`
36+
const TAG_FULL_SPAN: u8 = 0;
37+
// A partial span with no location information, encoded only with a `SyntaxContext`
38+
const TAG_PARTIAL_SPAN: u8 = 1;
3739

3840
const TAG_SYNTAX_CONTEXT: u8 = 0;
3941
const TAG_EXPN_DATA: u8 = 1;
@@ -864,10 +866,11 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
864866
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
865867
let tag: u8 = Decodable::decode(decoder)?;
866868

867-
if tag == TAG_INVALID_SPAN {
868-
return Ok(DUMMY_SP);
869+
if tag == TAG_PARTIAL_SPAN {
870+
let ctxt = SyntaxContext::decode(decoder)?;
871+
return Ok(DUMMY_SP.with_ctxt(ctxt));
869872
} else {
870-
debug_assert_eq!(tag, TAG_VALID_SPAN);
873+
debug_assert_eq!(tag, TAG_FULL_SPAN);
871874
}
872875

873876
let file_lo_index = SourceFileIndex::decode(decoder)?;
@@ -1057,24 +1060,29 @@ where
10571060
{
10581061
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
10591062
if *self == DUMMY_SP {
1060-
return TAG_INVALID_SPAN.encode(s);
1063+
TAG_PARTIAL_SPAN.encode(s)?;
1064+
return SyntaxContext::root().encode(s);
10611065
}
10621066

10631067
let span_data = self.data();
1064-
let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
1065-
Some(pos) => pos,
1066-
None => return TAG_INVALID_SPAN.encode(s),
1068+
let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
1069+
let partial_span = match &pos {
1070+
Some((file_lo, _, _)) => !file_lo.contains(span_data.hi),
1071+
None => true,
10671072
};
10681073

1069-
if !file_lo.contains(span_data.hi) {
1070-
return TAG_INVALID_SPAN.encode(s);
1074+
if partial_span {
1075+
TAG_PARTIAL_SPAN.encode(s)?;
1076+
return span_data.ctxt.encode(s);
10711077
}
10721078

1079+
let (file_lo, line_lo, col_lo) = pos.unwrap();
1080+
10731081
let len = span_data.hi - span_data.lo;
10741082

10751083
let source_file_index = s.source_file_index(file_lo);
10761084

1077-
TAG_VALID_SPAN.encode(s)?;
1085+
TAG_FULL_SPAN.encode(s)?;
10781086
source_file_index.encode(s)?;
10791087
line_lo.encode(s)?;
10801088
col_lo.encode(s)?;

compiler/rustc_span/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1899,8 +1899,9 @@ where
18991899
return;
19001900
}
19011901

1902-
if *self == DUMMY_SP {
1902+
if self.is_dummy() {
19031903
Hash::hash(&TAG_INVALID_SPAN, hasher);
1904+
self.ctxt().hash_stable(ctx, hasher);
19041905
return;
19051906
}
19061907

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Regression test for issue #80336
2+
// Test that we properly handle encoding, decoding, and hashing
3+
// of spans with an invalid location and non-root `SyntaxContext`
4+
5+
// revisions:rpass1 rpass2
6+
// only-x86_64
7+
8+
pub fn main() {
9+
let _ = is_x86_feature_detected!("avx2");
10+
}

0 commit comments

Comments
 (0)