diff options
Diffstat (limited to 'src/main/scala/scala/async/internal/TransformUtils.scala')
-rw-r--r-- | src/main/scala/scala/async/internal/TransformUtils.scala | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/src/main/scala/scala/async/internal/TransformUtils.scala b/src/main/scala/scala/async/internal/TransformUtils.scala index 90419d3..c86540b 100644 --- a/src/main/scala/scala/async/internal/TransformUtils.scala +++ b/src/main/scala/scala/async/internal/TransformUtils.scala @@ -24,6 +24,7 @@ private[async] trait TransformUtils { val ifRes = "ifres" val await = "await" val bindSuffix = "$bind" + val completed = newTermName("completed") val state = newTermName("state") val result = newTermName("result") @@ -38,6 +39,9 @@ private[async] trait TransformUtils { def fresh(name: String): String = c.freshName(name) } + def isAsync(fun: Tree) = + fun.symbol == defn.Async_async + def isAwait(fun: Tree) = fun.symbol == defn.Async_await @@ -164,7 +168,8 @@ private[async] trait TransformUtils { val NonFatalClass = rootMirror.staticModule("scala.util.control.NonFatal") val ThrowableClass = rootMirror.staticClass("java.lang.Throwable") - val Async_await = asyncBase.awaitMethod(c.universe)(c.macroApplication.symbol).ensuring(_ != NoSymbol) + lazy val Async_async = asyncBase.asyncMethod(c.universe)(c.macroApplication.symbol) + lazy val Async_await = asyncBase.awaitMethod(c.universe)(c.macroApplication.symbol) val IllegalStateExceptionClass = rootMirror.staticClass("java.lang.IllegalStateException") } @@ -186,6 +191,10 @@ private[async] trait TransformUtils { val LABEL = 1L << 17 // not in the public reflection API. (internal.flags(sym).asInstanceOf[Long] & LABEL) != 0L } + def isSynth(sym: Symbol): Boolean = { + val SYNTHETIC = 1 << 21 // not in the public reflection API. + (internal.flags(sym).asInstanceOf[Long] & SYNTHETIC) != 0L + } def symId(sym: Symbol): Int = { val symtab = this.c.universe.asInstanceOf[reflect.internal.SymbolTable] sym.asInstanceOf[symtab.Symbol].id @@ -281,6 +290,8 @@ private[async] trait TransformUtils { override def traverse(tree: Tree) { tree match { + case _ if isAsync(tree) => + // Under -Ymacro-expand:discard, used in the IDE, nested async blocks will be visible to the outer blocks case cd: ClassDef => nestedClass(cd) case md: ModuleDef => nestedModule(md) case dd: DefDef => nestedMethod(dd) @@ -382,7 +393,7 @@ private[async] trait TransformUtils { catch { case _: ScalaReflectionException => NoSymbol } } final def uncheckedBounds(tp: Type): Type = { - if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp + if ((tp.typeArgs.isEmpty && (tp match { case _: TypeRef => true; case _ => false}))|| UncheckedBoundsClass == NoSymbol) tp else withAnnotation(tp, Annotation(UncheckedBoundsClass.asType.toType, Nil, ListMap())) } // ===================================== @@ -396,9 +407,11 @@ private[async] trait TransformUtils { * in search of a sub tree that was decorated with the cached answer. */ final def containsAwaitCached(t: Tree): Tree => Boolean = { + if (c.macroApplication.symbol == null) return (t => false) + def treeCannotContainAwait(t: Tree) = t match { case _: Ident | _: TypeTree | _: Literal => true - case _ => false + case _ => isAsync(t) } def shouldAttach(t: Tree) = !treeCannotContainAwait(t) val symtab = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable] @@ -417,11 +430,15 @@ private[async] trait TransformUtils { override def traverse(tree: Tree): Unit = { stack ::= tree try { - if (isAwait(tree)) - stack.foreach(attachContainsAwait) - else - attachNoAwait(tree) - super.traverse(tree) + if (isAsync(tree)) { + ; + } else { + if (isAwait(tree)) + stack.foreach(attachContainsAwait) + else + attachNoAwait(tree) + super.traverse(tree) + } } finally stack = stack.tail } } @@ -463,6 +480,14 @@ private[async] trait TransformUtils { typingTransform(t, owner) { (tree, api) => tree match { + case LabelDef(name, params, rhs) => + val rhs1 = api.recur(rhs) + if (rhs1.tpe =:= UnitTpe) { + internal.setInfo(tree.symbol, internal.methodType(tree.symbol.info.paramLists.head, UnitTpe)) + treeCopy.LabelDef(tree, name, params, rhs1) + } else { + treeCopy.LabelDef(tree, name, params, rhs1) + } case Block(stats, expr) => val stats1 = stats map api.recur val expr1 = api.recur(expr) |