-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Fix the bug of next_point in source_map #103185
Conversation
1cb5780
to
0af255a
Compare
@bors r+ |
// If the width is 1, then the next span should point to the same `lo` and `hi`. However, | ||
// in the case of a multibyte character, where the width != 1, the next span should | ||
// span multiple bytes to include the whole character. | ||
let end_of_next_point = | ||
start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point); | ||
start_of_next_point.checked_add(width).unwrap_or(start_of_next_point); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've always found this bit confusing, but I'm wondering if this comment is now out-of-date?
The next_point()
function used to return an empty span (when the "width is 1" as in the comment) pointing just before the next character. This change seems to change it so that it is a non-empty span containing the next character.
I'm also wondering if the name of the function is also a bit misleading? The original next_point
function always returned an empty span (a "point", not a region). This was changed in #47420 to have the somewhat confusing behavior where an empty span would move forward to span the next character (non-empty), and a non-empty span would return an empty span pointing just past the end. It's not clear from that PR why that behavior was chosen.
I also think this function is still somewhat buggy with respect to multi-byte characters. Below is a unittest which illustrates some oddities. Perhaps it might be good to add this unittest?
#[test]
fn next_point() {
let sm = SourceMap::new(FilePathMapping::empty());
sm.new_source_file(PathBuf::from("example.rs").into(), "a…b".to_string());
let span = Span::with_root_ctxt(BytePos(0), BytePos(0));
// This confusingly does not advance the span?
let span = sm.next_point(span);
assert_eq!(span.lo().0, 0);
assert_eq!(span.hi().0, 0); // ERROR: This should probably be 1?
let span = Span::with_root_ctxt(BytePos(0), BytePos(1));
let span = sm.next_point(span);
assert_eq!(span.lo().0, 1);
assert_eq!(span.hi().0, 4);
// This creates an invalid span, slicing in the middle of a multi-byte char?
let span = Span::with_root_ctxt(BytePos(1), BytePos(1));
let span = sm.next_point(span);
assert_eq!(span.lo().0, 1);
assert_eq!(span.hi().0, 2); // ERROR: This should probably be 4?
let span = Span::with_root_ctxt(BytePos(1), BytePos(4));
let span = sm.next_point(span);
assert_eq!(span.lo().0, 4);
assert_eq!(span.hi().0, 5);
// This creates an invalid span, pointing past the end of the file?
let span = sm.next_point(span);
assert_eq!(span.lo().0, 5);
assert_eq!(span.hi().0, 6); // ERROR: This should probably be 5?
// Empty span pointing just past the last byte.
let span = Span::with_root_ctxt(BytePos(5), BytePos(5));
let span = sm.next_point(span);
assert_eq!(span.lo().0, 5);
assert_eq!(span.hi().0, 6); // ERROR: This should probably be 5?
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unit test implied another issue:
// This creates an invalid span, slicing in the middle of a multi-byte char?
let span = Span::with_root_ctxt(BytePos(1), BytePos(1));
let span = sm.next_point(span);
assert_eq!(span.lo().0, 1);
assert_eq!(span.hi().0, 2);
When lo
and hi
are same, we just reutrn the width with 1:
rust/compiler/rustc_span/src/source_map.rs
Line 877 in 194140b
if sp.lo == sp.hi { |
So the result is span.hi().0
will be 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ehuss,
I fixed all other issues in the test cases, except for this one:
let span = sm.next_point(span);
assert_eq!(span.lo().0, 0);
assert_eq!(span.hi().0, 0); // ERROR: This should probably be 1?
It return the same span because it's a dummy span, something special for macros..
…int, r=davidtwco Fix the bug of next_point in source_map There is a bug in `next_point`, the new span won't move to next position when be called in the first time. For this reason, our current code is working like this: 1. When we really want to move to the next position, we called two times of `next_point` 2. Some code which use `next_point` actually done the same thing with `shrink_to_hi` This fix make sure when `next_point` is called, span will move with the width at least 1, and also work correctly in the scenario of multiple bytes. Ref: rust-lang#103140 (comment) r? `@davidtwco`
@bors rollup=iffy might cause some clippy output change? |
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
This comment has been minimized.
This comment has been minimized.
663a55f
to
e84cdb8
Compare
This comment has been minimized.
This comment has been minimized.
Fixed by: - let hi = cx.sess().source_map().next_point(remove_span).hi();
- let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
+ let fmpos = cx.sess().source_map().lookup_byte_offset(remove_span.hi()); r? @davidtwco |
d35bd9d
to
249b1d5
Compare
@bors r- |
Please avoid pushing to the pull request after it has been approved, or ping someone to unapprove it if you have to, otherwise it can get merged with only the earlier changes. |
@bors r+ |
📌 Commit 249b1d54a8c1c3238cb131433642a34dcc24ef39 has been approved by It is now in the queue for this repository. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, FWIW, there is a dedicated test file for SourceMap
in rustc_span/src/source_map/tests.rs
, might be better to put this test there since it is primarily for SourceMap
.
…_character_at_span
@bors r- |
249b1d5
to
eb8aa97
Compare
r? @davidtwco |
@bors r+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (53728ff): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. Footnotes |
This may have introduced a compiler hang: #103451 |
…t, r=davidtwco Fix the bug of next_point in source_map There is a bug in `next_point`, the new span won't move to next position when be called in the first time. For this reason, our current code is working like this: 1. When we really want to move to the next position, we called two times of `next_point` 2. Some code which use `next_point` actually done the same thing with `shrink_to_hi` This fix make sure when `next_point` is called, span will move with the width at least 1, and also work correctly in the scenario of multiple bytes. Ref: rust-lang#103140 (comment) r? `@davidtwco`
There is a bug in
next_point
, the new span won't move to next position when be called in the first time.For this reason, our current code is working like this:
next_point
next_point
actually done the same thing withshrink_to_hi
This fix make sure when
next_point
is called, span will move with the width at least 1, and also work correctly in the scenario of multiple bytes.Ref: #103140 (comment)
r? @davidtwco