8000 Fix regression with non-awaiting patterns in tail position · scala/scala@8ef4dd9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8ef4dd9

Browse files
committed
Fix regression with non-awaiting patterns in tail position
1 parent e160b8d commit 8ef4dd9

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

src/compiler/scala/tools/nsc/transform/async/AnfTransform.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ private[async] trait AnfTransform extends TransformUtils {
5454
tree
5555
case _ if !treeContainsAwait =>
5656
tree
57+
case sel @ Select(fun, _) if containsAwait(fun) =>
58+
val fun1 = transform(fun)
59+
val valDef = defineVal(name.qual(), fun1, fun1.pos)
60+
currentStats += valDef
61+
treeCopy.Select(tree, fun1, sel.name)
5762
case Apply(sel @ Select(fun, _), arg :: Nil) if isBooleanAnd(sel.symbol) && containsAwait(arg) =>
5863
transform(treeCopy.If(tree, fun, arg, literalBool(false)))
5964
case Apply(sel @ Select(fun, _), arg :: Nil) if isBooleanOr(sel.symbol) && containsAwait(arg) =>
@@ -164,6 +169,8 @@ private[async] trait AnfTransform extends TransformUtils {
164169

165170
case ld @ LabelDef(name, params, rhs) =>
166171
treeCopy.LabelDef(tree, name, params, transformNewControlFlowBlock(rhs))
172+
case t @ Typed(expr, tpt) =>
173+
transform(expr).setType(t.tpe)
167174
case _ =>
168175
super.transform(tree)
169176
}

src/compiler/scala/tools/nsc/transform/async/AsyncNames.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ final class AsyncNames[U <: reflect.internal.Names with Singleton](val u: U) {
4343
}
4444
private val matchRes: TermNameCache = new TermNameCache("match")
4545
private val ifRes: TermNameCache = new TermNameCache("if")
46+
private val qual: TermNameCache = new TermNameCache("qual")
4647
private val await: TermNameCache = new TermNameCache("await")
4748

4849

@@ -54,6 +55,7 @@ final class AsyncNames[U <: reflect.internal.Names with Singleton](val u: U) {
5455
class AsyncName {
5556
final val matchRes = new NameSource[U#TermName](self.matchRes)
5657
final val ifRes = new NameSource[U#TermName](self.ifRes)
58+
final val qual = new NameSource[U#TermName](self.qual)
5759
final val await = new NameSource[U#TermName](self.await)
5860

5961
private val seenPrefixes = mutable.AnyRefMap[Name, AtomicInteger]()

src/compiler/scala/tools/nsc/transform/async/ExprBuilder.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,14 @@ trait ExprBuilder extends TransformUtils {
113113
// An exception should bubble out to the enclosing handler, don't insert a complete call.
114114
} else {
115115
val expr = stats.remove(stats.size - 1)
116-
stats += completeSuccess(expr)
116+
def pushIntoMatchEnd(t: Tree): Tree = {
117+
t match {
118+
case MatchEnd(ld) => treeCopy.LabelDef(ld, ld.name, ld.params, pushIntoMatchEnd(ld.rhs))
119+
case b@Block(caseStats, caseExpr) => assignUnitType(treeCopy.Block(b, caseStats, pushIntoMatchEnd(caseExpr)))
120+
case expr => completeSuccess(expr)
121+
}
122+
}
123+
stats += pushIntoMatchEnd(expr)
117124
}
118125
stats += typed(Return(literalUnit).setSymbol(currentTransformState.applySym))
119126
allNextStates -= nextState
@@ -243,7 +250,7 @@ trait ExprBuilder extends TransformUtils {
243250
}
244251

245252
case ld @ LabelDef(name, params, rhs) =>
246-
if (isCaseLabel(ld.symbol) || isMatchEndLabel(ld.symbol)) {
253+
if (isCaseLabel(ld.symbol) || (isMatchEndLabel(ld.symbol) && labelDefStates.contains(ld.symbol))) {
247254
// LabelDefs from patterns are a bit trickier as they can (forward) branch to each other.
248255

249256
labelDefStates.get(ld.symbol).foreach { startLabelState =>
@@ -259,7 +266,7 @@ trait ExprBuilder extends TransformUtils {
259266
}
260267

261268
val afterLabelState = afterState()
262-
val (inlinedState, nestedStates) = buildNestedStatesFirstForInlining(rhs, afterLabelState)
269+
val (inlinedState, nestedStates) = buildNestedStatesFirstForInlining(rhs, afterLabelState)
263270

264271
// Leave this label here for synchronous jumps from previous cases. This is
265272
// allowed even if this case has its own state (ie if there is an asynchrounous path
@@ -288,7 +295,6 @@ trait ExprBuilder extends TransformUtils {
288295
checkForUnsupportedAwait(stat)
289296
stateBuilder += stat
290297
}
291-
292298
case _ =>
293299
checkForUnsupportedAwait(stat)
294300
stateBuilder += stat

test/junit/scala/tools/nsc/async/AnnotationDrivenAsync.scala

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,43 @@ class AnnotationDrivenAsync {
3434
assertEquals(3, run(code))
3535
}
3636

37+
@Test
38+
def patternTailPosition(): Unit = {
39+
val code =
40+
"""
41+
|import scala.concurrent._, duration.Duration, ExecutionContext.Implicits.global
42+
|import scala.tools.partest.async.Async.{async, await}
43+
|import Future.{successful => f}
44+
|
45+
|object Test {
46+
| def test = async {
47+
| {
48+
| await(f(1))
49+
| "foo" match {
50+
| case x if "".isEmpty => x
51+
| }
52+
| }: AnyRef
53+
| }
54+
|}
55+
|""".stripMargin
56+
assertEquals("foo", run(code))
57+
}
58+
59+
@Test
60+
def awaitTyped(): Unit = {
61+
val code =
62+
"""
63+
|import scala.concurrent._, duration.Duration, ExecutionContext.Implicits.global
64+
|import scala.tools.partest.async.Async.{async, await}
65+
|import Future.{successful => f}
66+
|
67+
|object Test {
68+
| def test = async {(("msg: " + await(f(0))): String).toString}
69+
|}
70+
|""".stripMargin
71+
assertEquals("msg: 0", run(code))
72+
}
73+
3774
@Test
3875
def testBooleanAndOr(): Unit = {
3976
val code =
@@ -646,8 +683,8 @@ class AnnotationDrivenAsync {
646683

647684
// settings.debug.value = true
648685
// settings.uniqid.value = true
649-
// settings.processArgumentString("-Xprint:async -nowarn")
650-
// settings.log.value = List("async")
686+
settings.processArgumentString("-Xprint:async -nowarn")
687+
settings.log.value = List("async")
651688

652689
// NOTE: edit ANFTransform.traceAsync to `= true` to get additional diagnostic tracing.
653690

0 commit comments

Comments
 (0)
0