From b747209b10793a88ce09f4b89d90dd4c50b05896 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 31 Aug 2013 21:44:34 +0200 Subject: no longer warns on calls to vampire macros As eloquently elaborated and cleverly named by Travis Brown, macros defined in structural types are useful: http://meta.plasm.us/posts/2013/07/12/vampire-methods-for-structural-types/. However, since such macros are on the intersection of a number of language features, as usual, there are bugs. This commit fixes an unwanted interaction of macros defined in structural types with the scala.language.reflectiveCalls guard. Since macro calls aren't going to be carried to runtime, there's no need to warn about them. --- test/files/run/macro-vampire-false-warning.check | 2 + test/files/run/macro-vampire-false-warning.flags | 1 + .../run/macro-vampire-false-warning/Macros_1.scala | 52 ++++++++++++++++++++++ .../run/macro-vampire-false-warning/Test_2.scala | 6 +++ 4 files changed, 61 insertions(+) create mode 100644 test/files/run/macro-vampire-false-warning.check create mode 100644 test/files/run/macro-vampire-false-warning.flags create mode 100644 test/files/run/macro-vampire-false-warning/Macros_1.scala create mode 100644 test/files/run/macro-vampire-false-warning/Test_2.scala (limited to 'test') diff --git a/test/files/run/macro-vampire-false-warning.check b/test/files/run/macro-vampire-false-warning.check new file mode 100644 index 0000000000..4792e70f33 --- /dev/null +++ b/test/files/run/macro-vampire-false-warning.check @@ -0,0 +1,2 @@ +2 +3 diff --git a/test/files/run/macro-vampire-false-warning.flags b/test/files/run/macro-vampire-false-warning.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/run/macro-vampire-false-warning.flags @@ -0,0 +1 @@ +-Xfatal-warnings \ No newline at end of file diff --git a/test/files/run/macro-vampire-false-warning/Macros_1.scala b/test/files/run/macro-vampire-false-warning/Macros_1.scala new file mode 100644 index 0000000000..2d384fbb85 --- /dev/null +++ b/test/files/run/macro-vampire-false-warning/Macros_1.scala @@ -0,0 +1,52 @@ +// As per http://meta.plasm.us/posts/2013/08/31/feeding-our-vampires/ + +import scala.annotation.StaticAnnotation +import scala.reflect.macros.Context +import scala.language.experimental.macros + +class body(tree: Any) extends StaticAnnotation + +object Macros { + def selFieldImpl(c: Context) = { + import c.universe._ + val field = c.macroApplication.symbol + val bodyAnn = field.annotations.filter(_.tpe <:< typeOf[body]).head + c.Expr[Any](bodyAnn.scalaArgs.head) + } + + def mkObjectImpl(c: Context)(xs: c.Expr[Any]*) = { + import c.universe._ + import Flag._ + // val kvps = xs.toList map { case q"${_}(${Literal(Constant(name: String))}).->[${_}]($value)" => name -> value } + val kvps = xs.map(_.tree).toList map { case Apply(TypeApply(Select(Apply(_, List(Literal(Constant(name: String)))), _), _), List(value)) => name -> value } + // val fields = kvps map { case (k, v) => q"@body($v) def ${TermName(k)} = macro Macros.selFieldImpl" } + val fields = kvps map { case (k, v) => DefDef( + Modifiers(MACRO, tpnme.EMPTY, List(Apply(Select(New(Ident(TypeName("body"))), nme.CONSTRUCTOR), List(v)))), + TermName(k), Nil, Nil, TypeTree(), Select(Ident(TermName("Macros")), TermName("selFieldImpl"))) } + // q"import scala.language.experimental.macros; class Workaround { ..$fields }; new Workaround{}" + c.Expr[Any](Block( + List( + Import(Select(Select(Ident(TermName("scala")), TermName("language")), TermName("experimental")), List(ImportSelector(TermName("macros"), 51, TermName("macros"), 51))), + ClassDef( + NoMods, TypeName("Workaround"), Nil, + Template( + List(Select(Ident(TermName("scala")), TypeName("AnyRef"))), noSelfType, + DefDef( + NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), + Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))) + +: fields)), + ClassDef( + Modifiers(FINAL), TypeName("$anon"), Nil, + Template( + List(Ident(TypeName("Workaround"))), noSelfType, + List( + DefDef( + NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), + Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))))))), + Apply(Select(New(Ident(TypeName("$anon"))), nme.CONSTRUCTOR), List()))) + } +} + +object mkObject { + def apply(xs: Any*) = macro Macros.mkObjectImpl +} diff --git a/test/files/run/macro-vampire-false-warning/Test_2.scala b/test/files/run/macro-vampire-false-warning/Test_2.scala new file mode 100644 index 0000000000..6e44b68635 --- /dev/null +++ b/test/files/run/macro-vampire-false-warning/Test_2.scala @@ -0,0 +1,6 @@ +object Test extends App { + val foo = mkObject("x" -> "2", "y" -> 3) + println(foo.x) + println(foo.y) + // println(foo.z) => will result in a compilation error +} \ No newline at end of file -- cgit v1.2.3