Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make macro produce determistic output for sealed subclasses #263

Merged
merged 1 commit into from
Apr 26, 2019

Conversation

retronym
Copy link
Contributor

@retronym retronym commented Apr 26, 2019

.decls is documented as having unspecified order. (In practice,
the order reverses when called on previous compiled vs jointly compiled
types)

This commit follow the instructions in .decls ScalaDoc and calls
.sorted.

Here's an example of the non-deterministic output I'm trying to quash.

`.decls` is documented as having unspecified order. (In practice, it
the order reverses when called on previous compiled vs jointly compiled
types)

This commit follow the instructions in `.decls` ScalaDoc and calls
`.sorted`.

Here's an example of the non-deterministic output I'm trying to quash.
@retronym
Copy link
Contributor Author

retronym commented Apr 26, 2019

I've been working to make scalac itself deterministic (meaning: when sources doen't change, generated bytecode is identical from run to run, even when only a subset of sources are recompiled or when the order of source files changes).

I'd like it if the widely used macros in the ecosystem could adhere to the same principles.

Typically this involves:

  • adding .sorted to .decls / .members
  • sorting the result of knownDirectSubclasses
  • avoiding reflecting the iteration order of Hash{Map,Set}-s used in the implementation of macros in the order of generated code, by using Linked versions instead.

/cc @travisbrown @milessabin @raboof @lloydmeta

@retronym
Copy link
Contributor Author

Sharing my answer to Miles about how to write unit test for macro determinism:

You could borrow parts of https://github.com/scala/scala/blob/2.13.x/test/junit/scala/tools/nsc/DeterminismTest.scala, in which I compile a set of source files in different orders/subsets and check bytecode is identical.

I wrote http://github.com/scala/jardiff to automate the process of bytecode decompilation and diffing, which is handy when to diagnose test failures.

@raboof
Copy link
Member

raboof commented Apr 29, 2019

Additionally, if you use sbt you can add https://github.com/raboof/sbt-reproducible-builds to your build. This removes some additional 'accidental nondeterminisms' from the published artifacts, such as timestamps in jars.

Ideally, that would mean 2 builds from the same sources would then produce bit-by-bit identical results, so you can quickly checks for differences by comparing hashes or 'diff'ing. When there's differences you'd dig in with jardiff or diffoscope.

Of course, somewhat like unit tests, this can never prove the absence of problems, only sometimes signal their presence ;).

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.

3 participants