cmp: apply cleanupSurroundingIdentical's prepend/append after the loop instead of in defer - #406
Open
januththedev wants to merge 2 commits into
Open
januththedev wants to merge 2 commits into
januththedev wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
januththedev
force-pushed
the
fix/cleanup-surrounding-identical
branch
from
October 3, 2026 04:13
68c87b5 to
68ca6ea
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
cleanupSurroundingIdentical: twodeferclosures mutate a local, but the result is unnamedThe defect
cleanupSurroundingIdenticalusesdeferto prepend and append groups after the loop, per its own comments:The function has an unnamed result:
With an unnamed result,
return groupsassigns the result parameter before the deferred functions run. Both closures therefore reassign the localgroupsafter its value has already been copied to the return slot, and the mutation is silently discarded.The Go semantics, in isolation:
The second
deferhas the same problem.FormatValueinreport_reflect.go:114uses a named result (out textNode) for the same idiom, which confirms the intended pattern was a named result that someone later removed.Reachability — stated honestly
I could not reach either branch through the public
cmp.DiffAPI. I instrumented both branches and ran the full suite, roughly 3M randomized string pairs (small alphabets, random edits, forced shared prefixes and suffixes), and an exhaustive sweep of shared-prefix × short-tail combinations. Zero hits.I was also able to prove the leading branch unreachable: if
x[0] == y[0], the forward diff search matches at(0,0)on its first probe and emitsIdentity, so group 0 is always equal; and any unequal group 0 hasnx == 0orny == 0, which blocks the check. The trailing branch would need a sub-optimal diff leaving an unexamined misaligned equal pair at the end — possible in principle, butconnectchecks equality first on every probed pair.So this is a latent defect: provably dead code that contradicts its own comments, not a demonstrated user-visible failure. If either branch ever became reachable, the consequence would be a dropped report element followed by
formatDiffSlicefailing to consumevx/vyfully and trippingassert(vx.Len() == 0 && vy.Len() == 0)atreport_slices.go:434— acmp.Diffpanic on valid input.The change
Apply the prepend and append after the loop explicitly, rather than relying on
deferplus an unnamed result:I chose this over switching to a named result because the two
defers execute LIFO: with a single-group list where both branches fire, the append would run first and then the prepend would wrap it, so the trailing identical span would end up in the middle of the result. Applying both after the loop keeps prepend-then-append ordering correct by construction.If you would rather just delete the two dead branches, that is equally defensible and probably the smaller change — the function's contract is then simply "never emits leading or trailing identical groups". I did not take that route because the surrounding code and comments clearly intend to handle these cases, and deleting them would silently drop the behaviour if a future diff change makes the path reachable. Happy to switch to deletion if you prefer it.
Tests
cmp/report_slices_test.go(new,package cmp, matching the existing internal-test convention) covers four cases: a leading identical span with no preceding group, a trailing one with no succeeding group, both edges of a single unequal group, and a control where a middle group correctly folds into its neighbours.cleanupSurroundingIdentical([1 removed byte], eq) = [1 removed byte], want [1 identical byte 1 removed byte]; the control already passed. After: all four pass.go test -count=1 ./...→ all packagesok, 0 failures.gofmt -l cmp/clean.I checked the 41 open issues and 22 open PRs: nothing covers this. I deliberately avoided the neighbouring
sliceSorter.checkSortoff-by-one (#402),EquateComparablenil deref (#401), andAllowUnexportednil guard (#405), which are already open.Note that this repository requires a CLA; the signature is not something I can do on your behalf.