From ad96d40fa1a123d8d6efd672f1c7c7248c3bc3cf Mon Sep 17 00:00:00 2001 From: "GPT 5.4" Date: Mon, 23 Mar 2026 10:59:42 +0800 Subject: [PATCH 1/2] Bound common-line pruning to the local window Fix should_prune_common_line() so the backward scan starts at pos.saturating_sub(WINDOW_SIZE) instead of the absolute WINDOW_SIZE index. The old bound made the scanned range grow with pos, which turned the preprocessing heuristic into an increasingly expensive rescan on highly repetitive inputs and caused the gix-merge clusterfuzz testcase to time out. Add a regression test that proves distant context outside the local window does not affect the pruning decision. Co-authored-by: Sebastian Thiel --- src/myers/preprocess.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/myers/preprocess.rs b/src/myers/preprocess.rs index 9985c2a..af2bf6e 100644 --- a/src/myers/preprocess.rs +++ b/src/myers/preprocess.rs @@ -135,7 +135,7 @@ fn should_prune_common_line(token_status: &[Occurrences], pos: usize) -> bool { let mut unmatched_before = 0; let mut common_before = 0; - let start = if pos > WINDOW_SIZE { WINDOW_SIZE } else { 0 }; + let start = pos.saturating_sub(WINDOW_SIZE); for status in token_status[start..pos].iter().rev() { match status { Occurrences::None => { @@ -176,3 +176,23 @@ fn should_prune_common_line(token_status: &[Occurrences], pos: usize) -> bool { unmatched > 3 * common } + +#[cfg(test)] +mod tests { + use super::{should_prune_common_line, Occurrences}; + + #[test] + fn common_line_pruning_ignores_distant_context() { + let mut token_status = vec![Occurrences::Some; 700]; + token_status[100..400].fill(Occurrences::None); + token_status[400..450].fill(Occurrences::None); + token_status[450..500].fill(Occurrences::Common); + token_status[500..550].fill(Occurrences::Common); + token_status[550..600].fill(Occurrences::None); + + assert!( + !should_prune_common_line(&token_status, 500), + "only the last 100 items before the current line should contribute to the backward scan" + ); + } +} From d2930d174bd4469f4932b4658f4fa505e8e0b655 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 23 Mar 2026 11:55:44 +0800 Subject: [PATCH 2/2] thanks clippy --- src/myers/slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/myers/slice.rs b/src/myers/slice.rs index fce3e97..526b615 100644 --- a/src/myers/slice.rs +++ b/src/myers/slice.rs @@ -27,7 +27,7 @@ impl<'a> FileSlice<'a> { } } - pub fn borrow(&'_ mut self) -> FileSlice<'_> { + pub fn borrow(&mut self) -> FileSlice<'_> { FileSlice { tokens: self.tokens, changed: self.changed,