summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-22 22:02:34 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-04-23 17:55:35 +0200
commitd4b8d8deefcdd9144ef39d1456b03aa693f93ff7 (patch)
treef634abc7f093d2154d583f1b268c4c7c3ed20001 /src
parentf54e5c8bbdd719b5c9375c64c2f66b841984456e (diff)
downloadscala-d4b8d8deefcdd9144ef39d1456b03aa693f93ff7.tar.gz
scala-d4b8d8deefcdd9144ef39d1456b03aa693f93ff7.tar.bz2
scala-d4b8d8deefcdd9144ef39d1456b03aa693f93ff7.zip
interop between manifests and tags
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala11
-rw-r--r--src/library/scala/reflect/DummyMirror.scala9
-rw-r--r--src/library/scala/reflect/TagInterop.scala34
-rw-r--r--src/library/scala/reflect/api/TreeBuildUtil.scala18
-rw-r--r--src/library/scala/reflect/makro/internal/Utils.scala12
-rw-r--r--src/library/scala/reflect/package.scala4
7 files changed, 89 insertions, 2 deletions
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index 4ce6afe1f3..a55efea2e6 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -564,6 +564,7 @@ trait StdNames {
val argv : NameType = "argv"
val arrayClass: NameType = "arrayClass"
val arrayElementClass: NameType = "arrayElementClass"
+ val arrayTagToClassManifest: NameType = "arrayTagToClassManifest"
val arrayValue: NameType = "arrayValue"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
@@ -581,6 +582,7 @@ trait StdNames {
val checkInitialized: NameType = "checkInitialized"
val classOf: NameType = "classOf"
val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure
+ val concreteTypeTagToManifest: NameType = "concreteTypeTagToManifest"
val conforms: NameType = "conforms"
val copy: NameType = "copy"
val definitions: NameType = "definitions"
@@ -629,6 +631,7 @@ trait StdNames {
val macroContext : NameType = "c"
val main: NameType = "main"
val manifest: NameType = "manifest"
+ val manifestToConcreteTypeTag: NameType = "manifestToConcreteTypeTag"
val map: NameType = "map"
val materializeArrayTag: NameType = "materializeArrayTag"
val materializeClassTag: NameType = "materializeClassTag"
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index fadb691cb6..1612253dd6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1265,7 +1265,16 @@ trait Implicits {
}
}
- mot(tp, Nil, Nil)
+ val tagInScope =
+ if (full) context.withMacrosDisabled(resolveTypeTag(pos, ReflectMirrorPrefix.tpe, tp, true))
+ else context.withMacrosDisabled(resolveArrayTag(pos, tp))
+ if (tagInScope.isEmpty) mot(tp, Nil, Nil)
+ else {
+ val interop =
+ if (full) gen.mkMethodCall(ReflectPackage, nme.concreteTypeTagToManifest, List(tp), List(tagInScope))
+ else gen.mkMethodCall(ReflectPackage, nme.arrayTagToClassManifest, List(tp), List(tagInScope))
+ wrapResult(interop)
+ }
}
def wrapResult(tree: Tree): SearchResult =
diff --git a/src/library/scala/reflect/DummyMirror.scala b/src/library/scala/reflect/DummyMirror.scala
index 276237fce4..f40531e856 100644
--- a/src/library/scala/reflect/DummyMirror.scala
+++ b/src/library/scala/reflect/DummyMirror.scala
@@ -500,6 +500,7 @@ class DummyMirror(cl: ClassLoader) extends api.Mirror {
type TreeGenTree = global.Tree
type TreeGenType = global.Type
type TreeGenSymbol = global.Symbol
+ type TreeGenName = global.Name
def mkAttributedQualifier(tpe: TreeGenType): TreeGenTree = notSupported()
def mkAttributedQualifier(tpe: TreeGenType, termSym: TreeGenSymbol): TreeGenTree = notSupported()
def mkAttributedRef(pre: TreeGenType, sym: TreeGenSymbol): TreeGenTree = notSupported()
@@ -507,6 +508,14 @@ class DummyMirror(cl: ClassLoader) extends api.Mirror {
def mkAttributedThis(sym: TreeGenSymbol): TreeGenTree = notSupported()
def mkAttributedIdent(sym: TreeGenSymbol): TreeGenTree = notSupported()
def mkAttributedSelect(qual: TreeGenTree, sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkMethodCall(target: TreeGenTree,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenTree,method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(target: TreeGenTree,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(method: TreeGenSymbol,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkNullaryCall(method: TreeGenSymbol,targs: List[TreeGenType]): TreeGenTree = notSupported()
}
// Members declared in scala.reflect.api.TreePrinters
diff --git a/src/library/scala/reflect/TagInterop.scala b/src/library/scala/reflect/TagInterop.scala
new file mode 100644
index 0000000000..6c6bfcc2f2
--- /dev/null
+++ b/src/library/scala/reflect/TagInterop.scala
@@ -0,0 +1,34 @@
+package scala.reflect
+
+import scala.runtime.ScalaRunTime._
+import mirror._
+import definitions._
+
+object TagInterop {
+ def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = {
+ val erasure = arrayElementClass(tag)
+ if (erasure.isArray) {
+ val elementClass = arrayElementClass(erasure)
+ val elementManifest = arrayTagToClassManifest(ClassTag(elementClass))
+ ClassManifest.arrayType(elementManifest).asInstanceOf[ClassManifest[T]]
+ } else {
+ ClassManifest.fromClass(erasure.asInstanceOf[Class[T]])
+ }
+ }
+
+ def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = {
+ // todo. reproduce manifest generation code here. toolboxes are too slow.
+ val implicitly = PredefModule.typeSignature.member(newTermName("implicitly"))
+ val taggedTpe = appliedType(staticClass("scala.reflect.Manifest").asTypeConstructor, List(tag.tpe))
+ val materializer = TypeApply(Ident(implicitly), List(TypeTree(taggedTpe)))
+ try mkToolBox().runExpr(materializer).asInstanceOf[Manifest[T]]
+ catch { case ex: Throwable => Manifest.classType(tag.erasure).asInstanceOf[Manifest[T]] }
+ }
+
+ def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = {
+ val tpe =
+ if (tag.typeArguments.isEmpty) classToType(tag.erasure)
+ else appliedType(classToType(tag.erasure).typeConstructor, tag.typeArguments map (manifestToConcreteTypeTag(_)) map (_.tpe))
+ ConcreteTypeTag(tpe, tag.erasure)
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/TreeBuildUtil.scala b/src/library/scala/reflect/api/TreeBuildUtil.scala
index 4f510337c2..87790b3812 100644
--- a/src/library/scala/reflect/api/TreeBuildUtil.scala
+++ b/src/library/scala/reflect/api/TreeBuildUtil.scala
@@ -138,4 +138,22 @@ trait AbsTreeGen {
/** Builds a typed Select with an underlying symbol. */
def mkAttributedSelect(qual: Tree, sym: Symbol): Tree
+
+ /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
+ * There are a number of variations.
+ *
+ * @param receiver symbol of the method receiver
+ * @param methodName name of the method to call
+ * @param targs type arguments (if Nil, no TypeApply node will be generated)
+ * @param args value arguments
+ * @return the newly created trees.
+ */
+ def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(method: Symbol, args: List[Tree]): Tree
+ def mkMethodCall(target: Tree, args: List[Tree]): Tree
+ def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
+ def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
+ def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
}
diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala
index a8a2c98715..3af58e1c88 100644
--- a/src/library/scala/reflect/makro/internal/Utils.scala
+++ b/src/library/scala/reflect/makro/internal/Utils.scala
@@ -97,12 +97,22 @@ package internal {
val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name)
Select(ref, coreTags(coreTpe))
case _ =>
- translatingReificationErrors(materializer)
+ val manifestInScope = nonSyntheticManifestInScope(tpe)
+ if (manifestInScope.isEmpty) translatingReificationErrors(materializer)
+ else gen.mkMethodCall(staticModule("scala.reflect.package"), newTermName("manifestToConcreteTypeTag"), List(tpe), List(manifestInScope))
}
try c.typeCheck(result)
catch { case terr @ c.TypeError(pos, msg) => failTag(terr) }
}
+ private def nonSyntheticManifestInScope(tpe: Type) = {
+ val ManifestClass = staticClass("scala.reflect.Manifest")
+ val ManifestModule = staticModule("scala.reflect.Manifest")
+ val manifest = c.inferImplicitValue(appliedType(ManifestClass.asTypeConstructor, List(tpe)))
+ val notOk = manifest.isEmpty || (manifest exists (sub => sub.symbol != null && (sub.symbol == ManifestModule || sub.symbol.owner == ManifestModule)))
+ if (notOk) EmptyTree else manifest
+ }
+
def materializeExpr(prefix: Tree, expr: Tree): Tree = {
val result = translatingReificationErrors(c.reifyTree(prefix, expr))
try c.typeCheck(result)
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 0e6350183f..38a144cd49 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -63,4 +63,8 @@ package object reflect {
// ClassTag object is defined separately from the mirror
lazy val TypeTag = scala.reflect.mirror.TypeTag
lazy val ConcreteTypeTag = scala.reflect.mirror.ConcreteTypeTag
+
+ def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = TagInterop.arrayTagToClassManifest[T](tag)
+ def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = TagInterop.concreteTypeTagToManifest[T](tag)
+ def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = TagInterop.manifestToConcreteTypeTag[T](tag)
}