Skip to content

Commit 168e10c

Browse files
committed
Small cleanups after code review
- More internal docs - Be more frugal with the `NoAwait` attachment, for some AST node types this is implied. - Just use `x`, rather than what was effectively `x.reverseMap(identity).reverse`
1 parent e3ff038 commit 168e10c

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

src/main/scala/scala/async/internal/AnfTransform.scala

+11-3
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ private[async] trait AnfTransform {
220220

221221
case Block(stats, expr) =>
222222
val trees = stats.flatMap(linearize.transformToList).filterNot(isLiteralUnit) ::: linearize.transformToList(expr)
223-
eliminateLabelParameters(trees)
223+
eliminateMatchEndLabelParameter(trees)
224224

225225
case ValDef(mods, name, tpt, rhs) =>
226226
if (containsAwait(rhs)) {
@@ -273,7 +273,15 @@ private[async] trait AnfTransform {
273273
}
274274

275275
// Replace the label parameters on `matchEnd` with use of a `matchRes` temporary variable
276-
def eliminateLabelParameters(statsExpr: List[Tree]): List[Tree] = {
276+
//
277+
// CaseDefs are translated to labels without parmeters. A terminal label, `matchEnd`, accepts
278+
// a parameter which is the result of the match (this is regular, so even Unit-typed matches have this).
279+
//
280+
// For our purposes, it is easier to:
281+
// - extract a `matchRes` variable
282+
// - rewrite the terminal label def to take no parameters, and instead read this temp variable
283+
// - change jumps to the terminal label to an assignment and a no-arg label application
284+
def eliminateMatchEndLabelParameter(statsExpr: List[Tree]): List[Tree] = {
277285
import internal.{methodType, setInfo}
278286
val caseDefToMatchResult = collection.mutable.Map[Symbol, Symbol]()
279287

@@ -304,7 +312,7 @@ private[async] trait AnfTransform {
304312
)
305313
}
306314
matchResults.toList match {
307-
case Nil => statsExpr0.reverse
315+
case Nil => statsExpr
308316
case r1 :: Nil => (r1 +: statsExpr0.reverse) :+ atPos(tree.pos)(gen.mkAttributedIdent(r1.symbol))
309317
case _ => c.error(macroPos, "Internal error: unexpected tree encountered during ANF transform " + statsExpr); statsExpr
310318
}

src/main/scala/scala/async/internal/AsyncTransform.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,11 @@ trait AsyncTransform {
9898
}
9999

100100
val isSimple = asyncBlock.asyncStates.size == 1
101-
if (isSimple)
101+
val result = if (isSimple)
102102
futureSystemOps.spawn(body, execContext) // generate lean code for the simple case of `async { 1 + 1 }`
103103
else
104104
startStateMachine
105+
cleanupContainsAwaitAttachments(result)
105106
}
106107

107108
def logDiagnostics(anfTree: Tree, states: Seq[String]) {

src/main/scala/scala/async/internal/TransformUtils.scala

+27-8
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,18 @@ private[async] trait TransformUtils {
396396
* in search of a sub tree that was decorated with the cached answer.
397397
*/
398398
final def containsAwaitCached(t: Tree): Tree => Boolean = {
399+
def treeCannotContainAwait(t: Tree) = t match {
400+
case _: Ident | _: TypeTree | _: Literal => true
401+
case _ => false
402+
}
403+
def shouldAttach(t: Tree) = !treeCannotContainAwait(t)
399404
val symtab = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable]
400-
def attachContainsAwait(t: Tree): Unit = {
405+
def attachContainsAwait(t: Tree): Unit = if (shouldAttach(t)) {
401406
val t1 = t.asInstanceOf[symtab.Tree]
402407
t1.updateAttachment(ContainsAwait)
403408
t1.removeAttachment[NoAwait.type]
404409
}
405-
def attachNoAwait(t: Tree): Unit = {
410+
def attachNoAwait(t: Tree): Unit = if (shouldAttach(t)) {
406411
val t1 = t.asInstanceOf[symtab.Tree]
407412
t1.updateAttachment(NoAwait)
408413
}
@@ -423,22 +428,36 @@ private[async] trait TransformUtils {
423428
markContainsAwaitTraverser.traverse(t)
424429

425430
(t: Tree) => {
426-
val symtab = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable]
427431
object traverser extends Traverser {
428432
var containsAwait = false
429433
override def traverse(tree: Tree): Unit = {
430-
if (tree.asInstanceOf[symtab.Tree].hasAttachment[NoAwait.type])
431-
()
432-
else if (tree.asInstanceOf[symtab.Tree].hasAttachment[ContainsAwait.type])
433-
containsAwait = true
434-
else super.traverse(tree)
434+
def castTree = tree.asInstanceOf[symtab.Tree]
435+
if (!castTree.hasAttachment[NoAwait.type]) {
436+
if (castTree.hasAttachment[ContainsAwait.type])
437+
containsAwait = true
438+
else if (!treeCannotContainAwait(t))
439+
super.traverse(tree)
440+
}
435441
}
436442
}
437443
traverser.traverse(t)
438444
traverser.containsAwait
439445
}
440446
}
441447

448+
final def cleanupContainsAwaitAttachments(t: Tree): t.type = {
449+
val symtab = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable]
450+
t.foreach {t =>
451+
t.asInstanceOf[symtab.Tree].removeAttachment[ContainsAwait.type]
452+
t.asInstanceOf[symtab.Tree].removeAttachment[NoAwait.type]
453+
}
454+
t
455+
}
456+
457+
// First modification to translated patterns:
458+
// - Set the type of label jumps to `Unit`
459+
// - Propagate this change to trees known to directly enclose them:
460+
// ``If` / `Block`) adjust types of enclosing
442461
final def adjustTypeOfTranslatedPatternMatches(t: Tree, owner: Symbol): Tree = {
443462
import definitions.UnitTpe
444463
typingTransform(t, owner) {

0 commit comments

Comments
 (0)