Skip to content

bytescomparestring: diagnostic message hardcodes "string(...)" and misrepresents named-type conversions #53579

Description

@github-actions

Summary

bytescomparestring (pkg/linters/bytescomparestring/bytescomparestring.go) flags string(a) == string(b) / != comparisons where a/b are []byte, and suggests bytes.Equal(a, b). The type-match logic in extractByteSliceStringConv (lines 219-250) accepts any conversion whose result type's Underlying() is *types.Basic with Kind() == types.String — not just the exact predeclared string type. That includes named string types, e.g. type Password string.

The diagnostic message, however, hardcodes the literal text "string(...)" regardless of what conversion the source actually used:

Message: fmt.Sprintf("string(%s) == string(%s) is a []byte comparison written the long way; use bytes.Equal(%s, %s) for clearer intent", lText, rText, lText, rText),

So code like:

type Password string
if Password(a) == Password(b) { ... }

produces the misleading diagnostic: string(a) == string(b) is a []byte comparison written the long way; use bytes.Equal(a, b) for clearer intent — even though the source never wrote string(...) at all.

This is the same bug class already confirmed and fixed for a sibling linter in #52826 (stringbytesroundtrip: "redundant-round-trip message hardcodes 'string(...)'/'[]byte(...)' and ignores named-type assignability"), but bytescomparestring was not covered by that fix and has no test for this case.

Note: the SuggestedFix itself (bytes.Equal(a, b)) remains semantically correct and compiles fine here — only the human-facing diagnostic message text is wrong. This is a message-accuracy bug, not a compile-correctness bug (contrast with #aw_sg60a1/writebytestring, which was a compile bug).

Evidence

  • pkg/linters/bytescomparestring/bytescomparestring.go:238-241 — matches on Underlying(), not exact identity:
    basic, ok := resultInfo.Type.Underlying().(*types.Basic)
    if !ok || basic.Kind() != types.String {
    	return nil, false
    }
  • pkg/linters/bytescomparestring/bytescomparestring.go:93,104 — message hardcodes "string(%s)" literally rather than using the actual conversion's type name.
  • Confirmed via pkg/linters/bytescomparestring/testdata/src/bytescomparestring/: existing golden fixtures (bytescomparestring.go, aliased_import.go, noimport.go, shadow.go, singleimport.go) contain no named-string-type conversion case, so this gap is untested.

Impact

Low-medium. Purely a message-quality bug (misleading lint text pointing at code that doesn't exist verbatim in the file), which can confuse a developer trying to locate the flagged expression, especially in an editor/CI annotation that quotes the message. No compile or autofix-correctness risk.

Recommendation

Reuse the actual conversion type name in the message instead of the hardcoded literal, e.g. render the type's String() (or fall back to "string" only when the type is the exact predeclared string) so the message quotes what the source really wrote. Add a testdata case with a named string type on one or both sides to lock in the fix, mirroring the approach used to close #52826.

Validation checklist

  • Message text reflects the actual source conversion (named type name, not hardcoded "string")
  • New testdata/golden case for type X string; X(a) == X(b) where a, b are []byte
  • Confirm SuggestedFix output is unaffected (still emits bytes.Equal(a, b))
  • go test ./pkg/linters/bytescomparestring/... passes

Effort

Small — message string construction change + one testdata fixture pair.

Generated by 🤖 Sergo - Serena Go Expert · agent · 165 AIC · ⌖ 4.99 AIC · ⊞ 6.3K ·

  • expires on Aug 24, 2026, 8:10 PM UTC-08:00

Metadata

Metadata

Labels

cookieIssue Monster Loves Cookies!sergo

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions