From d28641c19e52ca4059fb2ec00f89e2fc71b9937e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Thu, 2 Feb 2023 12:07:40 +0100 Subject: [PATCH] Fix #16801: Scala.js: Handle Closure's of s.r.FunctionXXL. --- compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala | 7 +++++-- .../src/scala/scalajs/runtime/AnonFunctionXXL.scala | 8 ++++++++ project/MiMaFilters.scala | 3 +++ tests/run/functionXXL.scala | 2 -- tests/run/i2004.scala | 2 -- tests/run/implicitFunctionXXL.scala | 2 -- tests/run/tupled-function-andThen.scala | 2 -- tests/run/tupled-function-apply.scala | 4 +--- tests/run/tupled-function-compose.scala | 2 -- tests/run/tupled-function-extension-method.scala | 10 ++++++---- tests/run/tupled-function-tupled.scala | 2 -- 11 files changed, 23 insertions(+), 21 deletions(-) create mode 100644 library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 4caf1f6b5fa2..eee791852fde 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -3532,13 +3532,16 @@ class JSCodeGen()(using genCtx: Context) { val closure = js.Closure(arrow = true, formalCaptures, formalParams, restParam, genBody, actualCaptures) if (!funInterfaceSym.exists || defn.isFunctionClass(funInterfaceSym)) { - assert(!funInterfaceSym.exists || defn.isFunctionClass(funInterfaceSym), - s"Invalid functional interface $funInterfaceSym reached the back-end") val formalCount = formalParams.size val cls = ClassName("scala.scalajs.runtime.AnonFunction" + formalCount) val ctorName = MethodName.constructor( jstpe.ClassRef(ClassName("scala.scalajs.js.Function" + formalCount)) :: Nil) js.New(cls, js.MethodIdent(ctorName), List(closure)) + } else if (funInterfaceSym.name == tpnme.FunctionXXL && funInterfaceSym.owner == defn.ScalaRuntimePackageClass) { + val cls = ClassName("scala.scalajs.runtime.AnonFunctionXXL") + val ctorName = MethodName.constructor( + jstpe.ClassRef(ClassName("scala.scalajs.js.Function1")) :: Nil) + js.New(cls, js.MethodIdent(ctorName), List(closure)) } else { assert(funInterfaceSym.isJSType, s"Invalid functional interface $funInterfaceSym reached the back-end") diff --git a/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala b/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala new file mode 100644 index 000000000000..87208573eff9 --- /dev/null +++ b/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala @@ -0,0 +1,8 @@ +package scala.scalajs.runtime + +import scala.scalajs.js + +@inline +final class AnonFunctionXXL(f: js.Function1[IArray[Object], Object]) extends scala.runtime.FunctionXXL { + override def apply(xs: IArray[Object]): Object = f(xs) +} diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 0937777595ca..8af2de7058ee 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -17,6 +17,9 @@ object MiMaFilters { ProblemFilters.exclude[MissingClassProblem]("scala.util.boundary$Break"), ProblemFilters.exclude[MissingClassProblem]("scala.util.boundary$Label"), + // Scala.js only: new runtime support class in 3.2.3; not available to users + ProblemFilters.exclude[MissingClassProblem]("scala.scalajs.runtime.AnonFunctionXXL"), + // New experimental features in 3.3.X ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.stdLibPatches.language#experimental.clauseInterleaving"), ProblemFilters.exclude[MissingClassProblem]("scala.runtime.stdLibPatches.language$experimental$clauseInterleaving$"), diff --git a/tests/run/functionXXL.scala b/tests/run/functionXXL.scala index 885e7bce8be9..de8c8e3faedd 100644 --- a/tests/run/functionXXL.scala +++ b/tests/run/functionXXL.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - object Test { val f = (x1: Int, diff --git a/tests/run/i2004.scala b/tests/run/i2004.scala index dd829ef24b5b..8682423ef2f0 100644 --- a/tests/run/i2004.scala +++ b/tests/run/i2004.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - object Test { def main(args: Array[String]) = { diff --git a/tests/run/implicitFunctionXXL.scala b/tests/run/implicitFunctionXXL.scala index fcae9c135cda..b4131080577d 100644 --- a/tests/run/implicitFunctionXXL.scala +++ b/tests/run/implicitFunctionXXL.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run/tupled-function-andThen.scala b/tests/run/tupled-function-andThen.scala index a57c3613bb32..94236e9267e1 100644 --- a/tests/run/tupled-function-andThen.scala +++ b/tests/run/tupled-function-andThen.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.util.TupledFunction object Test { diff --git a/tests/run/tupled-function-apply.scala b/tests/run/tupled-function-apply.scala index 76f6b823df76..7d2162a565ac 100644 --- a/tests/run/tupled-function-apply.scala +++ b/tests/run/tupled-function-apply.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.util.TupledFunction object Test { @@ -119,4 +117,4 @@ object Test { */ extension [F, Args <: Tuple, R](f: F) def apply (args: Args)(using tf: TupledFunction[F, Args => R]): R = tf.tupled(f)(args) -} \ No newline at end of file +} diff --git a/tests/run/tupled-function-compose.scala b/tests/run/tupled-function-compose.scala index a2ca5c56771a..4cf83563274d 100644 --- a/tests/run/tupled-function-compose.scala +++ b/tests/run/tupled-function-compose.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run/tupled-function-extension-method.scala b/tests/run/tupled-function-extension-method.scala index 0185fc4eb06c..be5ccbd5ca17 100644 --- a/tests/run/tupled-function-extension-method.scala +++ b/tests/run/tupled-function-extension-method.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { @@ -13,7 +11,7 @@ object Test { (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25) ) - println(f0()) + portablePrintln(f0()) println(f1(1)) println(f2(1, 2)) println(f3(1, 2, 3)) @@ -34,6 +32,10 @@ object Test { } + def portablePrintln(x: Any): Unit = + if x == () then println("()") + else println(x) + class Expr[T](val x: T) // Specialized only for arity 0 and one as auto tupling will not provide the disired effect @@ -50,4 +52,4 @@ object Test { extension [F, Args <: Tuple, R](e: Expr[F]) def applyGiven (args: Args)(using tf: TupledFunction[F, Args ?=> R]): R = tf.tupled(e.x)(using args) -} \ No newline at end of file +} diff --git a/tests/run/tupled-function-tupled.scala b/tests/run/tupled-function-tupled.scala index 360e3e299770..6e7d94b3ac3d 100644 --- a/tests/run/tupled-function-tupled.scala +++ b/tests/run/tupled-function-tupled.scala @@ -1,5 +1,3 @@ -// scalajs: --skip --pending - import scala.util.TupledFunction object Test {