From 81557349be64db933c5060a6e1d7398bef32e0d7 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 27 Aug 2025 20:33:50 -0600 Subject: [PATCH 1/3] refactor: Move assert for disjoint substitution spans --- compiler/rustc_errors/src/emitter.rs | 1 - compiler/rustc_errors/src/lib.rs | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b94370e8e9b40..93b1e6b761520 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2354,7 +2354,6 @@ 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 diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a56e0f3fae132..7d8577ac2c268 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -381,6 +381,12 @@ 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", + ); // Find the bounding span. let lo = substitution.parts.iter().map(|part| part.span.lo()).min()?; From f196f50d6609eecfe94989a317a8779637288d94 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Thu, 4 Sep 2025 16:21:44 -0600 Subject: [PATCH 2/3] chore: Remove redundant disjoint spans assert --- compiler/rustc_errors/src/diagnostic.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 96a4ed3218fbf..ae23ef1e25536 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -945,11 +945,6 @@ 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 }], From b307a1146b4af3b5808510e44a13f56f2b0252e9 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 27 Aug 2025 20:33:50 -0600 Subject: [PATCH 3/3] fix: Filter suggestion parts that match existing code --- compiler/rustc_errors/src/lib.rs | 21 ++++++++++--------- .../tests/ui/bool_assert_comparison.stderr | 12 ++++------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7d8577ac2c268..8869799ce90d9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -388,6 +388,11 @@ impl CodeSuggestion { "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()?; let hi = substitution.parts.iter().map(|part| part.span.hi()).max()?; @@ -476,16 +481,12 @@ impl CodeSuggestion { _ => 1, }) .sum(); - 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, - }); - } + + 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 diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr index f823f08f31dca..72aa6303a2026 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr @@ -272,10 +272,8 @@ LL | assert_eq!(a!(), true); | help: replace it with `assert!(..)` | -LL | true -... -LL | -LL ~ assert!(a!()); +LL - assert_eq!(a!(), true); +LL + assert!(a!()); | error: used `assert_eq!` with a literal bool @@ -286,10 +284,8 @@ LL | assert_eq!(true, b!()); | help: replace it with `assert!(..)` | -LL | true -... -LL | -LL ~ assert!(b!()); +LL - assert_eq!(true, b!()); +LL + assert!(b!()); | error: used `debug_assert_eq!` with a literal bool