Skip to content

Commit

Permalink
Fix another Try expr problem
Browse files Browse the repository at this point in the history
  • Loading branch information
retronym committed Mar 29, 2020
1 parent 40247d6 commit 7084867
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
12 changes: 1 addition & 11 deletions src/compiler/scala/tools/nsc/transform/async/AsyncPhase.scala
Expand Up @@ -201,21 +201,11 @@ abstract class AsyncPhase extends Transform with TypingTransformers with AnfTran
}
atPos(tree.pos)(Select(outerOrThis.setType(stateMachineClass.tpe), tree.symbol).setType(tree.symbol.tpe))
}
// Avoid moving a Try into expression position with a potentially non-empty stack.
// Uncurry has already run and is responsible for faking try expressions! See needsTryLift.
private def pushAssignmentIntoTry(lhs: Tree, rhs: Tree): Tree = rhs match {
case Try(block, catches, finalizer) =>
val block1 = pushAssignmentIntoTry(lhs, block)
val catches1 = catches.mapConserve(cd => deriveCaseDef(cd)(body => pushAssignmentIntoTry(lhs, body)))
assignUnitType(treeCopy.Try(rhs, block1, catches1, finalizer))
case _ =>
assignUnitType(treeCopy.Assign(rhs, lhs, adapt(rhs, lhs.symbol.tpe)))
}
override def transform(tree: Tree): Tree = tree match {
case ValDef(_, _, _, rhs) if liftedSyms(tree.symbol) && currentOwner == applySym =>
// Drop the lifted definitions from the apply method
val rhs1 = transform(rhs.changeOwner(tree.symbol, currentOwner))
pushAssignmentIntoTry(fieldSel(tree), rhs1)
deriveTree(rhs1, definitions.UnitTpe)(t => treeCopy.Assign(rhs1, fieldSel(tree), adapt(t, tree.symbol.tpe)))
case _: DefTree if liftedSyms(tree.symbol) && currentOwner == applySym =>
// Drop the lifted definitions from the apply method
EmptyTree
Expand Down
Expand Up @@ -528,7 +528,9 @@ trait ExprBuilder extends TransformUtils {

// Comlete the Promise in the `result` field with the final successful result of this async block.
private def completeSuccess(expr: Tree): Tree = {
typed(Apply(currentTransformState.memberRef(currentTransformState.stateCompleteSuccess), expr :: Nil))
deriveTree(expr, definitions.UnitTpe) { expr =>
typed(Apply(currentTransformState.memberRef(currentTransformState.stateCompleteSuccess), expr :: Nil))
}
}

/** What trailing statements should be added to the code for this state to transition to the nest state? */
Expand Down
13 changes: 13 additions & 0 deletions src/compiler/scala/tools/nsc/transform/async/TransformUtils.scala
Expand Up @@ -61,6 +61,19 @@ private[async] trait TransformUtils extends AsyncTransformStates {

def assignUnitType(t: Tree): t.type = t.setType(definitions.UnitTpe)

// Avoid moving a Try into expression position with a potentially non-empty stack.
// Uncurry has already run and is responsible for faking try expressions! See needsTryLift.
final def deriveTree(tree: Tree, exprType: Type)(deriveExpr: Tree => Tree): Tree = tree match {
case Try(block, catches, finalizer) =>
val block1 = deriveTree(block, exprType)(deriveExpr)
val catches1 = catches.mapConserve(cd => deriveCaseDef(cd)(body => deriveTree(body, exprType)(deriveExpr)))
treeCopy.Try(tree, block1, catches1, finalizer).setType(exprType)
case Block(stats, expr) =>
treeCopy.Block(tree, stats, deriveTree(expr, exprType)(deriveExpr))
case _ =>
deriveExpr(tree).setType(exprType)
}

def isUnitType(tp: Type): Boolean = tp.typeSymbol == definitions.UnitClass || tp =:= definitions.BoxedUnitTpe

def literalUnit: Tree = Literal(Constant(())).setType(definitions.UnitTpe) // a def to avoid sharing trees
Expand Down
23 changes: 23 additions & 0 deletions test/junit/scala/tools/nsc/async/AnnotationDrivenAsync.scala
Expand Up @@ -140,6 +140,29 @@ class AnnotationDrivenAsync {
assertEquals(("body1", "body2"), run(code))
}

@Test
def avoidLiftingTryIntoExpression2(): Unit = {
val code =
"""
|import scala.concurrent._, duration.Duration, ExecutionContext.Implicits.global
|import scala.tools.partest.async.Async.{async, await}
|import Future.{successful => f}
|
|object Test {
| def test = async {
| await(f(1))
| try {
| "body"
| } catch {
| case _: Throwable =>
| "catch"
| }
| }
|}
|""".stripMargin
assertEquals("body", run(code))
}

@Test
def avoidWhileExprPosition(): Unit = {
val code =
Expand Down

0 comments on commit 7084867

Please sign in to comment.