From 88bc6bd21c695141965d0b9158a67a7213f48520 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 22 May 2018 20:04:37 +0200 Subject: [PATCH 1/2] Fix macros with array parameters --- .../dotty/tools/dotc/transform/Splicer.scala | 19 +++++++++++++- tests/pos/macro-with-array/Macro_1.scala | 25 +++++++++++++++++++ tests/pos/macro-with-array/Test_2.scala | 20 +++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/pos/macro-with-array/Macro_1.scala create mode 100644 tests/pos/macro-with-array/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 6c5d003fd79a..12bffb69d81f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -173,7 +173,24 @@ object Splicer { sym.signature.paramsSig.map { param => defn.valueTypeNameToJavaType(param) match { case Some(clazz) => clazz - case None => classLoader.loadClass(param.toString) + case None => + def javaArraySig(name: String): String = { + if (name.endsWith("[]")) "[" + javaArraySig(name.dropRight(2)) + else name match { + case "scala.Boolean" => "Z" + case "scala.Byte" => "B" + case "scala.Short" => "S" + case "scala.Int" => "I" + case "scala.Long" => "J" + case "scala.Float" => "F" + case "scala.Double" => "D" + case "scala.Char" => "C" + case paramName => "L" + paramName + ";" + } + } + def javaSig(name: String): String = + if (name.endsWith("[]")) javaArraySig(name) else name + java.lang.Class.forName(javaSig(param.toString), false, classLoader) } } } diff --git a/tests/pos/macro-with-array/Macro_1.scala b/tests/pos/macro-with-array/Macro_1.scala new file mode 100644 index 000000000000..9c9b2079927f --- /dev/null +++ b/tests/pos/macro-with-array/Macro_1.scala @@ -0,0 +1,25 @@ + +object Macro { + + inline def foo1(arr: Array[Boolean]): Unit = ~{ '() } + inline def foo2(arr: Array[Byte]): Unit = ~{ '() } + inline def foo3(arr: Array[Short]): Unit = ~{ '() } + inline def foo4(arr: Array[Int]): Unit = ~{ '() } + inline def foo5(arr: Array[Long]): Unit = ~{ '() } + inline def foo6(arr: Array[Float]): Unit = ~{ '() } + inline def foo7(arr: Array[Double]): Unit = ~{ '() } + inline def foo8(arr: Array[Char]): Unit = ~{ '() } + inline def foo9(arr: Array[Object]): Unit = ~{ '() } + inline def foo10(arr: Array[String]): Unit = ~{ '() } + inline def foo11[T](arr: Array[T]): Unit = ~{ '() } + inline def foo12(arr: Array[Array[Int]]): Unit = ~{ '() } + inline def foo13(arr: Array[Array[String]]): Unit = ~{ '() } + inline def foo14(arr: Array[Array[Array[Int]]]): Unit = ~{ '() } + inline def foo15(arr: Array[Any]): Unit = ~{ '() } + inline def foo16(arr: Array[AnyVal]): Unit = ~{ '() } + inline def foo17(arr: Array[AnyRef]): Unit = ~{ '() } + inline def foo18(arr: Array[Foo]): Unit = ~{ '() } + +} + +class Foo diff --git a/tests/pos/macro-with-array/Test_2.scala b/tests/pos/macro-with-array/Test_2.scala new file mode 100644 index 000000000000..492def650331 --- /dev/null +++ b/tests/pos/macro-with-array/Test_2.scala @@ -0,0 +1,20 @@ +object PowerInlined1 { + Macro.foo1(Array.empty) + Macro.foo2(Array.empty) + Macro.foo3(Array.empty) + Macro.foo4(Array.empty) + Macro.foo5(Array.empty) + Macro.foo6(Array.empty) + Macro.foo7(Array.empty) + Macro.foo8(Array.empty) + Macro.foo9(Array.empty) + Macro.foo10(Array.empty) + Macro.foo11[String](Array.empty) + Macro.foo12(Array.empty) + Macro.foo13(Array.empty) + Macro.foo14(Array.empty) + Macro.foo15(Array.empty) + Macro.foo16(Array.empty) + Macro.foo17(Array.empty) + Macro.foo18(Array.empty) +} From 7cdecc6ef9b3e4a79de40ce437acedaef6c8552c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 23 May 2018 14:22:18 +0200 Subject: [PATCH 2/2] Fix macros with Module and inner classes parameters --- .../dotty/tools/dotc/core/Definitions.scala | 10 +-- .../dotty/tools/dotc/transform/Splicer.scala | 65 ++++++++++++------- tests/pos/macro-with-array/Macro_1.scala | 11 +++- tests/pos/macro-with-array/Test_2.scala | 5 ++ 4 files changed, 63 insertions(+), 28 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index ef5d0d1f7022..b0b847da4e4d 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1137,7 +1137,7 @@ class Definitions { // private val unboxedTypeRef = mutable.Map[TypeName, TypeRef]() // private val javaTypeToValueTypeRef = mutable.Map[Class[_], TypeRef]() - private val valueTypeNamesToJavaType = mutable.Map[TypeName, Class[_]]() +// private val valueTypeNamesToJavaType = mutable.Map[TypeName, Class[_]]() private def valueTypeRef(name: String, boxed: TypeRef, jtype: Class[_], enc: Int, tag: Name): TypeRef = { val vcls = ctx.requiredClassRef(name) @@ -1146,7 +1146,7 @@ class Definitions { typeTags(vcls.name) = tag // unboxedTypeRef(boxed.name) = vcls // javaTypeToValueTypeRef(jtype) = vcls - valueTypeNamesToJavaType(vcls.name) = jtype +// valueTypeNamesToJavaType(vcls.name) = jtype vcls } @@ -1156,9 +1156,9 @@ class Definitions { /** The JVM tag for `tp` if it's a primitive, `java.lang.Object` otherwise. */ def typeTag(tp: Type)(implicit ctx: Context): Name = typeTags(scalaClassName(tp)) - /** The `Class[_]` of a primitive value type name */ - def valueTypeNameToJavaType(name: TypeName)(implicit ctx: Context): Option[Class[_]] = - valueTypeNamesToJavaType.get(if (name.firstPart eq nme.scala_) name.lastPart.toTypeName else name) +// /** The `Class[_]` of a primitive value type name */ +// def valueTypeNameToJavaType(name: TypeName)(implicit ctx: Context): Option[Class[_]] = +// valueTypeNamesToJavaType.get(if (name.firstPart eq nme.scala_) name.lastPart.toTypeName else name) type PrimitiveClassEnc = Int diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 12bffb69d81f..fa2900a673c1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -3,7 +3,6 @@ package transform import java.io.{PrintWriter, StringWriter} import java.lang.reflect.Method -import java.net.URLClassLoader import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts._ @@ -14,6 +13,7 @@ import dotty.tools.dotc.core.Names.Name import dotty.tools.dotc.core.quoted._ import dotty.tools.dotc.core.Types._ import dotty.tools.dotc.core.Symbols._ +import dotty.tools.dotc.core.TypeErasure import scala.util.control.NonFatal import dotty.tools.dotc.util.Positions.Position @@ -170,28 +170,49 @@ object Splicer { /** List of classes of the parameters of the signature of `sym` */ private def paramsSig(sym: Symbol): List[Class[_]] = { - sym.signature.paramsSig.map { param => - defn.valueTypeNameToJavaType(param) match { - case Some(clazz) => clazz - case None => - def javaArraySig(name: String): String = { - if (name.endsWith("[]")) "[" + javaArraySig(name.dropRight(2)) - else name match { - case "scala.Boolean" => "Z" - case "scala.Byte" => "B" - case "scala.Short" => "S" - case "scala.Int" => "I" - case "scala.Long" => "J" - case "scala.Float" => "F" - case "scala.Double" => "D" - case "scala.Char" => "C" - case paramName => "L" + paramName + ";" - } + TypeErasure.erasure(sym.info) match { + case meth: MethodType => + meth.paramInfos.map { param => + def arrayDepth(tpe: Type, depth: Int): (Type, Int) = tpe match { + case JavaArrayType(elemType) => arrayDepth(elemType, depth + 1) + case _ => (tpe, depth) } - def javaSig(name: String): String = - if (name.endsWith("[]")) javaArraySig(name) else name - java.lang.Class.forName(javaSig(param.toString), false, classLoader) - } + def javaArraySig(tpe: Type): String = { + val (elemType, depth) = arrayDepth(tpe, 0) + val sym = elemType.classSymbol + val suffix = + if (sym == defn.BooleanClass) "Z" + else if (sym == defn.ByteClass) "B" + else if (sym == defn.ShortClass) "S" + else if (sym == defn.IntClass) "I" + else if (sym == defn.LongClass) "J" + else if (sym == defn.FloatClass) "F" + else if (sym == defn.DoubleClass) "D" + else if (sym == defn.CharClass) "C" + else "L" + javaSig(elemType) + ";" + ("[" * depth) + suffix + } + def javaSig(tpe: Type): String = tpe match { + case tpe: JavaArrayType => javaArraySig(tpe) + case _ => + // Take the flatten name of the class and the full package name + val pack = tpe.classSymbol.topLevelClass.owner + val packageName = if (pack == defn.EmptyPackageClass) "" else pack.fullName + "." + packageName + tpe.classSymbol.fullNameSeparated(FlatName).toString + } + + val sym = param.classSymbol + if (sym == defn.BooleanClass) classOf[Boolean] + else if (sym == defn.ByteClass) classOf[Byte] + else if (sym == defn.CharClass) classOf[Char] + else if (sym == defn.ShortClass) classOf[Short] + else if (sym == defn.IntClass) classOf[Int] + else if (sym == defn.LongClass) classOf[Long] + else if (sym == defn.FloatClass) classOf[Float] + else if (sym == defn.DoubleClass) classOf[Double] + else java.lang.Class.forName(javaSig(param), false, classLoader) + } + case _ => Nil } } diff --git a/tests/pos/macro-with-array/Macro_1.scala b/tests/pos/macro-with-array/Macro_1.scala index 9c9b2079927f..a115aa3dc036 100644 --- a/tests/pos/macro-with-array/Macro_1.scala +++ b/tests/pos/macro-with-array/Macro_1.scala @@ -1,6 +1,7 @@ object Macro { + inline def foo0(i: Int): Unit = ~{ '() } inline def foo1(arr: Array[Boolean]): Unit = ~{ '() } inline def foo2(arr: Array[Byte]): Unit = ~{ '() } inline def foo3(arr: Array[Short]): Unit = ~{ '() } @@ -19,7 +20,15 @@ object Macro { inline def foo16(arr: Array[AnyVal]): Unit = ~{ '() } inline def foo17(arr: Array[AnyRef]): Unit = ~{ '() } inline def foo18(arr: Array[Foo]): Unit = ~{ '() } + inline def foo19(arr: Array[Macro.type]): Unit = ~{ '() } + inline def foo20(arr: Array[Bar]): Unit = ~{ '() } + inline def foo21(arr: Array[Baz.type]): Unit = ~{ '() } + inline def foo22(arr: Array[Foo#A]): Unit = ~{ '() } + class Bar + object Baz } -class Foo +class Foo { + class A +} diff --git a/tests/pos/macro-with-array/Test_2.scala b/tests/pos/macro-with-array/Test_2.scala index 492def650331..65f8ca52a651 100644 --- a/tests/pos/macro-with-array/Test_2.scala +++ b/tests/pos/macro-with-array/Test_2.scala @@ -1,4 +1,5 @@ object PowerInlined1 { + Macro.foo0(2) Macro.foo1(Array.empty) Macro.foo2(Array.empty) Macro.foo3(Array.empty) @@ -17,4 +18,8 @@ object PowerInlined1 { Macro.foo16(Array.empty) Macro.foo17(Array.empty) Macro.foo18(Array.empty) + Macro.foo19(Array.empty) + Macro.foo20(Array.empty) + Macro.foo21(Array.empty) + Macro.foo22(Array.empty) }