Skip to content

fix: keep std.trace lazy during static optimization#843

Merged
stephenamar-db merged 1 commit into
databricks:masterfrom
He-Pin:fix/trace-static-safety
May 12, 2026
Merged

fix: keep std.trace lazy during static optimization#843
stephenamar-db merged 1 commit into
databricks:masterfrom
He-Pin:fix/trace-static-safety

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented May 12, 2026

Motivation

std.trace has an observable side effect: it writes a trace message and returns the rest value. The static optimizer previously considered it safe to fold, so it could execute traces while optimizing expressions that the Jsonnet runtime never forces.

That caused two correctness problems:

  • unused values such as object fields could emit traces too early;
  • trace output could be reordered compared with official Jsonnet runtime behavior.

Key Design Decision

Mark std.trace as not static-safe. This keeps the existing optimizer behavior for pure builtins while preventing the optimizer from executing this side-effecting builtin.

Modification

  • Override staticSafe = false on the std.trace builtin.
  • Add regression tests proving unused traces inside object fields and format RHS values stay silent.
  • Keep a positive regression test proving directly used std.trace still logs and returns its rest value.
  • Update the upstream trace.jsonnet.golden trace order to match runtime evaluation order.

Benchmark Results

This is a correctness/compatibility PR, not a performance PR. No benchmark change is expected.

Analysis

StaticOptimizer.tryStaticApply can execute static-safe builtins during optimization. That is correct for pure functions, but std.trace is intentionally observable, so executing it before runtime changes program behavior. Disabling static folding for this builtin preserves Jsonnet laziness and official trace ordering without changing the runtime implementation.

References

  • Jsonnet stdlib: std.trace(str, rest) outputs str and returns rest.
  • Local commit: e176c85b fix: keep std.trace lazy during static optimization.

Result

./mill --no-server --ticker false --color false -j 1 __.test passed with 438 tests. Formatting was applied with __.reformat, git diff --check passed, and three independent reviews reported no blockers.

Motivation:
std.trace has an observable side effect, but the static optimizer treated it like a safe builtin and could execute it while folding expressions. That allowed traces from unused object fields or unused format expressions and could reorder trace output compared with official Jsonnet runtime behavior.

Modification:
Mark the std.trace builtin as not static-safe so it is evaluated only when the Jsonnet program forces it at runtime. Add regression tests that unused traces inside objects and format RHS values stay silent while a directly used trace still logs, and update the upstream trace golden to the runtime trace order.

Result:
Full ./mill --no-server --ticker false --color false -j 1 __.test passed with 438 tests. Three independent reviews found no blockers.
@He-Pin He-Pin marked this pull request as ready for review May 12, 2026 05:01
@stephenamar-db stephenamar-db merged commit 0945e7c into databricks:master May 12, 2026
5 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.

2 participants