From 5a0b1918238cb385401f304b22132f51936d795b Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 10 Apr 2013 23:52:31 +0200 Subject: Allow await in applications with multiple argument lists Before, we levied an implementation restriction to prevent this. As it turned out, that needlessly prevented use of `await` in the receiver of a multi-param-list application. This commit lifts the restriction altogether, and treats such applications holistically, being careful to preserve the left-to-right evaluation order of arguments in the translated code. - use `TreeInfo.Applied` and `Type#paramss` from `reflect.internal` to get the info we need - use the parameter name for the lifted argument val, rather than `argN` - encapsulate handling of by-name-ness and parameter names in `mapArgumentss` - test for evaluation order preservation --- .../scala/async/run/anf/AnfTransformSpec.scala | 76 +++++++++++++++++----- 1 file changed, 58 insertions(+), 18 deletions(-) (limited to 'src/test/scala/scala/async/run/anf/AnfTransformSpec.scala') diff --git a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala index 41c13e0..7be6299 100644 --- a/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala +++ b/src/test/scala/scala/async/run/anf/AnfTransformSpec.scala @@ -232,28 +232,68 @@ class AnfTransformSpec { } @Test - def awaitNotAllowedInNonPrimaryParamSection1() { - expectError("implementation restriction: await may only be used in the first parameter list.") { - """ - | import _root_.scala.async.AsyncId.{async, await} - | def foo(primary: Any)(i: Int) = i - | async { - | foo(???)(await(0)) - | } - """.stripMargin + def awaitInNonPrimaryParamSection1() { + import _root_.scala.async.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) + } + res mustBe "a0 = 1, b0 = 2" + } + + @Test + def awaitInNonPrimaryParamSection2() { + 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) :: await(async(Nil)) : _*) + } + res mustBe "a0 = 1, b0 = 2" + } + + @Test + def awaitInNonPrimaryParamSectionWithLazy1() { + import _root_.scala.async.AsyncId.{async, await} + def foo[T](a: => Int)(b: Int) = b + val res = async { + def get = async {0} + foo[Int](???)(await(get)) } + res mustBe 0 } @Test - def awaitNotAllowedInNonPrimaryParamSection2() { - expectError("implementation restriction: await may only be used in the first parameter list.") { - """ - | import _root_.scala.async.AsyncId.{async, await} - | def foo[T](primary: Any)(i: Int) = i - | async { - | foo[Int](???)(await(0)) - | } - """.stripMargin + def awaitInNonPrimaryParamSectionWithLazy2() { + import _root_.scala.async.AsyncId.{async, await} + def foo[T](a: Int)(b: => Int) = a + val res = async { + def get = async {0} + foo[Int](await(get))(???) + } + res mustBe 0 + } + + @Test + def awaitWithLazy() { + import _root_.scala.async.AsyncId.{async, await} + def foo[T](a: Int, b: => Int) = a + val res = async { + def get = async {0} + foo[Int](await(get), ???) + } + res mustBe 0 + } + + @Test + def awaitOkInReciever() { + import scala.async.AsyncId.{async, await} + class Foo { def bar(a: Int)(b: Int) = a + b } + async { + await(async(new Foo)).bar(1)(2) } } -- cgit v1.2.3