diff options
| author | bors <bors@rust-lang.org> | 2020-11-12 15:34:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-11-12 15:34:09 +0000 |
| commit | 9722952f0bed5815cb22cb4878be09fb39f92804 (patch) | |
| tree | 270b703ec4edbb5a4c94f9edaac23b714d7a0512 /compiler/rustc_span/src | |
| parent | 7f5a42b073dc2bee2aa625052eb066ee07072048 (diff) | |
| parent | dac57e67d6116bcad81f905b8e92be3e9d8e4d23 (diff) | |
| download | rust-9722952f0bed5815cb22cb4878be09fb39f92804.tar.gz rust-9722952f0bed5815cb22cb4878be09fb39f92804.zip | |
Auto merge of #76256 - tgnottingham:issue-74890, r=nikomatsakis
incr-comp: hash and serialize span end line/column 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 different end locations will have the same hash. This can cause a problem during incremental compilation wherein a previous result for a query that depends on the end location of a span will be incorrectly reused when the end location of the span it depends on has changed. A similar analysis applies if some query depends specifically on the length of the span, but we only hash the end location. So hash both. Fix #46744, fix #59954, fix #63161, fix #73640, fix #73967, fix #74890, fix #75900 --- See #74890 for a more in-depth analysis. I haven't thought about what other problems this root cause could be responsible for. Please let me know if anything springs to mind. I believe the issue has existed since the inception of incremental compilation.
Diffstat (limited to 'compiler/rustc_span/src')
| -rw-r--r-- | compiler/rustc_span/src/lib.rs | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f52b64f4883..0926561f4c5 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1894,16 +1894,37 @@ where return; } + let (_, line_hi, col_hi) = match ctx.byte_pos_to_line_and_col(span.hi) { + Some(pos) => pos, + None => { + Hash::hash(&TAG_INVALID_SPAN, hasher); + span.ctxt.hash_stable(ctx, hasher); + return; + } + }; + Hash::hash(&TAG_VALID_SPAN, hasher); // We truncate the stable ID hash and line and column numbers. The chances // of causing a collision this way should be minimal. Hash::hash(&(file_lo.name_hash as u64), hasher); - let col = (col_lo.0 as u64) & 0xFF; - let line = ((line_lo as u64) & 0xFF_FF_FF) << 8; - let len = ((span.hi - span.lo).0 as u64) << 32; - let line_col_len = col | line | len; - Hash::hash(&line_col_len, hasher); + // 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 + // different end locations will have the same hash. This can cause a problem + // during incremental compilation wherein a previous result for a query that + // depends on the end location of a span will be incorrectly reused when the + // end location of the span it depends on has changed (see issue #74890). A + // similar analysis applies if some query depends specifically on the length + // of the span, but we only hash the end location. So hash both. + + let col_lo_trunc = (col_lo.0 as u64) & 0xFF; + let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; + let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; + let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; + let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; + let len = (span.hi - span.lo).0; + Hash::hash(&col_line, hasher); + Hash::hash(&len, hasher); span.ctxt.hash_stable(ctx, hasher); } } |
