aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2013-08-14 07:51:10 -0700
committerPhilipp Haller <hallerp@gmail.com>2013-08-14 07:51:10 -0700
commit0c5a1ea043c72bbc3568a8df7f75bc65a261ed21 (patch)
treeb2667b421b7dde7ee8e196f616661baddd307579 /src/test
parent9156cbeb944db80245766c317f43434b4c1981e5 (diff)
parentb79c9ad864a27aea620254c3eade6d38adcf38f2 (diff)
downloadscala-async-0c5a1ea043c72bbc3568a8df7f75bc65a261ed21.tar.gz
scala-async-0c5a1ea043c72bbc3568a8df7f75bc65a261ed21.tar.bz2
scala-async-0c5a1ea043c72bbc3568a8df7f75bc65a261ed21.zip
Merge pull request #27 from retronym/topic/typed-transform-2
Typeful transformations
Diffstat (limited to 'src/test')
-rw-r--r--src/test/scala/scala/async/TreeInterrogation.scala24
-rw-r--r--src/test/scala/scala/async/neg/LocalClasses0Spec.scala124
-rw-r--r--src/test/scala/scala/async/neg/NakedAwait.scala38
-rw-r--r--src/test/scala/scala/async/package.scala17
-rw-r--r--src/test/scala/scala/async/run/anf/AnfTransformSpec.scala97
-rw-r--r--src/test/scala/scala/async/run/hygiene/Hygiene.scala3
-rw-r--r--src/test/scala/scala/async/run/ifelse0/IfElse0.scala1
-rw-r--r--src/test/scala/scala/async/run/ifelse0/WhileSpec.scala3
-rw-r--r--src/test/scala/scala/async/run/match0/Match0.scala35
-rw-r--r--src/test/scala/scala/async/run/nesteddef/NestedDef.scala57
-rw-r--r--src/test/scala/scala/async/run/noawait/NoAwaitSpec.scala1
-rw-r--r--src/test/scala/scala/async/run/toughtype/ToughType.scala71
12 files changed, 315 insertions, 156 deletions
diff --git a/src/test/scala/scala/async/TreeInterrogation.scala b/src/test/scala/scala/async/TreeInterrogation.scala
index deaee03..770c0f9 100644
--- a/src/test/scala/scala/async/TreeInterrogation.scala
+++ b/src/test/scala/scala/async/TreeInterrogation.scala
@@ -7,6 +7,7 @@ package scala.async
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
import AsyncId._
import tools.reflect.ToolBox
@@ -15,9 +16,9 @@ class TreeInterrogation {
@Test
def `a minimal set of vals are lifted to vars`() {
val cm = reflect.runtime.currentMirror
- val tb = mkToolbox("-cp target/scala-2.10/classes")
+ val tb = mkToolbox(s"-cp ${toolboxClasspath}")
val tree = tb.parse(
- """| import _root_.scala.async.AsyncId._
+ """| import _root_.scala.async.internal.AsyncId._
| async {
| val x = await(1)
| val y = x * 2
@@ -40,8 +41,7 @@ class TreeInterrogation {
val varDefs = tree1.collect {
case ValDef(mods, name, _, _) if mods.hasFlag(Flag.MUTABLE) => name
}
- varDefs.map(_.decoded.trim).toSet mustBe (Set("state$async", "await$1", "await$2"))
- varDefs.map(_.decoded.trim).toSet mustBe (Set("state$async", "await$1", "await$2"))
+ varDefs.map(_.decoded.trim).toSet mustBe (Set("state", "await$1$1", "await$2$1"))
val defDefs = tree1.collect {
case t: Template =>
@@ -52,7 +52,7 @@ class TreeInterrogation {
&& !dd.symbol.asTerm.isAccessor && !dd.symbol.asTerm.isSetter => dd.name
}
}.flatten
- defDefs.map(_.decoded.trim).toSet mustBe (Set("foo$1", "apply", "resume$async", "<init>"))
+ defDefs.map(_.decoded.trim).toSet mustBe (Set("foo$1", "apply", "resume", "<init>"))
}
}
@@ -68,17 +68,15 @@ object TreeInterrogation extends App {
withDebug {
val cm = reflect.runtime.currentMirror
- val tb = mkToolbox("-cp target/scala-2.10/classes -Xprint:flatten")
+ val tb = mkToolbox("-cp ${toolboxClasspath} -Xprint:typer -uniqid")
import scala.async.Async._
val tree = tb.parse(
- """ import _root_.scala.async.AsyncId.{async, await}
- | def foo[T](a0: Int)(b0: Int*) = s"a0 = $a0, b0 = ${b0.head}"
- | val res = async {
- | var i = 0
- | def get = async {i += 1; i}
- | foo[Int](await(get))(await(get) :: Nil : _*)
+ """ import _root_.scala.async.internal.AsyncId.{async, await}
+ | import reflect.runtime.universe._
+ | async {
+ | implicit def view(a: Int): String = ""
+ | await(0).length
| }
- | res
| """.stripMargin)
println(tree)
val tree1 = tb.typeCheck(tree.duplicate)
diff --git a/src/test/scala/scala/async/neg/LocalClasses0Spec.scala b/src/test/scala/scala/async/neg/LocalClasses0Spec.scala
index 2569303..6ebc9ca 100644
--- a/src/test/scala/scala/async/neg/LocalClasses0Spec.scala
+++ b/src/test/scala/scala/async/neg/LocalClasses0Spec.scala
@@ -5,121 +5,33 @@
package scala.async
package neg
-/**
- * Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com>
- */
-
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
@RunWith(classOf[JUnit4])
class LocalClasses0Spec {
-
@Test
- def `reject a local class`() {
- expectError("Local case class Person illegal within `async` block") {
- """
- | import scala.concurrent.ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | case class Person(name: String)
- | }
- """.stripMargin
- }
+ def localClassCrashIssue16() {
+ import AsyncId.{async, await}
+ async {
+ class B { def f = 1 }
+ await(new B()).f
+ } mustBe 1
}
@Test
- def `reject a local class 2`() {
- expectError("Local case class Person illegal within `async` block") {
- """
- | import scala.concurrent.{Future, ExecutionContext}
- | import ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | case class Person(name: String)
- | val fut = Future { 5 }
- | val x = await(fut)
- | x
- | }
- """.stripMargin
- }
+ def nestedCaseClassAndModuleAllowed() {
+ import AsyncId.{await, async}
+ async {
+ trait Base { def base = 0}
+ await(0)
+ case class Person(name: String) extends Base
+ val fut = async { "bob" }
+ val x = Person(await(fut))
+ x.base
+ x.name
+ } mustBe "bob"
}
-
- @Test
- def `reject a local class 3`() {
- expectError("Local case class Person illegal within `async` block") {
- """
- | import scala.concurrent.{Future, ExecutionContext}
- | import ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | val fut = Future { 5 }
- | val x = await(fut)
- | case class Person(name: String)
- | x
- | }
- """.stripMargin
- }
- }
-
- @Test
- def `reject a local class with symbols in its name`() {
- expectError("Local case class :: illegal within `async` block") {
- """
- | import scala.concurrent.{Future, ExecutionContext}
- | import ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | val fut = Future { 5 }
- | val x = await(fut)
- | case class ::(name: String)
- | x
- | }
- """.stripMargin
- }
- }
-
- @Test
- def `reject a nested local class`() {
- expectError("Local case class Person illegal within `async` block") {
- """
- | import scala.concurrent.{Future, ExecutionContext}
- | import ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | val fut = Future { 5 }
- | val x = 2 + 2
- | var y = 0
- | if (x > 0) {
- | case class Person(name: String)
- | y = await(fut)
- | } else {
- | y = x
- | }
- | y
- | }
- """.stripMargin
- }
- }
-
- @Test
- def `reject a local singleton object`() {
- expectError("Local object Person illegal within `async` block") {
- """
- | import scala.concurrent.ExecutionContext.Implicits.global
- | import scala.async.Async._
- |
- | async {
- | object Person { val name = "Joe" }
- | }
- """.stripMargin
- }
- }
-
}
diff --git a/src/test/scala/scala/async/neg/NakedAwait.scala b/src/test/scala/scala/async/neg/NakedAwait.scala
index b0d5fde..ba388c5 100644
--- a/src/test/scala/scala/async/neg/NakedAwait.scala
+++ b/src/test/scala/scala/async/neg/NakedAwait.scala
@@ -25,7 +25,7 @@ class NakedAwait {
def `await not allowed in by-name argument`() {
expectError("await must not be used under a by-name argument.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| def foo(a: Int)(b: => Int) = 0
| async { foo(0)(await(0)) }
""".stripMargin
@@ -36,7 +36,7 @@ class NakedAwait {
def `await not allowed in boolean short circuit argument 1`() {
expectError("await must not be used under a by-name argument.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { true && await(false) }
""".stripMargin
}
@@ -46,7 +46,7 @@ class NakedAwait {
def `await not allowed in boolean short circuit argument 2`() {
expectError("await must not be used under a by-name argument.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { true || await(false) }
""".stripMargin
}
@@ -56,7 +56,7 @@ class NakedAwait {
def nestedObject() {
expectError("await must not be used under a nested object.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { object Nested { await(false) } }
""".stripMargin
}
@@ -66,7 +66,7 @@ class NakedAwait {
def nestedTrait() {
expectError("await must not be used under a nested trait.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { trait Nested { await(false) } }
""".stripMargin
}
@@ -76,7 +76,7 @@ class NakedAwait {
def nestedClass() {
expectError("await must not be used under a nested class.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { class Nested { await(false) } }
""".stripMargin
}
@@ -86,7 +86,7 @@ class NakedAwait {
def nestedFunction() {
expectError("await must not be used under a nested function.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { () => { await(false) } }
""".stripMargin
}
@@ -96,7 +96,7 @@ class NakedAwait {
def nestedPatMatFunction() {
expectError("await must not be used under a nested class.") { // TODO more specific error message
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { { case x => { await(false) } } : PartialFunction[Any, Any] }
""".stripMargin
}
@@ -106,7 +106,7 @@ class NakedAwait {
def tryBody() {
expectError("await must not be used under a try/catch.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { try { await(false) } catch { case _ => } }
""".stripMargin
}
@@ -116,7 +116,7 @@ class NakedAwait {
def catchBody() {
expectError("await must not be used under a try/catch.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { try { () } catch { case _ => await(false) } }
""".stripMargin
}
@@ -126,17 +126,27 @@ class NakedAwait {
def finallyBody() {
expectError("await must not be used under a try/catch.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { try { () } finally { await(false) } }
""".stripMargin
}
}
@Test
+ def guard() {
+ expectError("await must not be used under a pattern guard.") {
+ """
+ | import _root_.scala.async.internal.AsyncId._
+ | async { 1 match { case _ if await(true) => } }
+ """.stripMargin
+ }
+ }
+
+ @Test
def nestedMethod() {
expectError("await must not be used under a nested method.") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| async { def foo = await(false) }
""".stripMargin
}
@@ -146,7 +156,7 @@ class NakedAwait {
def returnIllegal() {
expectError("return is illegal") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| def foo(): Any = async { return false }
| ()
|
@@ -158,7 +168,7 @@ class NakedAwait {
def lazyValIllegal() {
expectError("lazy vals are illegal") {
"""
- | import _root_.scala.async.AsyncId._
+ | import _root_.scala.async.internal.AsyncId._
| def foo(): Any = async { val x = { lazy val y = 0; y } }
| ()
|
diff --git a/src/test/scala/scala/async/package.scala b/src/test/scala/scala/async/package.scala
index 4a7a958..7c42024 100644
--- a/src/test/scala/scala/async/package.scala
+++ b/src/test/scala/scala/async/package.scala
@@ -42,7 +42,22 @@ package object async {
m.mkToolBox(options = compileOptions)
}
- def expectError(errorSnippet: String, compileOptions: String = "", baseCompileOptions: String = "-cp target/scala-2.10/classes")(code: String) {
+ def scalaBinaryVersion: String = {
+ val Pattern = """(\d+\.\d+)\..*""".r
+ scala.util.Properties.versionNumberString match {
+ case Pattern(v) => v
+ case _ => ""
+ }
+ }
+
+ def toolboxClasspath = {
+ val f = new java.io.File(s"target/scala-${scalaBinaryVersion}/classes")
+ if (!f.exists) sys.error(s"output directory ${f.getAbsolutePath} does not exist.")
+ f.getAbsolutePath
+ }
+
+ def expectError(errorSnippet: String, compileOptions: String = "",
+ baseCompileOptions: String = s"-cp ${toolboxClasspath}")(code: String) {
intercept[ToolBoxError] {
eval(code, compileOptions + " " + baseCompileOptions)
}.getMessage mustContain errorSnippet
diff --git a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala
index 7be6299..c8cec28 100644
--- a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala
+++ b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala
@@ -13,6 +13,7 @@ import scala.async.Async.{async, await}
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import scala.async.internal.AsyncId
class AnfTestClass {
@@ -114,8 +115,6 @@ class AnfTransformSpec {
@Test
def `inlining block does not produce duplicate definition`() {
- import scala.async.AsyncId
-
AsyncId.async {
val f = 12
val x = AsyncId.await(f)
@@ -132,8 +131,6 @@ class AnfTransformSpec {
@Test
def `inlining block in tail position does not produce duplicate definition`() {
- import scala.async.AsyncId
-
AsyncId.async {
val f = 12
val x = AsyncId.await(f)
@@ -176,7 +173,7 @@ class AnfTransformSpec {
@Test
def nestedAwaitAsBareExpression() {
import ExecutionContext.Implicits.global
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
val result = async {
await(await("").isEmpty)
}
@@ -186,7 +183,7 @@ class AnfTransformSpec {
@Test
def nestedAwaitInBlock() {
import ExecutionContext.Implicits.global
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
val result = async {
()
await(await("").isEmpty)
@@ -197,7 +194,7 @@ class AnfTransformSpec {
@Test
def nestedAwaitInIf() {
import ExecutionContext.Implicits.global
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
val result = async {
if ("".isEmpty)
await(await("").isEmpty)
@@ -208,7 +205,7 @@ class AnfTransformSpec {
@Test
def byNameExpressionsArentLifted() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo(ignored: => Any, b: Int) = b
val result = async {
foo(???, await(1))
@@ -218,7 +215,7 @@ class AnfTransformSpec {
@Test
def evaluationOrderRespected() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo(a: Int, b: Int) = (a, b)
val result = async {
var i = 0
@@ -233,19 +230,19 @@ class AnfTransformSpec {
@Test
def awaitInNonPrimaryParamSection1() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo(a0: Int)(b0: Int) = s"a0 = $a0, b0 = $b0"
val res = async {
var i = 0
def get = {i += 1; i}
- foo(get)(get)
+ foo(get)(await(get))
}
res mustBe "a0 = 1, b0 = 2"
}
@Test
def awaitInNonPrimaryParamSection2() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo[T](a0: Int)(b0: Int*) = s"a0 = $a0, b0 = ${b0.head}"
val res = async {
var i = 0
@@ -257,7 +254,7 @@ class AnfTransformSpec {
@Test
def awaitInNonPrimaryParamSectionWithLazy1() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo[T](a: => Int)(b: Int) = b
val res = async {
def get = async {0}
@@ -268,7 +265,7 @@ class AnfTransformSpec {
@Test
def awaitInNonPrimaryParamSectionWithLazy2() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo[T](a: Int)(b: => Int) = a
val res = async {
def get = async {0}
@@ -279,7 +276,7 @@ class AnfTransformSpec {
@Test
def awaitWithLazy() {
- import _root_.scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo[T](a: Int, b: => Int) = a
val res = async {
def get = async {0}
@@ -290,7 +287,7 @@ class AnfTransformSpec {
@Test
def awaitOkInReciever() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
class Foo { def bar(a: Int)(b: Int) = a + b }
async {
await(async(new Foo)).bar(1)(2)
@@ -299,7 +296,7 @@ class AnfTransformSpec {
@Test
def namedArgumentsRespectEvaluationOrder() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
def foo(a: Int, b: Int) = (a, b)
val result = async {
var i = 0
@@ -314,7 +311,7 @@ class AnfTransformSpec {
@Test
def namedAndDefaultArgumentsRespectEvaluationOrder() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
var i = 0
def next() = {
i += 1;
@@ -332,7 +329,7 @@ class AnfTransformSpec {
@Test
def repeatedParams1() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
var i = 0
def foo(a: Int, b: Int*) = b.toList
def id(i: Int) = i
@@ -343,7 +340,7 @@ class AnfTransformSpec {
@Test
def repeatedParams2() {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
var i = 0
def foo(a: Int, b: Int*) = b.toList
def id(i: Int) = i
@@ -351,4 +348,64 @@ class AnfTransformSpec {
foo(await(0), List(id(1), id(2), id(3)): _*)
} mustBe (List(1, 2, 3))
}
+
+ @Test
+ def awaitInThrow() {
+ import _root_.scala.async.internal.AsyncId.{async, await}
+ intercept[Exception](
+ async {
+ throw new Exception("msg: " + await(0))
+ }
+ ).getMessage mustBe "msg: 0"
+ }
+
+ @Test
+ def awaitInTyped() {
+ import _root_.scala.async.internal.AsyncId.{async, await}
+ async {
+ (("msg: " + await(0)): String).toString
+ } mustBe "msg: 0"
+ }
+
+
+ @Test
+ def awaitInAssign() {
+ import _root_.scala.async.internal.AsyncId.{async, await}
+ async {
+ var x = 0
+ x = await(1)
+ x
+ } mustBe 1
+ }
+
+ @Test
+ def caseBodyMustBeTypedAsUnit() {
+ import _root_.scala.async.internal.AsyncId.{async, await}
+ val Up = 1
+ val Down = 2
+ val sign = async {
+ await(1) match {
+ case Up => 1.0
+ case Down => -1.0
+ }
+ }
+ sign mustBe 1.0
+ }
+
+ @Test
+ def awaitInImplicitApply() {
+ val tb = mkToolbox(s"-cp ${toolboxClasspath}")
+ val tree = tb.typeCheck(tb.parse {
+ """
+ | import language.implicitConversions
+ | import _root_.scala.async.internal.AsyncId.{async, await}
+ | implicit def view(a: Int): String = ""
+ | async {
+ | await(0).length
+ | }
+ """.stripMargin
+ })
+ val applyImplicitView = tree.collect { case x if x.getClass.getName.endsWith("ApplyImplicitView") => x }
+ applyImplicitView.map(_.toString) mustBe List("view(a$1)")
+ }
}
diff --git a/src/test/scala/scala/async/run/hygiene/Hygiene.scala b/src/test/scala/scala/async/run/hygiene/Hygiene.scala
index 9d1df21..8081ee7 100644
--- a/src/test/scala/scala/async/run/hygiene/Hygiene.scala
+++ b/src/test/scala/scala/async/run/hygiene/Hygiene.scala
@@ -9,11 +9,12 @@ package hygiene
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import scala.async.internal.AsyncId
@RunWith(classOf[JUnit4])
class HygieneSpec {
- import scala.async.AsyncId.{async, await}
+ import AsyncId.{async, await}
@Test
def `is hygenic`() {
diff --git a/src/test/scala/scala/async/run/ifelse0/IfElse0.scala b/src/test/scala/scala/async/run/ifelse0/IfElse0.scala
index e2b1ca6..fc438a1 100644
--- a/src/test/scala/scala/async/run/ifelse0/IfElse0.scala
+++ b/src/test/scala/scala/async/run/ifelse0/IfElse0.scala
@@ -13,6 +13,7 @@ import scala.async.Async.{async, await}
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
class TestIfElseClass {
diff --git a/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala b/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala
index 1f1033a..b8d88fb 100644
--- a/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala
+++ b/src/test/scala/scala/async/run/ifelse0/WhileSpec.scala
@@ -9,6 +9,7 @@ package ifelse0
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
@RunWith(classOf[JUnit4])
class WhileSpec {
@@ -64,4 +65,4 @@ class WhileSpec {
}
result mustBe (100)
}
-} \ No newline at end of file
+}
diff --git a/src/test/scala/scala/async/run/match0/Match0.scala b/src/test/scala/scala/async/run/match0/Match0.scala
index 7624838..7c392ab 100644
--- a/src/test/scala/scala/async/run/match0/Match0.scala
+++ b/src/test/scala/scala/async/run/match0/Match0.scala
@@ -13,6 +13,7 @@ import scala.async.Async.{async, await}
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
class TestMatchClass {
@@ -111,4 +112,38 @@ class MatchSpec {
}
result mustBe (3)
}
+
+ @Test def duplicateBindName() {
+ import AsyncId.{async, await}
+ def m4(m: Any) = async {
+ m match {
+ case buf: String =>
+ await(0)
+ case buf: Double =>
+ await(2)
+ }
+ }
+ m4("") mustBe 0
+ }
+
+ @Test def bugCastBoxedUnitToStringMatch() {
+ import scala.async.internal.AsyncId.{async, await}
+ def foo = async {
+ val p2 = await(5)
+ "foo" match {
+ case p3: String =>
+ p2.toString
+ }
+ }
+ foo mustBe "5"
+ }
+
+ @Test def bugCastBoxedUnitToStringIf() {
+ import scala.async.internal.AsyncId.{async, await}
+ def foo = async {
+ val p2 = await(5)
+ if (true) p2.toString else p2.toString
+ }
+ foo mustBe "5"
+ }
}
diff --git a/src/test/scala/scala/async/run/nesteddef/NestedDef.scala b/src/test/scala/scala/async/run/nesteddef/NestedDef.scala
index ee0a78e..409f70a 100644
--- a/src/test/scala/scala/async/run/nesteddef/NestedDef.scala
+++ b/src/test/scala/scala/async/run/nesteddef/NestedDef.scala
@@ -5,6 +5,7 @@ package nesteddef
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.Test
+import scala.async.internal.AsyncId
@RunWith(classOf[JUnit4])
class NestedDef {
@@ -37,4 +38,60 @@ class NestedDef {
}
result mustBe ((0d, 44d, 2))
}
+
+ // We must lift `foo` and `bar` in the next two tests.
+ @Test
+ def nestedDefTransitive1() {
+ import AsyncId._
+ val result = async {
+ val a = 0
+ val x = await(a) - 1
+ def bar = a
+ def foo = bar
+ foo
+ }
+ result mustBe 0
+ }
+
+ @Test
+ def nestedDefTransitive2() {
+ import AsyncId._
+ val result = async {
+ val a = 0
+ val x = await(a) - 1
+ def bar = a
+ def foo = bar
+ 0
+ }
+ result mustBe 0
+ }
+
+
+ // checking that our use/definition analysis doesn't cycle.
+ @Test
+ def mutuallyRecursive1() {
+ import AsyncId._
+ val result = async {
+ val a = 0
+ val x = await(a) - 1
+ def foo: Int = if (true) 0 else bar
+ def bar: Int = if (true) 0 else foo
+ bar
+ }
+ result mustBe 0
+ }
+
+ // checking that our use/definition analysis doesn't cycle.
+ @Test
+ def mutuallyRecursive2() {
+ import AsyncId._
+ val result = async {
+ val a = 0
+ def foo: Int = if (true) 0 else bar
+ def bar: Int = if (true) 0 else foo
+ val x = await(a) - 1
+ bar
+ }
+ result mustBe 0
+ }
}
diff --git a/src/test/scala/scala/async/run/noawait/NoAwaitSpec.scala b/src/test/scala/scala/async/run/noawait/NoAwaitSpec.scala
index e2c69d0..ba9c9be 100644
--- a/src/test/scala/scala/async/run/noawait/NoAwaitSpec.scala
+++ b/src/test/scala/scala/async/run/noawait/NoAwaitSpec.scala
@@ -6,6 +6,7 @@ package scala.async
package run
package noawait
+import scala.async.internal.AsyncId
import AsyncId._
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/src/test/scala/scala/async/run/toughtype/ToughType.scala b/src/test/scala/scala/async/run/toughtype/ToughType.scala
index 83f5a2d..ec2278f 100644
--- a/src/test/scala/scala/async/run/toughtype/ToughType.scala
+++ b/src/test/scala/scala/async/run/toughtype/ToughType.scala
@@ -13,6 +13,7 @@ import scala.async.Async._
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import scala.async.internal.AsyncId
object ToughTypeObject {
@@ -67,4 +68,74 @@ class ToughTypeSpec {
await(f(2))
} mustBe 3
}
+
+ @Test def existentialBindIssue19() {
+ import AsyncId.{await, async}
+ def m7(a: Any) = async {
+ a match {
+ case s: Seq[_] =>
+ val x = s.size
+ var ss = s
+ ss = s
+ await(x)
+ }
+ }
+ m7(Nil) mustBe 0
+ }
+
+ @Test def existentialBind2Issue19() {
+ import scala.async.Async._, scala.concurrent.ExecutionContext.Implicits.global
+ def conjure[T]: T = null.asInstanceOf[T]
+
+ def m3 = async {
+ val p: List[Option[_]] = conjure[List[Option[_]]]
+ await(future(1))
+ }
+
+ def m4 = async {
+ await(future[List[_]](Nil))
+ }
+ }
+
+ @Test def singletonTypeIssue17() {
+ import AsyncId.{async, await}
+ class A { class B }
+ async {
+ val a = new A
+ def foo(b: a.B) = 0
+ await(foo(new a.B))
+ }
+ }
+
+ @Test def existentialMatch() {
+ import AsyncId.{async, await}
+ trait Container[+A]
+ case class ContainerImpl[A](value: A) extends Container[A]
+ def foo: Container[_] = async {
+ val a: Any = List(1)
+ a match {
+ case buf: Seq[_] =>
+ val foo = await(5)
+ val e0 = buf(0)
+ ContainerImpl(e0)
+ }
+ }
+ foo
+ }
+
+ @Test def existentialIfElse0() {
+ import AsyncId.{async, await}
+ trait Container[+A]
+ case class ContainerImpl[A](value: A) extends Container[A]
+ def foo: Container[_] = async {
+ val a: Any = List(1)
+ if (true) {
+ val buf: Seq[_] = List(1)
+ val foo = await(5)
+ val e0 = buf(0)
+ ContainerImpl(e0)
+ } else ???
+ }
+ foo
+ }
}