From 51b16e421ddd4e6c7e90ba945addf39ffcb4fa41 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 28 Jan 2014 11:29:28 +0300 Subject: SI-8192 adds ClassSymbol.isPrimaryConstructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exposes a popular code pattern in macros as a dedicated reflection API. This simple commit, however, ended up being not so simple, as it often happens with our compiler. When writing a test for the new API, I realized that our (pre-existing) MethodSymbol.isPrimaryConstructor API returns nonsensical results for implementation artifacts (trait mixin ctors, module class ctors). What’s even more funny is that according to our reflection internals, even Java classes have primary constructors. Well, that’s not surprising, because `primaryConstructor` is just `decl(ctorName).alternatives.head`. Good thing that package classes don’t have constructors or that would elevate the situation to three fries short of a happy meal. At the moment, I’m too scared to fiddle with internal#Symbol.primaryConstructor, because that could easily break someone right before RC1, so I simply documented the findings in SI-8193 and postponed the actual work, except for one thing - isJavaDefined symbols no longer have primary constructors. --- test/files/run/t6392b.check | 2 +- test/files/run/t7582-private-within.check | 2 +- test/files/run/t8192.check | 44 +++++++++++++++++++++++++++++++ test/files/run/t8192/Macros_1.scala | 44 +++++++++++++++++++++++++++++++ test/files/run/t8192/Test_2.scala | 39 +++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 test/files/run/t8192.check create mode 100644 test/files/run/t8192/Macros_1.scala create mode 100644 test/files/run/t8192/Test_2.scala (limited to 'test') diff --git a/test/files/run/t6392b.check b/test/files/run/t6392b.check index c2cc103373..3f191c7960 100644 --- a/test/files/run/t6392b.check +++ b/test/files/run/t6392b.check @@ -1 +1 @@ -ModuleDef(Modifiers(), TermName("C")#MOD, Template(List(Select(Ident(scala#PK), TypeName("AnyRef")#TPE)), noSelfType, List(DefDef(Modifiers(), nme.CONSTRUCTOR#PCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("C")), tpnme.EMPTY), nme.CONSTRUCTOR#PCTOR), List())), Literal(Constant(()))))))) +ModuleDef(Modifiers(), TermName("C")#MOD, Template(List(Select(Ident(scala#PK), TypeName("AnyRef")#TPE)), noSelfType, List(DefDef(Modifiers(), nme.CONSTRUCTOR#PCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("C")), tpnme.EMPTY), nme.CONSTRUCTOR#CTOR), List())), Literal(Constant(()))))))) diff --git a/test/files/run/t7582-private-within.check b/test/files/run/t7582-private-within.check index b2743ffa06..1b9a0910af 100644 --- a/test/files/run/t7582-private-within.check +++ b/test/files/run/t7582-private-within.check @@ -2,7 +2,7 @@ private[package pack] class JavaPackagePrivate private[package pack] module JavaPackagePrivate private[package pack] module class JavaPackagePrivate private[package pack] field field -private[package pack] primary constructor +private[package pack] constructor private[package pack] method meth private[package pack] field staticField private[package pack] method staticMeth diff --git a/test/files/run/t8192.check b/test/files/run/t8192.check new file mode 100644 index 0000000000..7195703e19 --- /dev/null +++ b/test/files/run/t8192.check @@ -0,0 +1,44 @@ +compile-time +class File +primary constructor: NoSymbol +def (x$1: String): java.io.File => false +def (x$1: String,x$2: String): java.io.File => false +def (x$1: java.io.File,x$2: String): java.io.File => false +def (x$1: java.net.URI): java.io.File => false +package scala +primary constructor: NoSymbol +object List +primary constructor: def (): scala.collection.immutable.List.type => true +def (): scala.collection.immutable.List.type => true +trait Product1 +primary constructor: def $init$(): Unit => true +class UninitializedFieldError +primary constructor: def (msg: String): UninitializedFieldError => true +def (msg: String): UninitializedFieldError => true +def (obj: Any): UninitializedFieldError => false +class C +primary constructor: def (x: Int): C => true +def (x: Int): C => true +def (x: String): C => false +runtime +class File +primary constructor: NoSymbol +def (x$1: java.io.File,x$2: java.lang.String): java.io.File => false +def (x$1: java.lang.String): java.io.File => false +def (x$1: java.lang.String,x$2: java.lang.String): java.io.File => false +def (x$1: java.net.URI): java.io.File => false +package scala +primary constructor: NoSymbol +object List +primary constructor: def (): scala.collection.immutable.List.type => true +def (): scala.collection.immutable.List.type => true +trait Product1 +primary constructor: def $init$(): Unit => true +class UninitializedFieldError +primary constructor: def (msg: String): UninitializedFieldError => true +def (msg: String): UninitializedFieldError => true +def (obj: Any): UninitializedFieldError => false +class C +primary constructor: def (x: Int): C => true +def (x: Int): C => true +def (x: String): C => false diff --git a/test/files/run/t8192/Macros_1.scala b/test/files/run/t8192/Macros_1.scala new file mode 100644 index 0000000000..2089273d6d --- /dev/null +++ b/test/files/run/t8192/Macros_1.scala @@ -0,0 +1,44 @@ +import scala.reflect.macros.whitebox._ +import scala.language.experimental.macros +import java.io._ + +object Macros { + def impl(c: Context) = { + var messages = List[String]() + def println(msg: String) = messages :+= msg + + import c.universe._ + def test(sym: ClassSymbol): Unit = { + def fullyInitializeSymbol(sym: Symbol): Unit = { + val internal = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable] + internal.definitions.fullyInitializeSymbol(sym.asInstanceOf[internal.Symbol]) + } + def defString(sym: Symbol): String = { + val internal = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable] + sym.asInstanceOf[internal.Symbol].defString + } + def showCtor(sym: Symbol): String = { + fullyInitializeSymbol(sym) + if (sym == NoSymbol) "NoSymbol" + else s"${defString(sym)} => ${sym.asMethod.isPrimaryConstructor}" + } + sym.typeSignature + println(sym.toString) + println(s"primary constructor: ${showCtor(sym.primaryConstructor)}") + val ctors = sym.typeSignature.members.filter(_.name == nme.CONSTRUCTOR).map(sym => showCtor(sym)) + ctors.toList.sorted.foreach(println) + } + + println("compile-time") + test(typeOf[File].typeSymbol.asClass) + test(definitions.ScalaPackageClass) + test(definitions.ListModule.moduleClass.asClass) + test(typeOf[Product1[_]].typeSymbol.asClass) + test(typeOf[UninitializedFieldError].typeSymbol.asClass) + test(c.mirror.staticClass("C").asClass) + + q"..${messages.map(msg => q"println($msg)")}" + } + + def foo: Any = macro impl +} \ No newline at end of file diff --git a/test/files/run/t8192/Test_2.scala b/test/files/run/t8192/Test_2.scala new file mode 100644 index 0000000000..15f684eb3f --- /dev/null +++ b/test/files/run/t8192/Test_2.scala @@ -0,0 +1,39 @@ +import java.io._ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} + +class C(x: Int) { + def this(x: String) = this(x.toInt) +} + +object Test extends App { + def test(sym: ClassSymbol): Unit = { + def fullyInitializeSymbol(sym: Symbol): Unit = { + val internal = ru.asInstanceOf[scala.reflect.internal.SymbolTable] + internal.definitions.fullyInitializeSymbol(sym.asInstanceOf[internal.Symbol]) + } + def defString(sym: Symbol): String = { + val internal = ru.asInstanceOf[scala.reflect.internal.SymbolTable] + sym.asInstanceOf[internal.Symbol].defString + } + def showCtor(sym: Symbol): String = { + fullyInitializeSymbol(sym) + if (sym == NoSymbol) "NoSymbol" + else s"${defString(sym)} => ${sym.asMethod.isPrimaryConstructor}" + } + sym.typeSignature + println(sym.toString) + println(s"primary constructor: ${showCtor(sym.primaryConstructor)}") + val ctors = sym.typeSignature.members.filter(_.name == nme.CONSTRUCTOR).map(sym => showCtor(sym)) + ctors.toList.sorted.foreach(println) + } + + Macros.foo + println("runtime") + test(typeOf[File].typeSymbol.asClass) + test(definitions.ScalaPackageClass) + test(definitions.ListModule.moduleClass.asClass) + test(typeOf[Product1[_]].typeSymbol.asClass) + test(typeOf[UninitializedFieldError].typeSymbol.asClass) + test(typeOf[C].typeSymbol.asClass) +} -- cgit v1.2.3