diff options
author | Philipp Haller <hallerp@gmail.com> | 2013-08-14 07:51:10 -0700 |
---|---|---|
committer | Philipp Haller <hallerp@gmail.com> | 2013-08-14 07:51:10 -0700 |
commit | 0c5a1ea043c72bbc3568a8df7f75bc65a261ed21 (patch) | |
tree | b2667b421b7dde7ee8e196f616661baddd307579 /src/test | |
parent | 9156cbeb944db80245766c317f43434b4c1981e5 (diff) | |
parent | b79c9ad864a27aea620254c3eade6d38adcf38f2 (diff) | |
download | scala-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')
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 + } } |