emmalanguage/emma

[IR] Autogenerated TypeTags for classes in package objects cause runtime errors

ggevay opened this issue · 17 comments

If I have a call like this

DataBag(imdb)

where the type of imdb is org.emmalanguage.codegen.ImdbMovie and it is in a package object, then the toolbox can't parse this code after showCode.
If we supply the generic argument explicitly, then it works:

DataBag[org.emmalanguage.codegen.ImdbMovie](imdb)

The difference between the output of showCode in the two cases is that the latter has ``package. before `ImdbMovie`.

I can't reproduce this. E.g. all of these compile fine:

  import scala.reflect.runtime.universe._
  import scala.reflect.runtime.currentMirror
  import scala.tools.reflect.ToolBox

  val tb = currentMirror.mkToolBox()

  tb.compile(tb.parse("org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.ImdbMovie](Nil)"))
  tb.compile(tb.parse("org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.`package`.ImdbMovie](Nil)"))
  tb.compile(q"org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.ImdbMovie](Nil)")
  tb.compile(q"org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.`package`.ImdbMovie](Nil)")
  tb.compile(reify(org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.ImdbMovie](Nil)).tree)
  tb.compile(reify(org.emmalanguage.api.DataBag[eu.stratosphere.emma.codegen.`package`.ImdbMovie](Nil)).tree)

Otherwise, the missing _root_ can be added by showCode(_, printRootPkg = true).

The problem happens only when you don't supply the generic argument, and typecheck infers it.

But doesn't showCode produce one of the strings from the first two lines above?

maybe it is again some "magic" happening in the ToolBox internal state?

@ggevay @joroKr21 BTW I am wondering whether we cannot serialize / deserialize the Scala ASTs using some different method (e.g., toolbox.show). Maybe this will solve the issue.

show or toString usually don't parse back as valid code.

@joroKr21

I can't reproduce this.

I can't reproduce it outside of BaseCodegenTest either. But here is a commit just for future reference that shows the problem there:
8612256

But I guess we can postpone fixing this, because it works if the type is not in the package object.

@joroKr21 @ggevay maybe this was fixed by ad50db6.

I can't verify this (neither the bug, nor the fix).

The problem seems to be still present. Here is a commit which is based on the current newir, and the change in it is to move ImdbMovie into a package object: ggevay@8c9aada Several tests are failing in BaseCodegenTest. (Different ones are failing with Flink and Spark.)

Wait what, so the code compiled in the ToolBox, but failed at runtime with ClassNotFound?
scala.ScalaReflectionException: class org.emmalanguage.test.schema.ImdbMovie in JavaMirror...
Something weird is going on here.

Yes...

It always happens when trying to create a TypeTag. Also this fails:

tb.typecheck(tb.parse(showCode(tb.typecheck(q"""
  import scala.reflect.runtime.universe.TypeTag
  implicitly[TypeTag[String]]
"""))))

But now I'm confused: Then what difference does it make whether the type is in a package object or not?

I have no idea. It's just that the whole TypeTag story is really weird.

This looks like another ToolBox issue. Say we move ImdbMovie in package object schema as described above. Then adding this line anywhere in BaseCodegenIntegrationSpec fixes the issue:

tb.typecheck(u.reify(ImdbMovie).tree)

Also, making examples.graphs.model a package object causes no problems for the macro-based compiler.

I suggest to enable -Xlint and -Xfatal-warnings in the build which will cause an error for classes defined in package objects and close this issue as wontfix. Note that you can still define all classes in the same file by simply omitting object:

package schema {
  case class ImdbMovie(...)
  // other case classes
}

-Xlint:package-object-classes enabled in with #306