Skip to content

Commit 2ad91c1

Browse files
committed
Issue lampepfl#7113: Fix Scala.js codegen for Tail Recursive Returns
In order to return from a tail recursive tree in Scala.js IR, a label must be placed outside the loop to serve as a jump/break point. While a fresh return label had been generated for such methods (in the LocalNameGenerator), it had not been placed at the top level of its method, and was otherwise unused. After generating a method's body, if a enclosing return label had been generated, use it to wrap the method body (just as Scala 2's JS codegen does) for such breaks. Enable the tests of ReadersTest.scala of the Scala.js test suite, of which InputStreamReaderTest used a tail-recursive method that depended on this fix.
1 parent 5e8e26f commit 2ad91c1

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,10 @@ class JSCodeGen()(implicit ctx: Context) {
723723
mutable = false, rest = false)
724724
}
725725

726-
def genBody() =
726+
def genBody() = localNames.withNewReturnableScope(resultIRType) {
727727
if (resultIRType == jstpe.NoType) genStat(tree)
728728
else genExpr(tree)
729+
}
729730

730731
//if (!isScalaJSDefinedJSClass(currentClassSym)) {
731732
val flags = js.MemberFlags.empty.withNamespace(namespace)

compiler/src/dotty/tools/backend/sjs/JSEncoding.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ object JSEncoding {
9292
returnLabelName = Some(freshName("_return"))
9393
js.Ident(returnLabelName.get)
9494
}
95+
96+
def withNewReturnableScope(tpe: jstpe.Type)(body: => js.Tree)(implicit pos: ir.Position): js.Tree = {
97+
val inner = body
98+
returnLabelName match {
99+
case None =>
100+
inner
101+
case Some(labelName) =>
102+
js.Labeled(js.Ident(labelName), tpe, inner)
103+
}
104+
}
95105
}
96106

97107
private object LocalNameGenerator {

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ object Build {
979979
(
980980
(dir / "shared/src/test/scala/org/scalajs/testsuite/compiler" ** (("*.scala":FileFilter) -- "RegressionTest.scala" -- "ReflectiveCallTest.scala")).get
981981
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/lang" ** (("*.scala": FileFilter) -- "ClassTest.scala" -- "StringTest.scala")).get
982-
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/io" ** (("*.scala": FileFilter) -- "ByteArrayInputStreamTest.scala" -- "ByteArrayOutputStreamTest.scala" -- "DataInputStreamTest.scala" -- "DataOutputStreamTest.scala" -- "InputStreamTest.scala" -- "OutputStreamWriterTest.scala" -- "PrintStreamTest.scala" -- "ReadersTest.scala" -- "CommonStreamsTests.scala")).get
982+
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/io" ** (("*.scala": FileFilter) -- "ByteArrayInputStreamTest.scala" -- "ByteArrayOutputStreamTest.scala" -- "DataInputStreamTest.scala" -- "DataOutputStreamTest.scala" -- "InputStreamTest.scala" -- "OutputStreamWriterTest.scala" -- "PrintStreamTest.scala" -- "CommonStreamsTests.scala")).get
983983
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/math" ** "*.scala").get
984984
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/net" ** (("*.scala": FileFilter) -- "URITest.scala")).get
985985
++ (dir / "shared/src/test/scala/org/scalajs/testsuite/javalib/security" ** "*.scala").get

0 commit comments

Comments
 (0)