diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-03-10 10:56:36 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-03-10 10:56:36 +0100 |
commit | 40b7832823d5e1cc39397b8960e62e0283bb0502 (patch) | |
tree | 3cdbd1e0a480d6258d9cb7a4017379ea03bbc86b | |
parent | 79ecd92f76df859cfde4b813ab9530d5352e48ca (diff) | |
parent | 384322b1cb824b0ff8a2a15a75d33d6a7cf8e85c (diff) | |
download | scala-40b7832823d5e1cc39397b8960e62e0283bb0502.tar.gz scala-40b7832823d5e1cc39397b8960e62e0283bb0502.tar.bz2 scala-40b7832823d5e1cc39397b8960e62e0283bb0502.zip |
Merge pull request #3606 from xeno-by/ticket/8375
SI-8375 saner binary incompat errors for macros
19 files changed, 87 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 2043eb5d5d..d439bb5603 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -725,11 +725,18 @@ trait ContextErrors { NormalTypeError(expandee, "too many argument lists for " + fun) } - def MacroIncompatibleEngineError(macroEngine: String) = { - val message = s"macro cannot be expanded, because it was compiled by an incompatible macro engine $macroEngine" + private def MacroIncompatibleEngineError(friendlyMessage: String, internalMessage: String) = { + def debugDiagnostic = s"(internal diagnostic: $internalMessage)" + val message = if (macroDebugLite || macroDebugVerbose) s"$friendlyMessage $debugDiagnostic" else friendlyMessage issueNormalTypeError(lastTreeToTyper, message) } + def MacroCantExpand210xMacrosError(internalMessage: String) = + MacroIncompatibleEngineError("can't expand macros compiled by previous versions of Scala", internalMessage) + + def MacroCantExpandIncompatibleMacrosError(internalMessage: String) = + MacroIncompatibleEngineError("macro cannot be expanded, because it was compiled by an incompatible macro engine", internalMessage) + case object MacroExpansionException extends Exception with scala.util.control.ControlThrowable protected def macroExpansionError(expandee: Tree, msg: String, pos: Position = NoPosition) = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 677c94e063..9cf92ca5b9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -224,7 +224,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { val Apply(_, pickledPayload) = wrapped val payload = pickledPayload.map{ case Assign(k, v) => (unpickleAtom(k), unpickleAtom(v)) }.toMap - def fail(msg: String) = abort(s"bad macro impl binding: $msg") + import typer.TyperErrorGen._ + def fail(msg: String) = MacroCantExpandIncompatibleMacrosError(msg) def unpickle[T](field: String, clazz: Class[T]): T = { def failField(msg: String) = fail(s"$field $msg") if (!payload.contains(field)) failField("is supposed to be there") @@ -236,8 +237,9 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { raw.asInstanceOf[T] } + if (!payload.contains("macroEngine")) MacroCantExpand210xMacrosError("macroEngine field not found") val macroEngine = unpickle("macroEngine", classOf[String]) - if (self.macroEngine != macroEngine) typer.TyperErrorGen.MacroIncompatibleEngineError(macroEngine) + if (self.macroEngine != macroEngine) MacroCantExpandIncompatibleMacrosError(s"expected = ${self.macroEngine}, actual = $macroEngine") val isBundle = unpickle("isBundle", classOf[Boolean]) val isBlackbox = unpickle("isBlackbox", classOf[Boolean]) diff --git a/test/files/lib/macro210.jar.desired.sha1 b/test/files/lib/macro210.jar.desired.sha1 new file mode 100644 index 0000000000..ff87a55129 --- /dev/null +++ b/test/files/lib/macro210.jar.desired.sha1 @@ -0,0 +1 @@ +3794ec22d9b27f2b179bd34e9b46db771b934ec3 ?macro210.jar diff --git a/test/files/neg/macro-incompatible-macro-engine-a.check b/test/files/neg/macro-incompatible-macro-engine-a.check new file mode 100644 index 0000000000..8ae08bd164 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-a.check @@ -0,0 +1,7 @@ +Test_3.scala:2: error: macro cannot be expanded, because it was compiled by an incompatible macro engine + Macros.foo + ^ +Test_3.scala:3: error: macro cannot be expanded, because it was compiled by an incompatible macro engine + Macros.foo + ^ +two errors found diff --git a/test/files/neg/macro-incompatible-macro-engine/Macros_2.flags b/test/files/neg/macro-incompatible-macro-engine-a/Macros_2.flags index 966df731d0..966df731d0 100644 --- a/test/files/neg/macro-incompatible-macro-engine/Macros_2.flags +++ b/test/files/neg/macro-incompatible-macro-engine-a/Macros_2.flags diff --git a/test/files/neg/macro-incompatible-macro-engine/Macros_2.scala b/test/files/neg/macro-incompatible-macro-engine-a/Macros_2.scala index 39708eee49..39708eee49 100644 --- a/test/files/neg/macro-incompatible-macro-engine/Macros_2.scala +++ b/test/files/neg/macro-incompatible-macro-engine-a/Macros_2.scala diff --git a/test/files/neg/macro-incompatible-macro-engine/Plugin_1.scala b/test/files/neg/macro-incompatible-macro-engine-a/Plugin_1.scala index 44ed91d2fb..44ed91d2fb 100644 --- a/test/files/neg/macro-incompatible-macro-engine/Plugin_1.scala +++ b/test/files/neg/macro-incompatible-macro-engine-a/Plugin_1.scala diff --git a/test/files/neg/macro-incompatible-macro-engine/Test_3.scala b/test/files/neg/macro-incompatible-macro-engine-a/Test_3.scala index 7e4fae5236..7e4fae5236 100644 --- a/test/files/neg/macro-incompatible-macro-engine/Test_3.scala +++ b/test/files/neg/macro-incompatible-macro-engine-a/Test_3.scala diff --git a/test/files/neg/macro-incompatible-macro-engine/scalac-plugin.xml b/test/files/neg/macro-incompatible-macro-engine-a/scalac-plugin.xml index 42b9cdd75d..42b9cdd75d 100644 --- a/test/files/neg/macro-incompatible-macro-engine/scalac-plugin.xml +++ b/test/files/neg/macro-incompatible-macro-engine-a/scalac-plugin.xml diff --git a/test/files/neg/macro-incompatible-macro-engine-b.check b/test/files/neg/macro-incompatible-macro-engine-b.check new file mode 100644 index 0000000000..2a7510cf86 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b.check @@ -0,0 +1,7 @@ +Test_3.scala:2: error: macro cannot be expanded, because it was compiled by an incompatible macro engine (internal diagnostic: expected = v7.0 (implemented in Scala 2.11.0-M8), actual = vxxx (implemented in the incompatibleMacroEngine plugin)) + Macros.foo + ^ +Test_3.scala:3: error: macro cannot be expanded, because it was compiled by an incompatible macro engine (internal diagnostic: expected = v7.0 (implemented in Scala 2.11.0-M8), actual = vxxx (implemented in the incompatibleMacroEngine plugin)) + Macros.foo + ^ +two errors found diff --git a/test/files/neg/macro-incompatible-macro-engine-b.flags b/test/files/neg/macro-incompatible-macro-engine-b.flags new file mode 100644 index 0000000000..037a693bbd --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b.flags @@ -0,0 +1 @@ +-Ymacro-debug-lite
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.flags b/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.flags new file mode 100644 index 0000000000..966df731d0 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.flags @@ -0,0 +1 @@ +-Xplugin:.
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.scala b/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.scala new file mode 100644 index 0000000000..39708eee49 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b/Macros_2.scala @@ -0,0 +1,7 @@ +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +object Macros { + def impl(c: Context) = c.universe.Literal(c.universe.Constant(())) + def foo: Unit = macro impl +}
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-b/Plugin_1.scala b/test/files/neg/macro-incompatible-macro-engine-b/Plugin_1.scala new file mode 100644 index 0000000000..44ed91d2fb --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b/Plugin_1.scala @@ -0,0 +1,35 @@ +package incompatibleMacroEngine + +import scala.tools.nsc.Global +import scala.tools.nsc.plugins.{Plugin => NscPlugin} + +class Plugin(val global: Global) extends NscPlugin { + import global._ + import analyzer._ + + val name = "incompatibleMacroEngine" + val description = "A sample analyzer plugin that crafts a macro impl binding with a non-standard macro engine." + val components = Nil + addMacroPlugin(MacroPlugin) + + object MacroPlugin extends MacroPlugin { + def fixupBinding(tree: Tree) = new Transformer { + override def transform(tree: Tree) = { + tree match { + case Literal(const @ Constant(x)) if tree.tpe == null => tree setType ConstantType(const) + case _ if tree.tpe == null => tree setType NoType + case _ => ; + } + super.transform(tree) + } + }.transform(tree) + + override def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Option[Tree] = { + val result = standardTypedMacroBody(typer, ddef) + val List(AnnotationInfo(atp, List(Apply(nucleus, _ :: others)), Nil)) = ddef.symbol.annotations + val updatedBinding = Apply(nucleus, Assign(Literal(Constant("macroEngine")), Literal(Constant("vxxx (implemented in the incompatibleMacroEngine plugin)"))) :: others) + ddef.symbol.setAnnotations(List(AnnotationInfo(atp, List(fixupBinding(updatedBinding)), Nil))) + Some(result) + } + } +}
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-b/Test_3.scala b/test/files/neg/macro-incompatible-macro-engine-b/Test_3.scala new file mode 100644 index 0000000000..7e4fae5236 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b/Test_3.scala @@ -0,0 +1,4 @@ +object Test extends App { + Macros.foo + Macros.foo +}
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-b/scalac-plugin.xml b/test/files/neg/macro-incompatible-macro-engine-b/scalac-plugin.xml new file mode 100644 index 0000000000..42b9cdd75d --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-b/scalac-plugin.xml @@ -0,0 +1,4 @@ +<plugin> + <name>incompatible-macro-engine</name> + <classname>incompatibleMacroEngine.Plugin</classname> +</plugin>
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine-c.check b/test/files/neg/macro-incompatible-macro-engine-c.check new file mode 100644 index 0000000000..fb6c59ab7c --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-c.check @@ -0,0 +1,4 @@ +macro-incompatible-macro-engine-c.scala:2: error: can't expand macros compiled by previous versions of Scala + MacroLibCompiledByScala210x.foo + ^ +one error found diff --git a/test/files/neg/macro-incompatible-macro-engine-c.scala b/test/files/neg/macro-incompatible-macro-engine-c.scala new file mode 100644 index 0000000000..037ac5f456 --- /dev/null +++ b/test/files/neg/macro-incompatible-macro-engine-c.scala @@ -0,0 +1,3 @@ +object Test extends App { + MacroLibCompiledByScala210x.foo +}
\ No newline at end of file diff --git a/test/files/neg/macro-incompatible-macro-engine.check b/test/files/neg/macro-incompatible-macro-engine.check deleted file mode 100644 index 1d582e5ed6..0000000000 --- a/test/files/neg/macro-incompatible-macro-engine.check +++ /dev/null @@ -1,7 +0,0 @@ -Test_3.scala:2: error: macro cannot be expanded, because it was compiled by an incompatible macro engine vxxx (implemented in the incompatibleMacroEngine plugin) - Macros.foo - ^ -Test_3.scala:3: error: macro cannot be expanded, because it was compiled by an incompatible macro engine vxxx (implemented in the incompatibleMacroEngine plugin) - Macros.foo - ^ -two errors found |