diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-09-23 14:07:22 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-09-28 14:21:45 +0200 |
commit | a6b81ac12a45866e97d30133c12dee775b93ea39 (patch) | |
tree | 89020413a56a36ebde3a02b99e4ec367f81cf33c /test/files | |
parent | 4e87654a9187fc65e5971580f4e25589fff052b9 (diff) | |
download | scala-a6b81ac12a45866e97d30133c12dee775b93ea39.tar.gz scala-a6b81ac12a45866e97d30133c12dee775b93ea39.tar.bz2 scala-a6b81ac12a45866e97d30133c12dee775b93ea39.zip |
SI-6417 correctly reifies non-value types
If we're reifying non-value types (e.g. MethodTypes), we can't use them
as type arguments for TypeTag/WeakTypeTag factory methods, otherwise
the macro expansion won't typecheck:
http://groups.google.com/group/scala-internals/browse_thread/thread/2d7bb85bfcdb2e2
This situation is impossible if one uses only reify and type tags, but
c.reifyTree and c.reifyType exposes in the macro API let anyone feed
anything into the reifier.
Therefore I now check the tpe that is about to be used in TypeApply
wrapping TypeTag/WeakTypeTag factory methods and replace it with AnyTpe
if it doesn't fit.
Diffstat (limited to 'test/files')
-rw-r--r-- | test/files/run/macro-reify-type.check | 1 | ||||
-rw-r--r-- | test/files/run/macro-reify-type.flags | 1 | ||||
-rw-r--r-- | test/files/run/macro-reify-type/Macros_1.scala | 27 | ||||
-rw-r--r-- | test/files/run/macro-reify-type/Test_2.scala | 21 |
4 files changed, 50 insertions, 0 deletions
diff --git a/test/files/run/macro-reify-type.check b/test/files/run/macro-reify-type.check new file mode 100644 index 0000000000..ea5e70e10d --- /dev/null +++ b/test/files/run/macro-reify-type.check @@ -0,0 +1 @@ +[B, That](f: Int => B)(implicit bf: scala.collection.generic.CanBuildFrom[List[Int],B,That])That
\ No newline at end of file diff --git a/test/files/run/macro-reify-type.flags b/test/files/run/macro-reify-type.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-reify-type.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-reify-type/Macros_1.scala b/test/files/run/macro-reify-type/Macros_1.scala new file mode 100644 index 0000000000..aeec9fc97c --- /dev/null +++ b/test/files/run/macro-reify-type/Macros_1.scala @@ -0,0 +1,27 @@ +import scala.reflect.macros.Context +import scala.reflect.runtime.{universe => ru} + +object StaticReflect { + def method[A](name: String): ru.Type = macro methodImpl[A] + + def methodImpl[A: c.WeakTypeTag](c: Context)(name: c.Expr[String]): c.Expr[ru.Type] = { + import c.universe._ + + val nameName: TermName = name.tree match { + case Literal(Constant(str: String)) => newTermName(str) + case _ => c.error(c.enclosingPosition, s"Method name not constant.") ; return reify(ru.NoType) + } + val clazz = weakTypeOf[A] + + clazz member nameName match { + case NoSymbol => c.error(c.enclosingPosition, s"No member called $nameName in $clazz.") ; reify(ru.NoType) + case member => + val mtpe = member typeSignatureIn clazz + val mtag = c.reifyType(c.runtimeUniverse, Select(c.runtimeUniverse, newTermName("rootMirror")), mtpe) + val mtree = Select(mtag, newTermName("tpe")) + + c.Expr[ru.Type](mtree) + } + } + +} diff --git a/test/files/run/macro-reify-type/Test_2.scala b/test/files/run/macro-reify-type/Test_2.scala new file mode 100644 index 0000000000..9beaf98681 --- /dev/null +++ b/test/files/run/macro-reify-type/Test_2.scala @@ -0,0 +1,21 @@ +import StaticReflect._ + +object Test extends App { + //println(method[List[Int]]("distinct")) + println(method[List[Int]]("map")) + //val $u: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe; + //val $m: $u.Mirror = scala.reflect.runtime.universe.rootMirror; + //import $u._, $m._, Flag._ + //val tpe = { + // val symdef$B2 = build.newNestedSymbol(build.selectTerm(staticClass("scala.collection.TraversableLike"), "map"), newTypeName("B"), NoPosition, DEFERRED | PARAM, false); + // val symdef$That2 = build.newNestedSymbol(build.selectTerm(staticClass("scala.collection.TraversableLike"), "map"), newTypeName("That"), NoPosition, DEFERRED | PARAM, false); + // val symdef$f2 = build.newNestedSymbol(build.selectTerm(staticClass("scala.collection.TraversableLike"), "map"), newTermName("f"), NoPosition, PARAM, false); + // val symdef$bf2 = build.newNestedSymbol(build.selectTerm(staticClass("scala.collection.TraversableLike"), "map"), newTermName("bf"), NoPosition, IMPLICIT | PARAM, false); + // build.setTypeSignature(symdef$B2, TypeBounds(staticClass("scala.Nothing").asType.toTypeConstructor, staticClass("scala.Any").asType.toTypeConstructor)); + // build.setTypeSignature(symdef$That2, TypeBounds(staticClass("scala.Nothing").asType.toTypeConstructor, staticClass("scala.Any").asType.toTypeConstructor)); + // build.setTypeSignature(symdef$f2, TypeRef(ThisType(staticPackage("scala").asModule.moduleClass), staticClass("scala.Function1"), List(staticClass("scala.Int").asType.toTypeConstructor, TypeRef(NoPrefix, symdef$B2, List())))); + // build.setTypeSignature(symdef$bf2, TypeRef(ThisType(staticPackage("scala.collection.generic").asModule.moduleClass), staticClass("scala.collection.generic.CanBuildFrom"), List(TypeRef(ThisType(staticPackage("scala.collection.immutable").asModule.moduleClass), staticClass("scala.collection.immutable.List"), List(staticClass("scala.Int").asType.toTypeConstructor)), TypeRef(NoPrefix, symdef$B2, List()), TypeRef(NoPrefix, symdef$That2, List())))); + // PolyType(List(symdef$B2, symdef$That2), MethodType(List(symdef$f2), MethodType(List(symdef$bf2), TypeRef(NoPrefix, symdef$That2, List())))) + //} + //println(tpe) +}
\ No newline at end of file |