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

-coverage-out generates unlinkable code on Scala.js #15383

Open
armanbilge opened this issue Jun 6, 2022 · 3 comments
Open

-coverage-out generates unlinkable code on Scala.js #15383

armanbilge opened this issue Jun 6, 2022 · 3 comments
Labels
area:coverage Code coverage, see https://dotty.epfl.ch/docs/internals/coverage.html area:scala.js area:scala.native itype:enhancement

Comments

@armanbilge
Copy link
Contributor

Compiler version

3.2.0-RC1-bin-20220604-13ce496-NIGHTLY

Minimized code

//> using scala "3.2.0-RC1-bin-20220604-13ce496-NIGHTLY"
//> using platform "js"
//> using option "-coverage-out:."

@main def main = ()

Output

Referring to non-existent class java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.write(java.lang.String)void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.write(int)void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.flush()void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.FileWriter
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.flush()void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.write(int)void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method java.io.FileWriter.write(java.lang.String)void
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.FileWriter
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.File
  called from scala.runtime.coverage.Invoker$.measurementFile(java.lang.String)java.io.File
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.File
  called from scala.runtime.coverage.Invoker$.measurementFile(java.lang.String)java.io.File
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.File
  called from scala.runtime.coverage.Invoker$.measurementFile(java.lang.String)java.io.File
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method constructor java.io.File.<init>(java.lang.String,java.lang.String)void
  called from scala.runtime.coverage.Invoker$.measurementFile(java.lang.String)java.io.File
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.FileWriter
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent method constructor java.io.FileWriter.<init>(java.io.File,boolean)void
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.io.File
  called from private scala.runtime.coverage.Invoker$.$anonfun$2(java.lang.String)java.io.FileWriter
  called from scala.runtime.coverage.Invoker$.invoked(int,java.lang.String)void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  scala.runtime.coverage.Invoker$
  coverage$package$
Referring to non-existent class java.security.SecureRandom
  called from private java.util.UUID$.csprng$lzycompute()java.util.Random
  called from private java.util.UUID$.csprng()java.util.Random
  called from java.util.UUID$.randomUUID()java.util.UUID
  called from static java.util.UUID.randomUUID()java.util.UUID
  called from constructor scala.runtime.coverage.Invoker$.<init>()void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  java.util.UUID$
  coverage$package$
Referring to non-existent class java.security.SecureRandom
  called from private java.util.UUID$.csprng$lzycompute()java.util.Random
  called from private java.util.UUID$.csprng()java.util.Random
  called from java.util.UUID$.randomUUID()java.util.UUID
  called from static java.util.UUID.randomUUID()java.util.UUID
  called from constructor scala.runtime.coverage.Invoker$.<init>()void
  called from coverage$package$.main()void
  called from static main.main([java.lang.String)void
  called from core module module initializers
involving instantiated classes:
  java.util.UUID$
  coverage$package$
Not showing 179 more linking errors
Exception in thread "main" org.scalajs.linker.interface.LinkingException: There were linking errors
        at org.scalajs.linker.frontend.BaseLinker.reportErrors$1(BaseLinker.scala:91)
        at org.scalajs.linker.frontend.BaseLinker.$anonfun$analyze$5(BaseLinker.scala:100)
        at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:467)
        at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
        at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
        at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
        at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:597)
        at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:194)
[error]  Error linking Scala.js

Expectation

Scoverage for Scala 2 is supported on Scala.js, so it should be on Scala 3 as well.

This is complicated by two things:

  1. The use of UUID. See:
  2. Varying APIs for filesystem access in JavaScript runtimes. See:

Either these changes need to be ported to Dotty, or I wonder if a better solution might be to shell out to the Scala 2 runtime with for3Use2_13.

/cc @ckipp01 @TheElectronWill

@armanbilge armanbilge added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jun 6, 2022
@TheElectronWill TheElectronWill added area:coverage Code coverage, see https://dotty.epfl.ch/docs/internals/coverage.html area:scala.js itype:enhancement and removed itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Jun 6, 2022
@armanbilge
Copy link
Contributor Author

armanbilge commented Sep 29, 2022

Note that this is a problem for Scala Native as well, but even more complicated because unlike Scala.js, Scala Native does not live in this repository.

I still think the best solution is to shell out to the existing, Scala 2 runtime. AFAICT the sources for the JVM runtime in this repo has already been copied from there, it's essentially identical.

The JS runtimes are complicated to test (think: Node.js, JSDOM browser emulators, installing stuff from npm, etc. etc.) and properly supporting them would bring undue maintenance burden to this repository.

Adding a Native runtime in this repository is effectively impossible.

Hence why I think sharing the existing Scala 2 runtime is the ideal way forward.

@TheElectronWill
Copy link
Contributor

TheElectronWill commented Sep 29, 2022

I agree. It would be great to remove this partial runtime from Dotty and reuse the one in scalac-coverage-plugin. The runtime to use could be passed as a parameter to the compiler, with a sensible default to scoverage.{Invoker, Platform} :)

Also, it could be a good opportunity to improve the interface of this runtime, so that the instrumented code is smaller and more performant.

@TheElectronWill
Copy link
Contributor

But first, I'll fix some instrumentation bugs like #15771 ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:coverage Code coverage, see https://dotty.epfl.ch/docs/internals/coverage.html area:scala.js area:scala.native itype:enhancement
Projects
None yet
Development

No branches or pull requests

2 participants