fix: bind self/$ to outer self in super[name] lookup (#829)#832
Merged
stephenamar-db merged 2 commits intodatabricks:masterfrom May 10, 2026
Merged
fix: bind self/$ to outer self in super[name] lookup (#829)#832stephenamar-db merged 2 commits intodatabricks:masterfrom
stephenamar-db merged 2 commits intodatabricks:masterfrom
Conversation
Motivation:
visitLookupSuper was calling sup.value(key, pos) without passing self,
so the field retrieved through super[name] had its self/$ bound to the
parent object instead of the merged outer self. Fields defined in mixins
applied AFTER the parent therefore became unreachable from inside fields
retrieved via super[name] + override, breaking grafana/mimir's
overrideSuperIfExists helper:
sjsonnet.Error: Field does not exist: ingest_storage_ingester_autoscaling_enabled
at [overrideSuperIfExists].(mimir/rollout-operator.libsonnet:18:64)
at [<root>].(mimir/memberlist.libsonnet:106:50)
Modification:
Pass scope.bindings(e.selfIdx) as the self argument, mirroring the
existing semantics of visitSelectSuper (super.name). Also use it as
the fallback when sup is null.
Result:
super[name] now agrees with super.name; fields retrieved through
computed-key super lookup see $ bound to the outermost merge result,
matching google/jsonnet, go-jsonnet, and jrsonnet. Adds two regression
tests under new_test_suite/: a focused parity/edge-case suite and a
multi-file end-to-end repro of the mimir failure.
References:
- databricks#829
…#829) Motivation: The fix in the previous commit is one line and easy to "clean up" by removing the seemingly redundant `self` argument, which would silently re-introduce issue databricks#829. Modification: Add a DO NOT CHANGE / WHY block in front of visitLookupSuper explaining why `self` must be passed explicitly to `sup.value(...)` and pointing at the cross-implementation contract with super.name. Result: Future readers (humans and AI alike) have an in-source warning explaining the invariant before they touch this method.
stephenamar-db
approved these changes
May 10, 2026
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.
Motivation
Issue #829: sjsonnet failed to evaluate grafana/mimir manifests with
while google/jsonnet (C++), go-jsonnet, and jrsonnet all evaluate it correctly.
Root cause:
visitLookupSuper(computed-keysuper[name]) calledsup.value(key, pos)without passing the actualself, soVal.Obj.valuedefaultedselftosup(the parent in the merge chain). Fields retrieved throughsuper[name]therefore had their$/selfbound to the parent rather than the merged outer self, making_configkeys defined in mixins applied after the parent unreachable. The static-key pathvisitSelectSuper(super.name) was already correct — it passedscope.bindings(e.selfIdx)asself. The two paths must agree.Modification
sjsonnet/src/sjsonnet/Evaluator.scala— makevisitLookupSupermirrorvisitSelectSuperby passing the currentselfexplicitly:Two regression tests under
sjsonnet/test/resources/new_test_suite/(run on JVM, Scala.js and Scala Native viaFileTests):super_lookup_dollar_binding.jsonnet— focused directional suite covering: parity betweensuper.nameandsuper[name]for$binding; theoverrideSuperIfExistspattern verbatim; baresuper[name](no override merge); 3-level chained mixins; computed key from a variable; object-extension syntaxobj { f: super[name] }.super_lookup_mimir_pattern.jsonnet— multi-file end-to-end reproduction of the issue, with three.libsonnetfiles mirroringrollout-operator/memberlist/ingest-storage-ingester-autoscaling. Without the fix, this throws the exact error from the issue.Result
super[name]now agrees withsuper.name; fields retrieved via computed-key super lookup see$bound to the outermost merge result, matching google/jsonnet, go-jsonnet, and jrsonnet. Verified by reverting the one-line fix locally — both regression tests fail with the original "Field does not exist" message and the entry-mimir.jsonnet evaluation in the issue is unblocked.Test plan:
./mill 'sjsonnet.jvm[3.3.7]'.test— 5/5 passing./mill 'sjsonnet.jvm[2.13.18]'.test— 4/4 passing./mill 'sjsonnet.jvm[2.12.21]'.test— 4/4 passing./mill 'sjsonnet.js[3.3.7]'.test— 407/407 passing./mill 'sjsonnet.native[3.3.7]'.test— 428/428 passing./mill __.checkFormat— cleanjsonnet(C++ v0.22.0) on minimal repros and both new test filesReferences
overrideSuperIfExistsdefinition: https://github.com/grafana/mimir/blob/39dd4ffb859d0abb3951d406495bc4bd422600dd/operations/mimir/memberlist.libsonnet#L171