Skip to content
Open
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
36 changes: 31 additions & 5 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2714,11 +2714,37 @@ impl<'test> TestCx<'test> {
(&tmp.0, &tmp.1)
}
} else if compare_output_by_lines {
let mut actual_lines: Vec<&str> = actual.lines().collect();
let mut expected_lines: Vec<&str> = expected.lines().collect();
actual_lines.sort_unstable();
expected_lines.sort_unstable();
if actual_lines == expected_lines {
// SVG output (`--color=always`) renders one terminal row per line,
// laid out top to bottom. Under the parallel front-end, independent
// diagnostics can be emitted in a different order, which permutes the
// rows and re-renders each at a different vertical `y` offset without
// changing its content. Strip the `y` coordinate (and the first line,
// the `<svg>` header whose width/height are already ignored by the
// exact comparison above) before the line-multiset comparison so that
// such a reordering is not reported as a difference. The normalization
// is comparison-only: on mismatch the original strings are kept for
// the diff and for blessing. Single-threaded runs take the
// exact-comparison path above and still check `y`.
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zetanumbers
At least the root cause analyses look plausible (although they need to be verified by a human of course), and may be potentially put into the tracking issue, even if the change is not merged.

View changes since the review

Copy link
Copy Markdown
Contributor Author

@xmakro xmakro Jun 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running the SVG test under the parallel frontend at head, then any run fails the existing line by line comparison, and compiletest writes the actual rendered SVG to disk:

RS=tests/ui/error-emitter/multiline-removal-suggestion.rs
for i in $(seq 1 40); do
  ./x test $RS --test-args "--parallel-frontend-threads=16" --force-rerun
done
# each failing run prints: Saved the actual svg to `<build>/.../multiline-removal-suggestion.svg`

Both files are 456 lines, but the diagnostic blocks come out in a different vertical order:

A: E0277@21:8 E0277@53:28 E0277@43:7 E0277@32:6 E0277@50:2 E0277@39:2 ...
B: E0277@43:7 E0277@39:2 E0277@53:28 E0277@32:6 E0277@21:8 E0277@50:2 ...

Raw sorted line comparison, which is what the test does before this PR:

$ diff <(sort A.svg) <(sort B.svg) | grep -c '^[<>]'
232      # nonzero, so the comparison reports a difference

By comparison, with this PR, we drop the <svg> header line, replace y="..px" with a constant, then sort:

$ norm(){ tail -n +2 "$1" | sed -E 's/y="[0-9]+px"/y="0px"/g' | sort; }
$ diff <(norm A.svg) <(norm B.svg) | grep -c '^[<>]'
0        # identical as a multiset

Each differing line is the same row at a different height. For example the rows for the span at :39:2:

A: <tspan x="10px" y="1648px"> ... rs:39:2</tspan>
B: <tspan x="10px" y="370px"> ... rs:39:2</tspan>

The content is the same but the y changes. After the substitution both become y="0px" and match.

let matches = if self.force_color_svg() {
let strip_y = static_regex!(r#"y="\d+px""#);
let normalize = |svg: &str| {
let mut lines: Vec<String> = svg
.lines()
.skip(1)
.map(|line| strip_y.replace_all(line, r#"y="0px""#).into_owned())
.collect();
lines.sort_unstable();
lines
};
normalize(expected) == normalize(actual)
} else {
let mut actual_lines: Vec<&str> = actual.lines().collect();
let mut expected_lines: Vec<&str> = expected.lines().collect();
actual_lines.sort_unstable();
expected_lines.sort_unstable();
actual_lines == expected_lines
};
if matches {
return CompareOutcome::Same;
} else {
(expected, actual)
Expand Down
1 change: 0 additions & 1 deletion tests/ui/error-emitter/multiline-removal-suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,3 @@ fn bay() -> Vec<(bool, HashSet<u8>)> {
.collect()
}
fn main() {}
//@ ignore-parallel-frontend invalid svg(multiple threads trying to write to the same file)
Loading