Skip to content
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

incr-comp: hash and serialize span end line/column #76256

Merged
merged 3 commits into from
Nov 12, 2020
Merged
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
31 changes: 26 additions & 5 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1878,16 +1878,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);
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/test/run-make/incr-prev-body-beyond-eof/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
include ../../run-make-fulldeps/tools.mk

# FIXME https://github.com/rust-lang/rust/issues/78911
# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)

tgnottingham marked this conversation as resolved.
Show resolved Hide resolved
# Tests that we don't ICE during incremental compilation after modifying a
# function span such that its previous end line exceeds the number of lines
# in the new file, but its start line/column and length remain the same.

SRC=$(TMPDIR)/src
INCR=$(TMPDIR)/incr
tgnottingham marked this conversation as resolved.
Show resolved Hide resolved

all:
mkdir $(SRC)
mkdir $(INCR)
cp a.rs $(SRC)/main.rs
$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs
cp b.rs $(SRC)/main.rs
$(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs
tgnottingham marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions src/test/run-make/incr-prev-body-beyond-eof/a.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
fn main() {
// foo must be used.
foo();
}

// For this test to operate correctly, foo's body must start on exactly the same
// line and column and have the exact same length in bytes in a.rs and b.rs. In
// a.rs, the body must end on a line number which does not exist in b.rs.
// Basically, avoid modifying this file, including adding or removing whitespace!
fn foo() {
assert_eq!(1, 1);




}
12 changes: 12 additions & 0 deletions src/test/run-make/incr-prev-body-beyond-eof/b.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fn main() {
// foo must be used.
foo();
}

// For this test to operate correctly, foo's body must start on exactly the same
// line and column and have the exact same length in bytes in a.rs and b.rs. In
// a.rs, the body must end on a line number which does not exist in b.rs.
// Basically, avoid modifying this file, including adding or removing whitespace!
fn foo() {
assert_eq!(1, 1);////
}
1 change: 1 addition & 0 deletions src/test/run-make/issue-36710/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include ../../run-make-fulldeps/tools.mk

# FIXME https://github.com/rust-lang/rust/issues/78911
# ignore-32bit wrong/no cross compiler and sometimes we pass wrong gcc args (-m64)

all: foo
Expand Down