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

Non-deterministic compiler output #3264

Open
memo33 opened this issue Dec 27, 2024 · 3 comments
Open

Non-deterministic compiler output #3264

memo33 opened this issue Dec 27, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@memo33
Copy link

memo33 commented Dec 27, 2024

The scalac compiler generates non-deterministic .class files whenever zio.http.Client is used, possibly caused by izumi-reflect.

To reproduce
Compiling the following code from scratch twice generates class files that are not binary identical.

object ExampleA {
  def createClient: zio.ZLayer[Any, Throwable, zio.http.Client] =
    zio.http.Client.default
      .map(_.update[zio.http.Client](c => c))
}

(tested with Scala 3.4.2, zio-http 3.0.1, zio 2.1.9, izumi-reflect 2.3.9)

Expected behavior
The compiler output should be deterministic.

Additional context
Comparing the class files with javap -v suggests that this is possibly caused by izumi.reflect.Tag producing inconsistent results for ZClient. For example, the following produces different hashcodes after every compiler run, so equality would seem to be broken:

implicitly[izumi.reflect.Tag[zio.http.Client]].hashCode

I'm not sure if the ZClient type falls under one of the known limitations of izumi-reflect or not, so it might also be a bug upstream.

Are there any workarounds to get determinstic output?

@memo33 memo33 added the bug Something isn't working label Dec 27, 2024
@memo33
Copy link
Author

memo33 commented Dec 27, 2024

Here's the diff of running javap -v on two ExampleA$.class files.

   #107 = Utf8               Lizumi/reflect/macrortti/LightTypeTag$;
   #108 = NameAndType        #21:#107      // MODULE$:Lizumi/reflect/macrortti/LightTypeTag$;
   #109 = Fieldref           #106.#108     // izumi/reflect/macrortti/LightTypeTag$.MODULE$:Lizumi/reflect/macrortti/LightTypeTag$;
-  #110 = Integer            -1820475688
-  #111 = Utf8               \u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0000\u0001
-  #112 = String             #111          // \u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0000\u0001
-  #113 = Utf8               \u0000\u0006\u0004\u0000\u0001\rscala.Product\u0001\u0001\u0001\u0004\u0000\u0001\fscala.Equals\u0001\u0001\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0004\u0000\u0001\u0014java.io.Serializable\u0001\u0001\u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0000\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001 zio.http.internal.HeaderModifier\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0002\u0001\u0001\u0001\u0001\u001bzio.http.internal.HeaderOps\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0001\u0001\u0001\u001ezio.http.internal.HeaderChecks\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0000\u0001\u0004\u0000\u0001\u001fzio.http.internal.HeaderGetters\u0001\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u0090\r\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0001\u0001\u0001\u0090\f\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0001\u0001\u0001\u0090\u000b\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0001\u0001\u0090\f\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0003\u0001\u0001\u0001\u0090\r\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0001\u0001\u0090\u000b\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\r\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0000\u0001\u0090\f\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u0006\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\r\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0000\u0001\u0090\f\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001
-  #114 = String             #113          // \u0000\u0006\u0004\u0000\u0001\rscala.Product\u0001\u0001\u0001\u0004\u0000\u0001\fscala.Equals\u0001\u0001\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0004\u0000\u0001\u0014java.io.Serializable\u0001\u0001\u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0000\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001 zio.http.internal.HeaderModifier\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0002\u0001\u0001\u0001\u0001\u001bzio.http.internal.HeaderOps\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0001\u0001\u0001\u001ezio.http.internal.HeaderChecks\u0001\u0000\u0001\u0001\u0001\u0090\u0006\u0005\u0000\u0004\u0000\u0001\u0090\u0007\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\b\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0000\u0001\u0004\u0000\u0001\u001fzio.http.internal.HeaderGetters\u0001\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u0090\r\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0001\u0001\u0001\u0090\f\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0001\u0001\u0001\u0090\u000b\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0001\u0001\u0090\f\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0003\u0001\u0001\u0001\u0090\r\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0001\u0001\u0090\u000b\u0001\u0000\u0004\u0000\u0001\u0090\n\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\t\u0001\u0001\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\r\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0000\u0001\u0090\f\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u0006\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\r\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0000\u0001\u0090\f\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001
+  #110 = Integer            -1039755758
+  #111 = Utf8               \u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0002\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0001\u0001
+  #112 = String             #111          // \u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0002\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0001\u0001
+  #113 = Utf8               \u0000\u0006\u0004\u0000\u0001\rscala.Product\u0001\u0001\u0001\u0004\u0000\u0001\fscala.Equals\u0001\u0001\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0004\u0000\u0001\u0014java.io.Serializable\u0001\u0001\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u001ezio.http.internal.HeaderChecks\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0000\u0001\u0001\u0001\u0001\u001bzio.http.internal.HeaderOps\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0001\u0001\u0001 zio.http.internal.HeaderModifier\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u001fzio.http.internal.HeaderGetters\u0001\u0001\u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0007\u0001\u0001\u0001\u0090\u0007\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u0090\t\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0002\u0001\u0001\u0001\u0001\u0090\b\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0001\u0001\u0001\u0090\b\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0003\u0001\u0001\u0001\u0090\u0007\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0001\u0001\u0001\u0090\t\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u0006\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\u0007\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0000\u0001\u0090\b\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\u0007\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0000\u0001\u0090\b\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001
+  #114 = String             #113          // \u0000\u0006\u0004\u0000\u0001\rscala.Product\u0001\u0001\u0001\u0004\u0000\u0001\fscala.Equals\u0001\u0001\u0004\u0000\u0001\tzio.Scope\u0001\u0001\u0001\u0004\u0000\u0001\u0014java.io.Serializable\u0001\u0001\u0004\u0000\u0001\u0011zio.http.Response\u0001\u0001\u0007\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u001ezio.http.internal.HeaderChecks\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0000\u0001\u0001\u0001\u0001\u001bzio.http.internal.HeaderOps\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0001\u0001\u0001 zio.http.internal.HeaderModifier\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u001fzio.http.internal.HeaderGetters\u0001\u0001\u0001\u0001\u0001\u0010zio.http.ZClient\u0005\u0000\u0004\u0000\u0001\tscala.Any\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\rzio.http.Body\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0013java.lang.Throwable\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0007\u0001\u0001\u0001\u0090\u0007\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\u0002\u0001\u0001\u0004\u0000\u0001\u0090\u0003\u0001\u0001\u0001\u0001\u0001\u0090\t\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0002\u0001\u0001\u0001\u0001\u0090\b\u0001\u0000\u0001\u0001\u0001\u0090\u000b\u0005\u0000\u0004\u0000\u0001\u0090\f\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0002\u0000\u0004\u0000\u0001\u0090\r\u0001\u0001\u0000\u0000\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0001\u0001\u0001\u0090\b\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0003\u0001\u0001\u0001\u0090\u0007\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0000\u0001\u0004\u0000\u0001\u0090\n\u0001\u0001\u0001\u0001\u0001\u0090\t\u0001\u0000\u0004\u0000\u0001\u0090\u0006\u0001\u0001\u0002\u0001\u0004\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0004\u0000\u0001\u0090\u0005\u0001\u0001\u0004\u0000\u0001\u0090\u0004\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u0006\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\u0007\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0000\u0001\u0090\b\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001\u0000\u0001\u0090\u000e\u0001\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\u000b\u0001\u0001\u0007\u0000\u0001\u0090\u0002\u0001\u0001\u0000\u0001\u0090\u0003\u0001\u0001\u0000\u0001\u0090\u0007\u0001\u0001\u0000\u0001\u0090\t\u0001\u0001\u0000\u0001\u0090\b\u0001\u0001\u0000\u0001\u0090\u0005\u0001\u0001\u0000\u0001\u0090\n\u0001\u0001
   #115 = Utf8               parse
   #116 = Utf8               (ILjava/lang/String;Ljava/lang/String;I)Lizumi/reflect/macrortti/LightTypeTag;
   #117 = NameAndType        #115:#116     // parse:(ILjava/lang/String;Ljava/lang/String;I)Lizumi/reflect/macrortti/LightTypeTag;

@kyri-petrou
Copy link
Collaborator

What happens in the case that the implicit Tag[ZClient] is materialized in a val and is imported? Does that produce a deterministic binary output for the class that your method is defined in?

Also, have you tried with the latest version of zio and other Scala 3 versions (3.3.4 and 3.6.2) to check if this is still an issue?

@memo33
Copy link
Author

memo33 commented Jan 6, 2025

First off, the same issue is present when using zio 2.1.14 or Scala 3.3.4 or 3.6.2.

What happens in the case that the implicit Tag[ZClient] is materialized in a val and is imported? Does that produce a deterministic binary output for the class that your method is defined in?

Almost. My actual project is closer to the following example, where the environment consists of an intersection type Foo & zio.http.Client.

class Foo

object ExampleB {

  def createClient: zio.ZLayer[Any, Throwable, zio.http.Client] =
    zio.http.Client.default
      .map(_.update[zio.http.Client](c => c) /* using izumi.reflect.Tag.tagFromTagMacro[zio.http.Client] */ )

  val routes: zio.http.Routes[Foo & zio.http.Client, Nothing] = zio.http.Routes.empty

  val serve =
    zio.http.Server.install(routes) /* using izumi.reflect.Tag.tagFromTagMacro[Foo & zio.http.Client] */
    .provide(
      zio.http.Server.default,
      createClient,
      zio.ZLayer.succeed(Foo()),
    )
}

Using the scalac option -Xprint:typer, I identified the locations where ZClient tags are implicitly created via macro, as indicated in the comments above.

To get a deterministic class file, I've had to replace both macro invocations. The following seems to work (although there might be more elegant ways to accomplish this):

object NondeterministicTags {
  implicit val clientTag: zio.Tag[zio.http.Client] = zio.Tag.materialize[zio.http.Client]
}

class Foo

object ExampleA {
  import NondeterministicTags.*

  def deterministicIntersectionTag[R1, R2](implicit tag1: izumi.reflect.Tag[R1], tag2: izumi.reflect.Tag[R2]): izumi.reflect.Tag[R1 & R2] =
    izumi.reflect.Tag.refinedTag[R1 & R2](
      classOf[Any],
      List(tag1.tag, tag2.tag),
      izumi.reflect.Tag[Nothing].tag,
      Map.empty,
    )

  def createClient: zio.ZLayer[Any, Throwable, zio.http.Client] =
    zio.http.Client.default
      .map(_.update[zio.http.Client](c => c) /* using NondeterministicTags.clientTag instead of macro */ )

  val routes: zio.http.Routes[Foo & zio.http.Client, Nothing] = zio.http.Routes.empty

  val serve =
    zio.http.Server.install(routes)(
      implicitly[zio.Trace],
      deterministicIntersectionTag[Foo, zio.http.Client],  // instead of macro
    )
    .provide(
      zio.http.Server.default,
      createClient,
      zio.ZLayer.succeed(Foo()),
    )

}

The important bits are clientTag and deterministicIntersectionTag[Foo, zio.http.Client]. (Importing the clientTag alone would not be sufficient to replace the 2nd macro invocation.)

Now my project seems to compile deterministically, except for the tiny NondeterministicTags$.class.

Is it possible to import this materialized Tag[zio.http.Client] from zio-http? Or maybe there's a way to make it deterministic as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants