Properly handle SyntaxContext
of dummy spans in incr comp
Fixes #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.
This commit is contained in:
parent
fd2df74902
commit
482a67d20f
@ -32,8 +32,10 @@ use std::mem;
|
||||
|
||||
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
|
||||
|
||||
const TAG_VALID_SPAN: u8 = 0;
|
||||
const TAG_INVALID_SPAN: u8 = 1;
|
||||
// A normal span encoded with both location information and a `SyntaxContext`
|
||||
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_SYNTAX_CONTEXT: u8 = 0;
|
||||
const TAG_EXPN_DATA: u8 = 1;
|
||||
@ -864,10 +866,11 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
|
||||
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
|
||||
let tag: u8 = Decodable::decode(decoder)?;
|
||||
|
||||
if tag == TAG_INVALID_SPAN {
|
||||
return Ok(DUMMY_SP);
|
||||
if tag == TAG_PARTIAL_SPAN {
|
||||
let ctxt = SyntaxContext::decode(decoder)?;
|
||||
return Ok(DUMMY_SP.with_ctxt(ctxt));
|
||||
} else {
|
||||
debug_assert_eq!(tag, TAG_VALID_SPAN);
|
||||
debug_assert_eq!(tag, TAG_FULL_SPAN);
|
||||
}
|
||||
|
||||
let file_lo_index = SourceFileIndex::decode(decoder)?;
|
||||
@ -1057,24 +1060,29 @@ where
|
||||
{
|
||||
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
|
||||
if *self == DUMMY_SP {
|
||||
return TAG_INVALID_SPAN.encode(s);
|
||||
TAG_PARTIAL_SPAN.encode(s)?;
|
||||
return SyntaxContext::root().encode(s);
|
||||
}
|
||||
|
||||
let span_data = self.data();
|
||||
let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
|
||||
Some(pos) => pos,
|
||||
None => return TAG_INVALID_SPAN.encode(s),
|
||||
let pos = s.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,
|
||||
};
|
||||
|
||||
if !file_lo.contains(span_data.hi) {
|
||||
return TAG_INVALID_SPAN.encode(s);
|
||||
if partial_span {
|
||||
TAG_PARTIAL_SPAN.encode(s)?;
|
||||
return span_data.ctxt.encode(s);
|
||||
}
|
||||
|
||||
let (file_lo, line_lo, col_lo) = pos.unwrap();
|
||||
|
||||
let len = span_data.hi - span_data.lo;
|
||||
|
||||
let source_file_index = s.source_file_index(file_lo);
|
||||
|
||||
TAG_VALID_SPAN.encode(s)?;
|
||||
TAG_FULL_SPAN.encode(s)?;
|
||||
source_file_index.encode(s)?;
|
||||
line_lo.encode(s)?;
|
||||
col_lo.encode(s)?;
|
||||
|
@ -1899,8 +1899,9 @@ where
|
||||
return;
|
||||
}
|
||||
|
||||
if *self == DUMMY_SP {
|
||||
if self.is_dummy() {
|
||||
Hash::hash(&TAG_INVALID_SPAN, hasher);
|
||||
self.ctxt().hash_stable(ctx, hasher);
|
||||
return;
|
||||
}
|
||||
|
||||
|
10
src/test/incremental/issue-80336-invalid-span.rs
Normal file
10
src/test/incremental/issue-80336-invalid-span.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Regression test for issue #80336
|
||||
// Test that we properly handle encoding, decoding, and hashing
|
||||
// of spans with an invalid location and non-root `SyntaxContext`
|
||||
|
||||
// revisions:rpass1 rpass2
|
||||
// only-x86_64
|
||||
|
||||
pub fn main() {
|
||||
let _ = is_x86_feature_detected!("avx2");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user