Repository navigation
Fix complex encoding emitting 1+-0i for a negative-zero imaginary part - #1598
Open
januththedev wants to merge 1 commit into
Open
januththedev wants to merge 1 commit into
januththedev wants to merge 1 commit into
Conversation
Author
Ok i have signed in |
januththedev
force-pushed
the
fix/complex-negative-zero
branch
from
October 3, 2026 04:14
074492d to
913b4e5
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.
Complex encoding emits
1+-0ifor a negative-zero imaginary partDescription
(*jsonEncoder).appendComplexchooses the sign of the imaginary part withif i >= 0, against the invariant stated in its own comment — "If imaginary part is less than 0, minus (-) sign is added by default by AppendFloat."IEEE-754 makes
-0.0 >= 0true, butstrconvstill renders negative zero as-0. So for a negative-zero imaginary part the code prepends'+'andAppendFloatemits-0, producing two sign characters.Why it's wrong
The encoder's contract — already asserted by the pre-existing table case
"complex128/negative_i" -> "1-2i"— is<real><sign><imag>i. The output is"1+-0i", a malformed complex literal. It affectsAddComplex128/AddComplex64onObjectEncoderandAppendComplex128/AppendComplex64onArrayEncoder, i.e. every JSON- or console-encoded complex field and everyComplex128s/Complex64sarray.It is reachable from ordinary code: any arithmetic that underflows to
-0yieldscomplex(a, -0.0)— e.g.x * -1wherex == 0.The fix
math.Signbitdistinguishes-0from+0, which a comparison cannot.Tests
Four new table entries:
complex128/negative_zero_iandcomplex64/negative_zero_i, in bothTestJSONEncoderObjectFieldsandTestJSONEncoderArrays, e.g.:{"complex128/negative_zero_i", `"k":"1-0i"`, func(e Encoder) { e.AddComplex128("k", complex(1, math.Copysign(0, -1))) }},expected: "\"k\":\"1-0i\"" actual: "\"k\":\"1+-0i\"". After: pass.go test -count=1 ./... -v: 824 PASS, 14 FAIL — the identical set of 14 that fails on unmodified HEAD, all Windows-environment artifacts (URL parsing offile://localhostC:\..., and aTempDircleanup blocked by an open handle). The sorted--- FAILdiff before vs after is identical apart from timing digits, so there are zero regressions and 4 net-new passing subtests.go vet ./zapcore/clean.gofmt -lflags the two files, but the same two HEAD files are flagged identically (CRLF checkout vs LF) — pre-existing, not introduced here.This HEAD is upstream master's tip, so the defect is unfixed there. Searching open issues for
complex,negative zero, andAppendComplexreturns zero results, and no open PR touchesappendComplex(nearest are #1553 NaN/Inf→null and #1588AppendNumber).I also checked and did not report:
LevelEncoder.UnmarshalTextdocs"colored"but matches"color"(a doc bug, not code);TrimmedPathdropping/v2for major-version modules (open PR #1559); andzapgrpc'sV()sending unknown levels toInfoLevel(issue #1544, PRs #1583/#1546). Several other candidates —Field.Equalspanicking on uncomparableStringer,encodeStringeremittingPANIC=for a nil Stringer, missing nil guards inEncodeCaller/EncodeTime, and themultiWriteSyncershort-write accounting — all have open PRs (#1569, #1555, #1566, #1584, #1590) and are out of scope.Note this repository requires a CLA signature before merging; that is the contributor's action, not something the change can address.