scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.83k stars 1.05k forks source link

SIP-47 Clause Interleaving + Java = `bad class file` error #21346

Open SethTisue opened 1 month ago

SethTisue commented 1 month ago

Discussed in https://github.com/scala/scala3/discussions/21195

Originally posted by **xuwei-k** July 15, 2024 Is this expected behavior? or we should/can fix this error? 🤔 `A.scala` ```scala package example class A { def f[B](b: B)[C](c: C): (B, C) = (b, c) } ``` `build.sbt` ```scala scalaVersion := "3.6.0-RC1-bin-20240712-97a711c-NIGHTLY" ``` `X.java` ```java package j; import example.A; class X { A a = new A(); } ``` `sbt compile` ``` [error] example-project-dir/X.java:3:1: cannot access example.A [error] bad class file: example-project-dir/target/scala-3.6.0-RC1-bin-20240712-97a711c-NIGHTLY/classes/example/A.class [error] undeclared type variable: C [error] Please remove or make sure it appears in the correct subdirectory of the classpath. ``` `javap -v A.class` ``` public scala.Tuple2 f(B); descriptor: (Ljava/lang/Object;Ljava/lang/Object;)Lscala/Tuple2; ``` `getGenericParameterTypes` and `getGenericReturnType` ``` Welcome to Scala 3.6.0-RC1-bin-20240712-97a711c-NIGHTLY-git-97a711c (11.0.23, Java OpenJDK 64-Bit Server VM). Type in expressions for evaluation. Or try :help. scala> val f = classOf[example.A].getMethods.find(_.getName == "f").get val f: java.lang.reflect.Method = public scala.Tuple2 example.A.f(java.lang.Object,java.lang.Object) scala> f.getGenericParameterTypes val res0: Array[java.lang.reflect.Type] = Array(B) scala> f.getGenericReturnType java.lang.NullPointerException at java.base/sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.toString(ParameterizedTypeImpl.java:229) at scala.runtime.ScalaRunTime$.inner$1(ScalaRunTime.scala:258) at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:263) at scala.runtime.ScalaRunTime.stringOf(ScalaRunTime.scala) at jdk.internal.reflect.GeneratedMethodAccessor5.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at dotty.tools.repl.Rendering.poorStringOf$1$$anonfun$1(Rendering.scala:64) at dotty.tools.repl.Rendering.poorStringOf$1$$anonfun$adapted$1(Rendering.scala:64) at dotty.tools.repl.Rendering.stringOfMaybeTruncated$1(Rendering.scala:68) at dotty.tools.repl.Rendering.classLoader$$anonfun$1(Rendering.scala:77) at dotty.tools.repl.Rendering.classLoader$$anonfun$adapted$1(Rendering.scala:76) at dotty.tools.repl.Rendering.replStringOf(Rendering.scala:105) at dotty.tools.repl.Rendering.valueOf$$anonfun$2(Rendering.scala:123) at scala.Option.map(Option.scala:242) at dotty.tools.repl.Rendering.valueOf(Rendering.scala:123) at dotty.tools.repl.Rendering.renderVal(Rendering.scala:160) at dotty.tools.repl.ReplDriver.$anonfun$7(ReplDriver.scala:402) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15) at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10) at scala.collection.immutable.List.foreach(List.scala:334) at dotty.tools.repl.ReplDriver.extractAndFormatMembers$1(ReplDriver.scala:402) at dotty.tools.repl.ReplDriver.renderDefinitions$$anonfun$2(ReplDriver.scala:440) at scala.Option.map(Option.scala:242) at dotty.tools.repl.ReplDriver.renderDefinitions(ReplDriver.scala:439) at dotty.tools.repl.ReplDriver.compile$$anonfun$2(ReplDriver.scala:342) at scala.util.Either.fold(Either.scala:197) at dotty.tools.repl.ReplDriver.compile(ReplDriver.scala:324) at dotty.tools.repl.ReplDriver.interpret(ReplDriver.scala:283) at dotty.tools.repl.ReplDriver.loop$1(ReplDriver.scala:196) at dotty.tools.repl.ReplDriver.runUntilQuit$$anonfun$1(ReplDriver.scala:199) at dotty.tools.repl.ReplDriver.withRedirectedOutput(ReplDriver.scala:238) at dotty.tools.repl.ReplDriver.runBody$$anonfun$1(ReplDriver.scala:212) at dotty.tools.runner.ScalaClassLoader$.asContext(ScalaClassLoader.scala:80) at dotty.tools.repl.ReplDriver.runBody(ReplDriver.scala:212) at dotty.tools.repl.ReplDriver.runUntilQuit(ReplDriver.scala:199) at xsbt.ConsoleInterface.run(ConsoleInterface.java:52) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at sbt.internal.inc.AnalyzingCompiler.invoke(AnalyzingCompiler.scala:329) at sbt.internal.inc.AnalyzingCompiler.console(AnalyzingCompiler.scala:233) at sbt.Console.console0$1(Console.scala:65) at sbt.Console.$anonfun$apply$5(Console.scala:75) at sbt.Run$.executeSuccess(Run.scala:187) at sbt.Console.$anonfun$apply$4(Console.scala:75) at sbt.internal.util.Terminal.withRawInput(Terminal.scala:146) at sbt.internal.util.Terminal.withRawInput$(Terminal.scala:144) at sbt.internal.util.Terminal$ProxyTerminal$.withRawInput(Terminal.scala:424) at sbt.Console.$anonfun$apply$3(Console.scala:75) at sbt.internal.util.Terminal$TerminalImpl.withRawOutput(Terminal.scala:1028) at sbt.internal.util.Terminal$ProxyTerminal$.withRawOutput(Terminal.scala:463) at sbt.Console.apply(Console.scala:72) at sbt.Console.apply(Console.scala:50) at sbt.Console.apply(Console.scala:42) at sbt.Defaults$.$anonfun$consoleTask$1(Defaults.scala:2287) at sbt.Defaults$.$anonfun$consoleTask$1$adapted(Defaults.scala:2273) at scala.Function1.$anonfun$compose$1(Function1.scala:49) at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63) at sbt.std.Transform$$anon$4.work(Transform.scala:69) at sbt.Execute.$anonfun$submit$2(Execute.scala:283) at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24) at sbt.Execute.work(Execute.scala:292) at sbt.Execute.$anonfun$submit$1(Execute.scala:283) at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265) at sbt.CompletionService$$anon$2.call(CompletionService.scala:65) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:829) ```
SethTisue commented 1 month ago

at https://github.com/scala/scala3/pull/20861#issuecomment-2272655737 , @sjrd wrote:

I don't think [this is a blocker for SIP-47]. It only affects new code combined with Java code. It cannot break anyone immediately. We should fix it, though, for sure, but not a blocker IMO.