Skip to content

fix: flip equality comparisons in place instead of calling a generic helper - #45

Merged
fchimpan merged 1 commit into
mainfrom
fix/mixed-type-equality
Aug 25, 2026
Merged

fix: flip equality comparisons in place instead of calling a generic helper#45
fchimpan merged 1 commit into
mainfrom
fix/mixed-type-equality

Conversation

@fchimpan

Copy link
Copy Markdown
Owner

Go permits x == y between operands of different static types when one is
assignable to the other (e.g. any == error, io.Writer == *os.File, or two
interface types where one embeds the other). The generated generic helper
_mutest_eq_N[T comparable](a, b T) cannot unify such operands into a single
type parameter, so type inference failed and the whole package aborted at
the build stage with zero results (issue #39).

Since the equality mutation is exactly a negation, rewrite the site as

(x == y) != _mutest_on(N)

where _mutest_on reports whether mutant N is active. The original
comparison stays in place, evaluated once, so its typing and semantics
cannot drift:

  • mixed static types need no inference (fixes Instrumentation build fails for legal mixed-type equality comparisons (e.g. any == error) #39)
  • comparison results stay untyped bool, so defined-bool-type contexts
    (type Flag bool; return a == b) now build too, where the old helper's
    typed bool aborted the package the same way
  • recover() in an operand keeps working: unlike the inline closure
    previously used for nil comparisons, the operand is not moved into a
    nested function literal, where recover() no longer stops a panic
  • operand text is emitted once, so nested equality grows linearly

This replaces both the _mutest_eq_N helper and the nil-comparison inline
closure. Ordered comparisons keep the generic cmp.Ordered helper: their
mutations are not negations. instrumentFile now also fails loudly if a
mutation point matches no AST node instead of silently reporting a no-op
mutant as SURVIVED.

Fixes #39

…helper

Go permits x == y between operands of different static types when one is
assignable to the other (e.g. any == error, io.Writer == *os.File, or two
interface types where one embeds the other). The generated generic helper
_mutest_eq_N[T comparable](a, b T) cannot unify such operands into a single
type parameter, so type inference failed and the whole package aborted at
the build stage with zero results (issue #39).

Since the equality mutation is exactly a negation, rewrite the site as

    (x == y) != _mutest_on(N)

where _mutest_on reports whether mutant N is active. The original
comparison stays in place, evaluated once, so its typing and semantics
cannot drift:

- mixed static types need no inference (fixes #39)
- comparison results stay untyped bool, so defined-bool-type contexts
  (type Flag bool; return a == b) now build too, where the old helper's
  typed bool aborted the package the same way
- recover() in an operand keeps working: unlike the inline closure
  previously used for nil comparisons, the operand is not moved into a
  nested function literal, where recover() no longer stops a panic
- operand text is emitted once, so nested equality grows linearly

This replaces both the _mutest_eq_N helper and the nil-comparison inline
closure. Ordered comparisons keep the generic cmp.Ordered helper: their
mutations are not negations. instrumentFile now also fails loudly if a
mutation point matches no AST node instead of silently reporting a no-op
mutant as SURVIVED.

Fixes #39
@fchimpan
fchimpan merged commit 6bf5daa into main Aug 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Instrumentation build fails for legal mixed-type equality comparisons (e.g. any == error)

1 participant