diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-01-12 12:01:12 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-01-12 18:03:51 +0100 |
commit | e36888c3d953048483ccea9a95d5984b54ad6ebc (patch) | |
tree | a6ba3268a238acb5310dcfdefcf8234c0b7f6a77 | |
parent | 3a689f5c426436aea716567625fd6167e57bef92 (diff) | |
download | scala-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.
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 |