summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-12 12:01:12 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-01-12 18:03:51 +0100
commite36888c3d953048483ccea9a95d5984b54ad6ebc (patch)
treea6ba3268a238acb5310dcfdefcf8234c0b7f6a77
parent3a689f5c426436aea716567625fd6167e57bef92 (diff)
downloadscala-e36888c3d953048483ccea9a95d5984b54ad6ebc.tar.gz
scala-e36888c3d953048483ccea9a95d5984b54ad6ebc.tar.bz2
scala-e36888c3d953048483ccea9a95d5984b54ad6ebc.zip
prohibits constructor overloading for macro bundles
As per Jason’s feedback, this commit handles overloaded constructors in macro bundles. The backend now checks that we have a constructor of a correct type. The frontend now prohibits multiple constructors altogether.
-rw-r--r--src/compiler/scala/reflect/macros/compiler/Errors.scala2
-rw-r--r--src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala15
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala3
-rw-r--r--test/files/neg/macro-bundle-abstract.check2
-rw-r--r--test/files/neg/macro-bundle-overloaded.check4
-rw-r--r--test/files/neg/macro-bundle-overloaded.scala12
6 files changed, 32 insertions, 6 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala
index 6b6d4248aa..280baa2a42 100644
--- a/src/compiler/scala/reflect/macros/compiler/Errors.scala
+++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala
@@ -51,7 +51,7 @@ trait Errors extends Traces {
def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static")
- def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete classes having a single `val c: Context` parameter")
+ def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter")
// compatibility errors
diff --git a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala
index 8ad38ff5f0..ecdd48db22 100644
--- a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala
+++ b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala
@@ -2,7 +2,9 @@ package scala.reflect.macros
package runtime
import scala.reflect.runtime.ReflectionUtils
-import scala.reflect.macros.blackbox.{Context => ApiContext}
+import scala.reflect.macros.blackbox.{Context => BlackboxContext}
+import scala.reflect.macros.whitebox.{Context => WhiteboxContext}
+import java.lang.reflect.{Constructor => jConstructor}
trait JavaReflectionRuntimes {
self: scala.tools.nsc.typechecker.Analyzer =>
@@ -19,8 +21,15 @@ trait JavaReflectionRuntimes {
macroLogVerbose(s"successfully loaded macro impl as ($implClass, $implMeth)")
args => {
val implObj =
- if (isBundle) implClass.getConstructors().head.newInstance(args.c)
- else ReflectionUtils.staticSingletonInstance(implClass)
+ if (isBundle) {
+ def isMacroContext(clazz: Class[_]) = clazz == classOf[BlackboxContext] || clazz == classOf[WhiteboxContext]
+ def isBundleCtor(ctor: jConstructor[_]) = ctor.getParameterTypes match {
+ case Array(param) if isMacroContext(param) => true
+ case _ => false
+ }
+ val Array(bundleCtor) = implClass.getConstructors.filter(isBundleCtor)
+ bundleCtor.newInstance(args.c)
+ } else ReflectionUtils.staticSingletonInstance(implClass)
val implArgs = if (isBundle) args.others else args.c +: args.others
implMeth.invoke(implObj, implArgs.asInstanceOf[Seq[AnyRef]]: _*)
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 03826a3011..29a8e62b6e 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -616,8 +616,9 @@ trait Definitions extends api.StandardDefinitions {
def isMacroBundleType(tp: Type) = {
val isContextCompatible = macroBundleParamInfo(tp) != NoType
+ val hasSingleConstructor = !tp.declaration(nme.CONSTRUCTOR).isOverloaded
val nonAbstract = !tp.erasure.typeSymbol.isAbstractClass
- isContextCompatible && nonAbstract
+ isContextCompatible && hasSingleConstructor && nonAbstract
}
def isBlackboxMacroBundleType(tp: Type) =
diff --git a/test/files/neg/macro-bundle-abstract.check b/test/files/neg/macro-bundle-abstract.check
index 010d0768c9..3afd079521 100644
--- a/test/files/neg/macro-bundle-abstract.check
+++ b/test/files/neg/macro-bundle-abstract.check
@@ -1,4 +1,4 @@
-macro-bundle-abstract.scala:10: error: macro bundles must be concrete classes having a single `val c: Context` parameter
+macro-bundle-abstract.scala:10: error: macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter
def foo = macro Bundle.impl
^
one error found
diff --git a/test/files/neg/macro-bundle-overloaded.check b/test/files/neg/macro-bundle-overloaded.check
new file mode 100644
index 0000000000..fc94ff0000
--- /dev/null
+++ b/test/files/neg/macro-bundle-overloaded.check
@@ -0,0 +1,4 @@
+macro-bundle-overloaded.scala:11: error: macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter
+ def foo = macro Bundle.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-bundle-overloaded.scala b/test/files/neg/macro-bundle-overloaded.scala
new file mode 100644
index 0000000000..a4bc66f974
--- /dev/null
+++ b/test/files/neg/macro-bundle-overloaded.scala
@@ -0,0 +1,12 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.{Context => BlackboxContext}
+import scala.reflect.macros.whitebox.{Context => WhiteboxContext}
+
+class Bundle(val c: BlackboxContext) {
+ def this(c: WhiteboxContext) = this(c: BlackboxContext)
+ def impl = ???
+}
+
+object Macros {
+ def foo = macro Bundle.impl
+} \ No newline at end of file