Auto merge of #148043 - lqd:revert-146121, r=wesleywiser

Revert "fix: Filter suggestion parts that match existing code"

As requested by `@wesleywiser` in https://github.com/rust-lang/rust/issues/147973#issuecomment-3437393773 this is a revert of https://github.com/rust-lang/rust/pull/146121 due to the handful of diagnostics ICEs that have been since reported, and found in the beta crater run.

This should thus also be backported to beta so the ICEs don't make it to next week's stable.

Works around (after backport)
- https://github.com/rust-lang/rust/issues/146261
- https://github.com/rust-lang/rust/issues/146706
- https://github.com/rust-lang/rust/issues/146834 but I didn't add a test for this allowed-by-default lint
- as well as the crater run regressions from https://github.com/rust-lang/rust/issues/147973 of which I only added the MCVE as a test.

The proper fix would likely be https://github.com/rust-lang/rust/pull/147849 but it's still currently at the MCP stage. In the meantime, this PR would still emit the same overlapping suggestions, but still use a debug-assert...

r? `@wesleywiser`
This commit is contained in:
bors 2025-10-24 09:50:35 +00:00
commit 8aab621cd5
8 changed files with 81 additions and 21 deletions

View file

@ -945,6 +945,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
None,
"Span must not be empty and have no suggestion",
);
debug_assert_eq!(
parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
None,
"suggestion must not have overlapping parts",
);
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution { parts }],

View file

@ -2350,6 +2350,7 @@ impl HumanEmitter {
.sum();
let underline_start = (span_start_pos + start) as isize + offset;
let underline_end = (span_start_pos + start + sub_len) as isize + offset;
assert!(underline_start >= 0 && underline_end >= 0);
let padding: usize = max_line_num_len + 3;
for p in underline_start..underline_end {
if let DisplaySuggestion::Underline = show_code_change

View file

@ -400,17 +400,6 @@ impl CodeSuggestion {
// Assumption: all spans are in the same file, and all spans
// are disjoint. Sort in ascending order.
substitution.parts.sort_by_key(|part| part.span.lo());
// Verify the assumption that all spans are disjoint
assert_eq!(
substitution.parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
None,
"all spans must be disjoint",
);
// Account for cases where we are suggesting the same code that's already
// there. This shouldn't happen often, but in some cases for multipart
// suggestions it's much easier to handle it here than in the origin.
substitution.parts.retain(|p| is_different(sm, &p.snippet, p.span));
// Find the bounding span.
let lo = substitution.parts.iter().map(|part| part.span.lo()).min()?;
@ -505,12 +494,16 @@ impl CodeSuggestion {
_ => 1,
})
.sum();
line_highlight.push(SubstitutionHighlight {
start: (cur_lo.col.0 as isize + acc) as usize,
end: (cur_lo.col.0 as isize + acc + len) as usize,
});
if !is_different(sm, &part.snippet, part.span) {
// Account for cases where we are suggesting the same code that's already
// there. This shouldn't happen often, but in some cases for multipart
// suggestions it's much easier to handle it here than in the origin.
} else {
line_highlight.push(SubstitutionHighlight {
start: (cur_lo.col.0 as isize + acc) as usize,
end: (cur_lo.col.0 as isize + acc + len) as usize,
});
}
buf.push_str(&part.snippet);
let cur_hi = sm.lookup_char_pos(part.span.hi());
// Account for the difference between the width of the current code and the

View file

@ -272,8 +272,10 @@ LL | assert_eq!(a!(), true);
|
help: replace it with `assert!(..)`
|
LL - assert_eq!(a!(), true);
LL + assert!(a!());
LL | true
...
LL |
LL ~ assert!(a!());
|
error: used `assert_eq!` with a literal bool
@ -284,8 +286,10 @@ LL | assert_eq!(true, b!());
|
help: replace it with `assert!(..)`
|
LL - assert_eq!(true, b!());
LL + assert!(b!());
LL | true
...
LL |
LL ~ assert!(b!());
|
error: used `debug_assert_eq!` with a literal bool

13
tests/crashes/146261.rs Normal file
View file

@ -0,0 +1,13 @@
// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with
// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121.
//@ needs-rustc-debug-assertions
//@ known-bug: #146261
enum U {
B(),
}
fn main() {
A(U::C)
}

15
tests/crashes/146706.rs Normal file
View file

@ -0,0 +1,15 @@
// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with
// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121.
//@ needs-rustc-debug-assertions
//@ known-bug: #146706
type Alias<'a, T> = Foo<T>;
enum Foo<T> {
Bar { t: T },
}
fn main() {
Alias::Bar::<u32> { t: 0 };
}

14
tests/crashes/147973.rs Normal file
View file

@ -0,0 +1,14 @@
// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with
// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121.
// This is one MCVE from the beta crater run regressions from issue 147973.
//@ needs-rustc-debug-assertions
//@ known-bug: #147973
//@ aux-build: overlapping_spans_helper.rs
extern crate overlapping_spans_helper;
fn main() {
let _name = Some(1);
overlapping_spans_helper::do_loop!(_name);
}

View file

@ -0,0 +1,15 @@
// Auxiliary lib for the issue 147973 regression test with ICEs due to overlapping spans.
#[macro_export]
macro_rules! identity {
($x:ident) => {
$x
};
}
#[macro_export]
macro_rules! do_loop {
($x:ident) => {
for $crate::identity!($x) in $x {}
};
}