summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-03-03 07:44:52 -0800
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-03-03 07:44:52 -0800
commit34f550aa6152ca3c035881aac53682e4d7b296c7 (patch)
treefa066dd6f136fded1e23c2de4f65a70b71294f4a
parent5a6af8fbc930586da6cc45e2ee27c7715ce840d9 (diff)
parent82000a17010ecbf0dd7d0bfe6393b9fba346c28c (diff)
downloadscala-34f550aa6152ca3c035881aac53682e4d7b296c7.tar.gz
scala-34f550aa6152ca3c035881aac53682e4d7b296c7.tar.bz2
scala-34f550aa6152ca3c035881aac53682e4d7b296c7.zip
Merge pull request #258 from dragos/2.9.x
Fix for cps regression.
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala22
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala14
-rw-r--r--test/files/continuations-neg/t5445.check4
-rw-r--r--test/files/continuations-neg/t5445.scala5
-rw-r--r--test/files/continuations-run/t5538.check1
-rw-r--r--test/files/continuations-run/t5538.scala50
6 files changed, 81 insertions, 15 deletions
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index 98f44a70a0..27c9f9a484 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -346,29 +346,31 @@ abstract class CPSAnnotationChecker extends CPSUtils {
def single(xs: List[AnnotationInfo]) = xs match {
case List(x) => x
case _ =>
- global.globalError("not a single cps annotation: " + xs)// FIXME: error message
+ global.globalError("not a single cps annotation: " + xs)
xs(0)
}
+
+ def emptyOrSingleList(xs: List[AnnotationInfo]) = if (xs.isEmpty) Nil else List(single(xs))
def transChildrenInOrder(tree: Tree, tpe: Type, childTrees: List[Tree], byName: List[Tree]) = {
def inspect(t: Tree): List[AnnotationInfo] = {
if (t.tpe eq null) Nil else {
val extra: List[AnnotationInfo] = t.tpe match {
case _: MethodType | _: PolyType | _: OverloadedType =>
- // method types, poly types and overloaded types do not obtain cps annotions by propagat
- // need to reconstruct transitively from their children.
- t match {
- case Select(qual, name) => inspect(qual)
- case Apply(fun, args) => (fun::args) flatMap inspect
- case TypeApply(fun, args) => (fun::args) flatMap inspect
- case _ => Nil
- }
+ // method types, poly types and overloaded types do not obtain cps annotions by propagation
+ // need to reconstruct transitively from their children.
+ t match {
+ case Select(qual, name) => inspect(qual)
+ case Apply(fun, args) => (fun::(transArgList(fun,args).flatten)) flatMap inspect
+ case TypeApply(fun, args) => (fun::(transArgList(fun,args).flatten)) flatMap inspect
+ case _ => Nil
+ }
case _ => Nil
}
val types = filterAttribs(t.tpe, MarkerCPSTypes)
// TODO: check that it has been adapted and if so correctly
- extra ++ (if (types.isEmpty) Nil else List(single(types)))
+ extra ++ emptyOrSingleList(types)
}
}
val children = childTrees flatMap inspect
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index e2e31a5d37..107f7ad358 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -97,13 +97,17 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
case vd @ ValDef(mods, name, tpt, rhs) => // object-level valdefs
log("transforming valdef " + vd.symbol)
- atOwner(vd.symbol) {
+ if (getExternalAnswerTypeAnn(tpt.tpe).isEmpty) {
+
+ atOwner(vd.symbol) {
- assert(getExternalAnswerTypeAnn(tpt.tpe) == None)
+ val rhs1 = transExpr(rhs, None, None)
- val rhs1 = transExpr(rhs, None, None)
-
- treeCopy.ValDef(vd, mods, name, transform(tpt), rhs1)
+ treeCopy.ValDef(vd, mods, name, transform(tpt), rhs1)
+ }
+ } else {
+ unit.error(tree.pos, "cps annotations not allowed on by-value parameters or value definitions")
+ super.transform(tree)
}
case TypeTree() =>
diff --git a/test/files/continuations-neg/t5445.check b/test/files/continuations-neg/t5445.check
new file mode 100644
index 0000000000..eb2943b6a6
--- /dev/null
+++ b/test/files/continuations-neg/t5445.check
@@ -0,0 +1,4 @@
+t5445.scala:4: error: cps annotations not allowed on by-value parameters or value definitions
+ def foo(block: Unit @suspendable ): Unit @suspendable = {}
+ ^
+one error found
diff --git a/test/files/continuations-neg/t5445.scala b/test/files/continuations-neg/t5445.scala
new file mode 100644
index 0000000000..cb6f8f686d
--- /dev/null
+++ b/test/files/continuations-neg/t5445.scala
@@ -0,0 +1,5 @@
+import scala.util.continuations._
+
+object Test {
+ def foo(block: Unit @suspendable ): Unit @suspendable = {}
+}
diff --git a/test/files/continuations-run/t5538.check b/test/files/continuations-run/t5538.check
new file mode 100644
index 0000000000..457721d5e0
--- /dev/null
+++ b/test/files/continuations-run/t5538.check
@@ -0,0 +1 @@
+Future(Future(Future(Future(Future(List(1, 2, 3, 4, 5))))))
diff --git a/test/files/continuations-run/t5538.scala b/test/files/continuations-run/t5538.scala
new file mode 100644
index 0000000000..42f8163caf
--- /dev/null
+++ b/test/files/continuations-run/t5538.scala
@@ -0,0 +1,50 @@
+import scala.util.continuations._
+import scala.collection.generic.CanBuildFrom
+
+object Test {
+
+ class ExecutionContext
+
+ implicit def defaultExecutionContext = new ExecutionContext
+
+ case class Future[+T](x:T) {
+ final def map[A](f: T => A): Future[A] = new Future[A](f(x))
+ final def flatMap[A](f: T => Future[A]): Future[A] = f(x)
+ }
+
+ class PromiseStream[A] {
+ override def toString = xs.toString
+
+ var xs: List[A] = Nil
+
+ final def +=(elem: A): this.type = { xs :+= elem; this }
+
+ final def ++=(elem: Traversable[A]): this.type = { xs ++= elem; this }
+
+ final def <<(elem: Future[A]): PromiseStream[A] @cps[Future[Any]] =
+ shift { cont: (PromiseStream[A] => Future[Any]) => elem map (a => cont(this += a)) }
+
+ final def <<(elem1: Future[A], elem2: Future[A], elems: Future[A]*): PromiseStream[A] @cps[Future[Any]] =
+ shift { cont: (PromiseStream[A] => Future[Any]) => Future.flow(this << elem1 << elem2 <<< Future.sequence(elems.toSeq)) map cont }
+
+ final def <<<(elems: Traversable[A]): PromiseStream[A] @cps[Future[Any]] =
+ shift { cont: (PromiseStream[A] => Future[Any]) => cont(this ++= elems) }
+
+ final def <<<(elems: Future[Traversable[A]]): PromiseStream[A] @cps[Future[Any]] =
+ shift { cont: (PromiseStream[A] => Future[Any]) => elems map (as => cont(this ++= as)) }
+ }
+
+ object Future {
+
+ def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] =
+ new Future(in.asInstanceOf[Traversable[Future[A]]].map((f:Future[A])=>f.x)(cbf.asInstanceOf[CanBuildFrom[Traversable[Future[A]], A, M[A]]]))
+
+ def flow[A](body: => A @cps[Future[Any]])(implicit executor: ExecutionContext): Future[A] = reset(Future(body)).asInstanceOf[Future[A]]
+
+ }
+
+ def main(args: Array[String]) = {
+ val p = new PromiseStream[Int]
+ println(Future.flow(p << (Future(1), Future(2), Future(3), Future(4), Future(5))))
+ }
+} \ No newline at end of file