scala/scala-async

scala.reflect.internal.annotations.uncheckedBounds in compiler mirror not found

dn-mib opened this issue · 10 comments

We tried to upgrade our project to 0.10.0, but all compilation now fails with

scala.ScalaReflectionException: object scala.reflect.internal.annotations.uncheckedBounds in compiler mirror not found.
    at scala.reflect.internal.Mirrors$RootsBase.staticClass(Mirrors.scala:129)
    at scala.reflect.internal.Mirrors$RootsBase.staticClass(Mirrors.scala:29)
    at scala.async.internal.TransformUtils.scala$async$internal$TransformUtils$$UncheckedBoundsClass(TransformUtils.scala:393)
    at scala.async.internal.TransformUtils.scala$async$internal$TransformUtils$$UncheckedBoundsClass$(TransformUtils.scala:392)
    at scala.async.internal.AsyncMacro$$anon$1.scala$async$internal$TransformUtils$$UncheckedBoundsClass$lzycompute(AsyncMacro.scala:25)
    at scala.async.internal.AsyncMacro$$anon$1.scala$async$internal$TransformUtils$$UncheckedBoundsClass(AsyncMacro.scala:25)
    at scala.async.internal.TransformUtils.uncheckedBounds(TransformUtils.scala:396)
    at scala.async.internal.TransformUtils.uncheckedBounds$(TransformUtils.scala:394)
    at scala.async.internal.AsyncMacro$$anon$1.uncheckedBounds(AsyncMacro.scala:25)
    at scala.async.internal.AsyncTransform.asyncTransform(AsyncTransform.scala:30)
    at scala.async.internal.AsyncTransform.asyncTransform$(AsyncTransform.scala:24)
    at scala.async.internal.AsyncMacro$$anon$1.asyncTransform(AsyncMacro.scala:25)
    at scala.async.internal.AsyncBase.asyncImpl(AsyncBase.scala:56)
    at scala.async.internal.ScalaConcurrentAsync$.asyncImpl(ScalaConcurrentAsync.scala:27)

Scala version is 2.12.8 and sbt 1.2.8.

Minimal example:
https://scastie.scala-lang.org/INyvtq3BSNWPP15W4Si4UQ

build.sbt

scalacOptions ++= Seq(
  "-deprecation",
  "-encoding", "UTF-8",
  "-feature",
  "-unchecked"
)

libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.10.0"

AsyncApp.scala

import scala.async.Async._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object AsyncApp {

  def main(args: Array[String]): Unit = {
    work()
  }

  def work(): Future[String] = async {
    val result: String = await { send() }
    result.toUpperCase
  }

  def send(): Future[String] = {
    Future.successful("ok")
  }
}

thanks for the minimization.

can you confirm that the problem goes away if you add libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided to your build.sbt?

I think the problem will also go away if you use Scala 2.12.8. sbt 1.2.8's default Scala version is 2.12.7.

Hi Seth!
Yes it goes away by adding scala-reflect as a provided dependency. Thanks!

Changing Scala version doesn't help. I have tried
scalaVersion := "2.13.0-RC1", scalaVersion := "2.12.8" and scalaVersion := "2.12.7",
all fails with the error - but all three works by adding
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided

@retronym does this mean that we screwed up the 0.10.0 publishing?

@SethTisue Looks like f8a5b00 removed the try/catch around the the lookup of s.r.internal.annotations.uncheckedBounds. IIRC the intention of that try/catch was to be compatible with Scala 2.10.2 and lower, so the removal made sense. But it turns out that it was also compensating for classpaths that were missing scala-reflect.jar.

What's the solution? We could introduce a dependency on scala-reflect in our POM. The downside is that it will end up on user's runtime classpath unless they override things in their build.

Just adding the try/catch back in isn't a great solution, as it might expose users to bounds errors when refchecks inspects the types of the temporary vals extracted by the ANF transform (these ill-bounded inferred types are not flagged as errors in the types of within chained expressions.)

We could introduce a dependency on scala-reflect in our POM. The downside is that it will end up on user's runtime classpath unless they override things in their build.

can't we declare the dependency as "provided" to prevent that? /cc @eed3si9n

My understanding is that a provided scope dependency is not transitively depended on (even in the "provided" scope) for projects that depend on us. https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope

Right. "provided" assumes that the app will provide the runtime, so it will not transitively add things to Compile configuration.

I guess this is a documentation issue, then. PR with README change welcome

As of scala-async 1.0, scala-reflect will not be needed on the compilation classpath at all. I've simplified the README accordingly in #237.