Skip to content

fix: reject function equality comparisons with clear error#966

Closed
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:fix/function-equality-error
Closed

fix: reject function equality comparisons with clear error#966
He-Pin wants to merge 1 commit into
databricks:masterfrom
He-Pin:fix/function-equality-error

Conversation

@He-Pin

@He-Pin He-Pin commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Motivation

Jsonnet semantics dictate that functions cannot be compared for equality. sjsonnet silently returned false for f == g (two functions), diverging from go-jsonnet, C++ jsonnet, and jrsonnet which all raise runtime errors. This silent divergence masked bugs where users accidentally compared functions instead of their return values.

Modification

  • Evaluator.scala: Add Val.Func checks in equal() for object field comparison (lazy-evaluated fields), array element comparison, and top-level scalar comparison
  • Raise Error.fail("cannot test equality of functions") when both operands are Val.Func instances
  • Handle asymmetric cases (func == non-func) by returning false after checking the non-func operand

Result

function(x) x == function(x) x now raises sjsonnet.Error: cannot test equality of functions, matching go-jsonnet, C++ jsonnet, and jrsonnet behavior.

Implementation Result Error message
go-jsonnet v0.22.0 Error RUNTIME ERROR: Cannot test equality of functions
C++ jsonnet Error RUNTIME ERROR: cannot test equality of functions
jrsonnet v0.5.0-pre99 Error runtime error: cannot test equality of functions
sjsonnet (before) Silent false (no error, returns false)
sjsonnet (after) Error sjsonnet.Error: cannot test equality of functions

Test plan

  • function(x) x == function(x) x raises error
  • function(x) x != function(x) x raises error
  • Function equality in arrays: [f] == [g] raises error
  • Function equality in objects: {a: f} == {a: g} raises error
  • Non-function comparisons unchanged: 1 == 2, "a" == "b", etc.
  • All existing tests pass

Motivation:
Jsonnet semantics dictate that functions cannot be compared for equality.
sjsonnet silently returned false for `f == g` (two functions), diverging
from go-jsonnet, C++ jsonnet, and jrsonnet which all raise runtime errors.
This silent divergence masked bugs where users accidentally compared
functions instead of their return values.

Modification:
- Evaluator.scala: Add Val.Func checks in `equal()` for object field
  comparison, array element comparison, and top-level comparison
- Raise Error.fail("cannot test equality of functions") when both operands
  are Val.Func instances
- Handle asymmetric cases (func == non-func) by returning false after
  checking the non-func operand

Result:
`function(x) x == function(x) x` now raises:
  sjsonnet.Error: cannot test equality of functions
matching go-jsonnet, C++ jsonnet, and jrsonnet behavior. Prevents silent
false results that mask comparison bugs.

References:
- go-jsonnet: "RUNTIME ERROR: Cannot test equality of functions"
- C++ jsonnet: "RUNTIME ERROR: cannot test equality of functions"
- jrsonnet: "runtime error: cannot test equality of functions"
@He-Pin

He-Pin commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Closing: PR #959 has identical Evaluator.scala changes plus comprehensive test coverage (3 test files). This PR is a strict subset — keeping #959 instead to avoid duplicate work.

@He-Pin He-Pin closed this Jun 18, 2026
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.

1 participant