Skip to content

Commit de641dc

Browse files
committed
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.
1 parent 43c0287 commit de641dc

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,11 @@ trait AsyncTransform {
7070
for ((state, flds) <- assignsOf) {
7171
val assigns = flds.map { fld =>
7272
val fieldSym = fld.symbol
73-
Block(
74-
List(
75-
asyncBase.nullOut(c.universe)(c.Expr[String](Literal(Constant(fieldSym.name.toString))), c.Expr[Any](Ident(fieldSym))).tree
76-
),
77-
Assign(gen.mkAttributedStableRef(thisType(fieldSym.owner), fieldSym), mkZero(fieldSym.info))
78-
)
73+
val assign = Assign(gen.mkAttributedStableRef(thisType(fieldSym.owner), fieldSym), mkZero(fieldSym.info))
74+
asyncBase.nullOut(c.universe)(c.Expr[String](Literal(Constant(fieldSym.name.toString))), c.Expr[Any](Ident(fieldSym))).tree match {
75+
case Literal(Constant(value: Unit)) => assign
76+
case x => Block(x :: Nil, assign)
77+
}
7978
}
8079
val asyncState = asyncBlock.asyncStates.find(_.state == state).get
8180
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
@@ -34,8 +34,13 @@ trait ExprBuilder {
3434

3535
var stats: List[Tree]
3636

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

@@ -52,8 +57,9 @@ trait ExprBuilder {
5257
def nextStates: List[Int] =
5358
List(nextState)
5459

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

5864
override val toString: String =
5965
s"AsyncState #$state, next = $nextState"
@@ -87,10 +93,10 @@ trait ExprBuilder {
8793
val tryGetOrCallOnComplete =
8894
if (futureSystemOps.continueCompletedFutureOnSameThread)
8995
If(futureSystemOps.isCompleted(c.Expr[futureSystem.Fut[_]](awaitable.expr)).tree,
90-
Block(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil, literalUnit),
91-
Block(callOnComplete :: Nil, Return(literalUnit)))
96+
adaptToUnit(ifIsFailureTree[T](futureSystemOps.getCompleted[Any](c.Expr[futureSystem.Fut[Any]](awaitable.expr)).tree) :: Nil),
97+
Block(toList(callOnComplete), Return(literalUnit)))
9298
else
93-
Block(callOnComplete :: Nil, Return(literalUnit))
99+
Block(toList(callOnComplete), Return(literalUnit))
94100
mkHandlerCase(state, stats ++ List(mkStateTree(onCompleteState, symLookup), tryGetOrCallOnComplete))
95101
}
96102

@@ -110,11 +116,11 @@ trait ExprBuilder {
110116
*/
111117
def ifIsFailureTree[T: WeakTypeTag](tryReference: => Tree) =
112118
If(futureSystemOps.tryyIsFailure(c.Expr[futureSystem.Tryy[T]](tryReference)).tree,
113-
Block(futureSystemOps.completeProm[T](
119+
Block(toList(futureSystemOps.completeProm[T](
114120
c.Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)),
115121
c.Expr[futureSystem.Tryy[T]](
116122
TypeApply(Select(tryReference, newTermName("asInstanceOf")),
117-
List(TypeTree(futureSystemOps.tryType[T]))))).tree :: Nil,
123+
List(TypeTree(futureSystemOps.tryType[T]))))).tree),
118124
Return(literalUnit)),
119125
Block(List(tryGetTree(tryReference)), mkStateTree(nextState, symLookup))
120126
)
@@ -382,12 +388,12 @@ trait ExprBuilder {
382388
val t = c.Expr[Throwable](Ident(name.t))
383389
val complete = futureSystemOps.completeProm[T](
384390
c.Expr[futureSystem.Prom[T]](symLookup.memberRef(name.result)), futureSystemOps.tryyFailure[T](t)).tree
385-
Block(complete :: Nil, Return(literalUnit))
391+
Block(toList(complete), Return(literalUnit))
386392
})), EmptyTree)
387393

388394
def forever(t: Tree): Tree = {
389395
val labelName = name.fresh("while$")
390-
LabelDef(labelName, Nil, Block(t :: Nil, Apply(Ident(labelName), Nil)))
396+
LabelDef(labelName, Nil, Block(toList(t), Apply(Ident(labelName), Nil)))
391397
}
392398

393399
/**
@@ -405,7 +411,7 @@ trait ExprBuilder {
405411
def onCompleteHandler[T: WeakTypeTag]: Tree = {
406412
val onCompletes = initStates.flatMap(_.mkOnCompleteHandler[T]).toList
407413
forever {
408-
Block(resumeFunTree :: Nil, literalUnit)
414+
adaptToUnit(toList(resumeFunTree))
409415
}
410416
}
411417
}
@@ -422,12 +428,32 @@ trait ExprBuilder {
422428
Assign(symLookup.memberRef(name.state), Literal(Constant(nextState)))
423429

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

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

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

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

0 commit comments

Comments
 (0)