Open julien-truffaut opened 9 years ago
Yes, both the miniboxing runtime and plugin are required to compile any source code that uses or interacts with miniboxed bytecode. This is quite restrictive, and although there are solutions to it (see #115 for example), they are not yet implemented. In principle, it would be best if one could mark a class as @api
and the plugin would make sure no special features are added to that class, so its users can be compiled with the vanilla scala compiler.
But you raise a very good point. There should be a warning or an error message when using miniboxed code from generic environments. I do not know how to inject that in the compiler as long as I don't have the plugin in there, but maybe I can find something -- I just need to think hard enough about it.
Assigned to milestone 0.5
since it's quite a difficult problem.
ps: sorry for spamming you with issues
Thank you for doing so. How else would the miniboxing plugin become bug-free? :D
During a discussion today with @xeno-by I learned about the @copileTimeOnly
annotation: https://issues.scala-lang.org/browse/SI-6539, which could be used to implement this feature.
Here's a test case:
$ cat gh-bug-185-1.scala
package miniboxing.tests.compile.bug185
class C[@miniboxed T]
$ mb-scalac gh-bug-185-1.scala
$ cat gh-bug-185-2.scala
package miniboxing.tests.compile.bug185
object Test {
def main(args: Array[String]): Unit = {
val c = new C[Int] // unless the miniboxing plugin is attached, this is incorrect bytecode
}
}
$ scalac gh-bug-185-2.scala
$ scala miniboxing.tests.compile.bug185.Test
java.lang.InstantiationError: miniboxing.tests.compile.bug185.C
at miniboxing.tests.compile.bug185.Test$.main(gh-bug-185-2.scala:5)
at miniboxing.tests.compile.bug185.Test.main(gh-bug-185-2.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
The idea is:
scala> import scala.reflect.internal.annotations.compileTimeOnly
import scala.reflect.internal.annotations.compileTimeOnly
scala> @compileTimeOnly("use the miniboxing plugin!") class C
defined class C
scala> new C
<console>:10: error: use the miniboxing plugin!
new C
^
So the solution is simple. Here are the phases in Scala:
$ mb-scalac -Xshow-phases
phase name id description
---------- -- -----------
... .. ...
pickler 11 ... <== this is where signatures are saved
refchecks 12 ... <== this is where compileTimeOnly is checked
... .. ...
So the steps that need to be done in the miniboxing plugin are:
@miniboxed
type params by @compileTimeOnly
before pickling their signatures (before the pickler
phase)@compileTimeOnly
annotation between the pickler
and refchecks
phasesThen, we get this:
@compileTimeOnly
annotation and is rejected by the refchecks
phase (and the "use the miniboxing plugin message gets output")@compileTimeOnly
annotation, but that annotation is removed by the phase injected between pickler
and refchecks
, so the compilation goes through correctly.There are 2 ideas on further developing this:
@compileTimeOnly
annotation to @miniboxed
, @api
and the reflection classes, so they can only be used with the miniboxing plugin activated
I am not sure where is the miniboxing compiler plugin and runtime required, for example, if I annotate a class with miniboxed in module A, I need to add both compiler and runtime for this module. However, if module B has a dependency to module A, does he also need to add miniboxing dependencies? If yes, are the compiler and the runtime required or only one of those.
ps: sorry for spamming you with issues