aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-07-29 19:22:00 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-07-29 19:22:00 +1000
commit6d44255964092b672accd7784ddc712d30f1d7c4 (patch)
tree32ba363fcd1416582bf1ebae01837ff4082b33d4 /src
parentde641dc265f34b06e17dfa7c64be00219f72b670 (diff)
downloadscala-async-6d44255964092b672accd7784ddc712d30f1d7c4.tar.gz
scala-async-6d44255964092b672accd7784ddc712d30f1d7c4.tar.bz2
scala-async-6d44255964092b672accd7784ddc712d30f1d7c4.zip
Avoid dead code warnings in generated code.
If we blindly splicing `{..$stats, ..$generatedCode}`, and the last expression in `$stats` is of type `Nothing`, we'll incur a dead code warning when typechecking the block. This commit: - introduces a helper method to augment user-written stats with synthetic code - Emit a try/finally in that code (so we advance the state, even if we are about to exit the state machine in the async-block global exception handler - Hide `Nothing` typed expressions from the dead code analysis by wrapping them in an `expr: Any` Fixes #150 (the part reported in the comments, not the original ticket.)
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/scala/async/internal/ExprBuilder.scala7
-rw-r--r--src/test/scala/scala/async/package.scala26
-rw-r--r--src/test/scala/scala/async/run/WarningsSpec.scala29
3 files changed, 58 insertions, 4 deletions
diff --git a/src/main/scala/scala/async/internal/ExprBuilder.scala b/src/main/scala/scala/async/internal/ExprBuilder.scala
index f24e37e..164e85b 100644
--- a/src/main/scala/scala/async/internal/ExprBuilder.scala
+++ b/src/main/scala/scala/async/internal/ExprBuilder.scala
@@ -35,7 +35,12 @@ trait ExprBuilder {
var stats: List[Tree]
def statsAnd(trees: List[Tree]): List[Tree] = {
- val body = adaptToUnit(stats)
+ val body = stats match {
+ case init :+ last if tpeOf(last) =:= definitions.NothingTpe =>
+ adaptToUnit(init :+ Typed(last, TypeTree(definitions.AnyTpe)))
+ case _ =>
+ adaptToUnit(stats)
+ }
Try(body, Nil, adaptToUnit(trees)) :: Nil
}
diff --git a/src/test/scala/scala/async/package.scala b/src/test/scala/scala/async/package.scala
index 166edaa..8f23a8c 100644
--- a/src/test/scala/scala/async/package.scala
+++ b/src/test/scala/scala/async/package.scala
@@ -51,6 +51,32 @@ package object async {
m.mkToolBox(options = compileOptions)
}
+ import scala.tools.nsc._, reporters._
+ def mkGlobal(compileOptions: String = ""): Global = {
+ val source = """
+ | class Test {
+ | def test = {
+ | import scala.async.Async._, scala.concurrent._, ExecutionContext.Implicits.global
+ | async {
+ | val opt = await(async(Option.empty[String => Future[Unit]]))
+ | opt match {
+ | case None =>
+ | throw new RuntimeException("case a")
+ | case Some(f) =>
+ | await(f("case b"))
+ | }
+ | }
+ | }
+ | }
+ | """.stripMargin
+ val settings = new Settings()
+ settings.processArgumentString(compileOptions)
+ settings.usejavacp.value = true
+ settings.embeddedDefaults(getClass.getClassLoader)
+ val reporter = new StoreReporter
+ new Global(settings, reporter)
+ }
+
def scalaBinaryVersion: String = {
val PreReleasePattern = """.*-(M|RC).*""".r
val Pattern = """(\d+\.\d+)\..*""".r
diff --git a/src/test/scala/scala/async/run/WarningsSpec.scala b/src/test/scala/scala/async/run/WarningsSpec.scala
index 3a7843a..f0b414a 100644
--- a/src/test/scala/scala/async/run/WarningsSpec.scala
+++ b/src/test/scala/scala/async/run/WarningsSpec.scala
@@ -7,10 +7,8 @@ package run
import org.junit.Test
-import scala.async.internal.AsyncId
-import scala.concurrent.Await
-import scala.concurrent.duration._
import scala.language.{postfixOps, reflectiveCalls}
+import scala.tools.nsc.reporters.StoreReporter
class WarningsSpec {
@@ -32,4 +30,29 @@ class WarningsSpec {
""".stripMargin
})
}
+
+ @Test
+ def noDeadCodeWarning() {
+ val global = mkGlobal("-cp ${toolboxClasspath} -Yrangepos -Ywarn-dead-code -Xfatal-warnings")
+ val source = """
+ | class Test {
+ | def test = {
+ | import scala.async.Async._, scala.concurrent._, ExecutionContext.Implicits.global
+ | async {
+ | val opt = await(async(Option.empty[String => Future[Unit]]))
+ | opt match {
+ | case None =>
+ | throw new RuntimeException("case a")
+ | case Some(f) =>
+ | await(f("case b"))
+ | }
+ | }
+ | }
+ |}
+ """.stripMargin
+ val run = new global.Run
+ val sourceFile = global.newSourceFile(source)
+ run.compileSources(sourceFile :: Nil)
+ assert(!global.reporter.hasErrors, global.reporter.asInstanceOf[StoreReporter].infos)
+ }
}