Skip to content

Commit 3f43614

Browse files
committed
Issue lampepfl#7113: Fix Scala.js codegen for Explicit Returns
In order to use an explicit return statement in Scala.js IR, a label must be placed wrapping the whole function body to serve as a jump/break point for all control structures inside the function. 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. This affected the tree created by the TailRec MiniPhase, as well as user-written early return statements. 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 3f43614

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-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.makeLabeledIfRequiresEnclosingReturn(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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,17 @@ object JSEncoding {
9292
returnLabelName = Some(freshName("_return"))
9393
js.Ident(returnLabelName.get)
9494
}
95+
96+
/** If the evaluation of `body` adds a `returnLabelName`, wrap the resulting js.Tree to use that label */
97+
def makeLabeledIfRequiresEnclosingReturn(tpe: jstpe.Type)(body: js.Tree)(implicit pos: ir.Position): js.Tree = {
98+
val inner = body
99+
returnLabelName match {
100+
case None =>
101+
inner
102+
case Some(labelName) =>
103+
js.Labeled(js.Ident(labelName), tpe, inner)
104+
}
105+
}
95106
}
96107

97108
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)