Skip to content

Commit dc3fd62

Browse files
committed
[backport] Cleanup code generation by avoiding redundant blocks
Don't bother adding `{ ...; () }` if we can use the original tree(s) instead, e.g. if the last tree in `...` conforms to `Unit`. This makes the debug output of the macro a little easier to read. (cherry picked from commit de641dc)
1 parent ad6c3c0 commit dc3fd62

File tree

2 files changed

+45
-19
lines changed

2 files changed

+45
-19
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ trait AsyncTransform {
6868
for ((state, flds) <- assignsOf) {
6969
val assigns = flds.map { fld =>
7070
val fieldSym = fld.symbol
71-
Block(
72-
List(
73-
asyncBase.nullOut(global)(Expr[String](Literal(Constant(fieldSym.name.toString))), Expr[Any](Ident(fieldSym))).tree
74-
),
75-
Assign(gen.mkAttributedStableRef(fieldSym.owner.thisType, fieldSym), mkZero(fieldSym.info))
76-
)
71+
val assign = Assign(gen.mkAttributedStableRef(fieldSym.owner.thisType, fieldSym), mkZero(fieldSym.info))
72+
asyncBase.nullOut(global)(Expr[String](Literal(Constant(fieldSym.name.toString))), Expr[Any](Ident(fieldSym))).tree
73+
match {
74+
case Literal(Constant(value: Unit)) => assign
75+
case x => Block(x :: Nil, assign)
76+
}
7777
}
7878
val asyncState = asyncBlock.asyncStates.find(_.state == state).get
7979
asyncState.stats = assigns ++ asyncState.stats

src/main/scala/scala/async/internal/ExprBuilder.scala

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ trait ExprBuilder {
3333

3434
var stats: List[Tree]
3535

36+
def statsAnd(trees: List[Tree]): List[Tree] = {
37+
val body = adaptToUnit(stats)
38+
Try(body, Nil, adaptToUnit(trees)) :: Nil
39+
}
40+
3641
final def allStats: List[Tree] = this match {
37-
case a: AsyncStateWithAwait => stats :+ a.awaitable.resultValDef
42+
case a: AsyncStateWithAwait => statsAnd(a.awaitable.resultValDef :: Nil)
3843
case _ => stats
3944
}
4045

@@ -51,8 +56,9 @@ trait ExprBuilder {
5156
def nextStates: List[Int] =
5257
List(nextState)
5358

54-
def mkHandlerCaseForState[T: WeakTypeTag]: CaseDef =
55-
mkHandlerCase(state, stats :+ mkStateTree(nextState, symLookup))
59+
def mkHandlerCaseForState[T: WeakTypeTag]: CaseDef = {
60+
mkHandlerCase(state, statsAnd(mkStateTree(nextState, symLookup) :: Nil))
61+
}
5662

5763
override val toString: String =
5864
s"AsyncState #$state, next = $nextState"
@@ -86,10 +92,10 @@ trait ExprBuilder {
8692
val tryGetOrCallOnComplete =
8793
if (futureSystemOps.continueCompletedFutureOnSameThread)
8894
If(futureSystemOps.isCompleted(Expr[futureSystem.Fut[_]](awaitable.expr)).tree,
89-
Block(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil, literalUnit),
90-
Block(callOnComplete :: Nil, Return(literalUnit)))
95+
adaptToUnit(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil),
96+
Block(toList(callOnComplete), Return(literalUnit)))
9197
else
92-
Block(callOnComplete :: Nil, Return(literalUnit))
98+
Block(toList(callOnComplete), Return(literalUnit))
9399
mkHandlerCase(state, stats ++ List(mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
94100
}
95101

@@ -109,11 +115,11 @@ trait ExprBuilder {
109115
*/
110116
def ifIsFailureTree[T: WeakTypeTag](tryReference: => Tree) =
111117
If(futureSystemOps.tryyIsFailure(Expr[futureSystem.Tryy[T]](tryReference)).tree,
112-
Block(futureSystemOps.completeProm[T](
118+
Block(toList(futureSystemOps.completeProm[T](
113119
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)),
114120
Expr[futureSystem.Tryy[T]](
115121
TypeApply(Select(tryReference, newTermName("asInstanceOf")),
116-
List(TypeTree(futureSystemOps.tryType[T]))))).tree :: Nil,
122+
List(TypeTree(futureSystemOps.tryType[T]))))).tree),
117123
Return(literalUnit)),
118124
Block(List(tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
119125
)
@@ -381,12 +387,12 @@ trait ExprBuilder {
381387
val t = Expr[Throwable](Ident(name.t))
382388
val complete = futureSystemOps.completeProm[T](
383389
Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T](t)).tree
384-
Block(complete :: Nil, Return(literalUnit))
390+
Block(toList(complete), Return(literalUnit))
385391
})), EmptyTree)
386392

387393
def forever(t: Tree): Tree = {
388394
val labelName = name.fresh("while$")
389-
LabelDef(labelName, Nil, Block(t :: Nil, Apply(Ident(labelName), Nil)))
395+
LabelDef(labelName, Nil, Block(toList(t), Apply(Ident(labelName), Nil)))
390396
}
391397

392398
/**
@@ -404,7 +410,7 @@ trait ExprBuilder {
404410
def onCompleteHandler[T: WeakTypeTag]: Tree = {
405411
val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T]).toList
406412
forever {
407-
Block(resumeFunTree :: Nil, literalUnit)
413+
adaptToUnit(toList(resumeFunTree))
408414
}
409415
}
410416
}
@@ -421,12 +427,32 @@ trait ExprBuilder {
421427
Assign(symLookup.memberRef(name.state), Literal(Constant(nextState)))
422428

423429
private def mkHandlerCase(num: Int, rhs: List[Tree]): CaseDef =
424-
mkHandlerCase(num, Block(rhs, literalUnit))
430+
mkHandlerCase(num, adaptToUnit(rhs))
431+
432+
private def tpeOf(t: Tree): Type = t match {
433+
case _ if t.tpe != null => t.tpe
434+
case Try(body, Nil, _) => tpeOf(body)
435+
case _ => NoType
436+
}
437+
438+
private def adaptToUnit(rhs: List[Tree]): Block = {
439+
rhs match {
440+
case init :+ last if tpeOf(last) <:< definitions.UnitTpe =>
441+
Block(init, last)
442+
case _ =>
443+
Block(rhs, literalUnit)
444+
}
445+
}
425446

426447
private def mkHandlerCase(num: Int, rhs: Tree): CaseDef =
427448
CaseDef(Literal(Constant(num)), EmptyTree, rhs)
428449

429-
def literalUnit = Literal(Constant(()))
450+
def literalUnit = Literal(Constant(())) // a def to avoid sharing trees
451+
452+
def toList(tree: Tree): List[Tree] = tree match {
453+
case Block(stats, Literal(Constant(value))) if value == () => stats
454+
case _ => tree :: Nil
455+
}
430456

431457
def literalNull = Literal(Constant(null))
432458
}

0 commit comments

Comments
 (0)