summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/runtime
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-30 10:01:31 +0300
committerEugene Burmako <xeno.by@gmail.com>2014-02-14 23:51:22 +0100
commit114c99691674873393223a11a9aa9168c3f41d77 (patch)
treed855c67a565faf4dbe414cc8f1a1aaff68a8df79 /src/reflect/scala/reflect/runtime
parent27805570cbf130260eab04fe1491e58fa95e8108 (diff)
downloadscala-114c99691674873393223a11a9aa9168c3f41d77.tar.gz
scala-114c99691674873393223a11a9aa9168c3f41d77.tar.bz2
scala-114c99691674873393223a11a9aa9168c3f41d77.zip
establishes scala.reflect.api#internal
Reflection API exhibits a tension inherent to experimental things: on the one hand we want it to grow into a beautiful and robust API, but on the other hand we have to deal with immaturity of underlying mechanisms by providing not very pretty solutions to enable important use cases. In Scala 2.10, which was our first stab at reflection API, we didn't have a systematic approach to dealing with this tension, sometimes exposing too much of internals (e.g. Symbol.deSkolemize) and sometimes exposing too little (e.g. there's still no facility to change owners, to do typing transformations, etc). This resulted in certain confusion with some internal APIs living among public ones, scaring the newcomers, and some internal APIs only available via casting, which requires intimate knowledge of the compiler and breaks compatibility guarantees. This led to creation of the `internal` API module for the reflection API, which provides advanced APIs necessary for macros that push boundaries of the state of the art, clearly demarcating them from the more or less straightforward rest and providing compatibility guarantees on par with the rest of the reflection API. This commit does break source compatibility with reflection API in 2.10, but the next commit is going to introduce a strategy of dealing with that.
Diffstat (limited to 'src/reflect/scala/reflect/runtime')
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala42
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala4
2 files changed, 40 insertions, 6 deletions
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index 85c56bc4bb..b5446694ed 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -2,18 +2,22 @@ package scala
package reflect
package runtime
+import scala.reflect.internal.{TreeInfo, SomePhase}
+import scala.reflect.internal.{SymbolTable => InternalSymbolTable}
+import scala.reflect.runtime.{SymbolTable => RuntimeSymbolTable}
+import scala.reflect.api.{TreeCreator, TypeCreator, Universe}
+
/** An implementation of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders.
*
* Should not be instantiated directly, use [[scala.reflect.runtime.universe]] instead.
*
* @contentDiagram hideNodes "*Api" "*Extractor"
*/
-class JavaUniverse extends internal.SymbolTable with JavaUniverseForce with ReflectSetup with runtime.SymbolTable { self =>
+class JavaUniverse extends InternalSymbolTable with JavaUniverseForce with ReflectSetup with RuntimeSymbolTable { self =>
override def inform(msg: String): Unit = log(msg)
- def picklerPhase = internal.SomePhase
- def erasurePhase = internal.SomePhase
-
+ def picklerPhase = SomePhase
+ def erasurePhase = SomePhase
lazy val settings = new Settings
private val isLogging = sys.props contains "scala.debug.reflect"
@@ -26,10 +30,38 @@ class JavaUniverse extends internal.SymbolTable with JavaUniverseForce with Refl
def currentFreshNameCreator = globalFreshNameCreator
+ override lazy val internal: Internal = new SymbolTableInternal {
+ override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: Universe # TypeTag[T]): Manifest[T] = {
+ // SI-6239: make this conversion more precise
+ val mirror = mirror0.asInstanceOf[Mirror]
+ val runtimeClass = mirror.runtimeClass(tag.in(mirror).tpe)
+ Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]]
+ }
+ override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): Universe # TypeTag[T] =
+ TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator {
+ def apply[U <: Universe with Singleton](mirror: scala.reflect.api.Mirror[U]): U # Type = {
+ mirror.universe match {
+ case ju: JavaUniverse =>
+ val jm = mirror.asInstanceOf[ju.Mirror]
+ val sym = jm.classSymbol(manifest.runtimeClass)
+ val tpe =
+ if (manifest.typeArguments.isEmpty) sym.toType
+ else {
+ val tags = manifest.typeArguments map (targ => ju.internal.manifestToTypeTag(jm, targ))
+ ju.appliedType(sym.toTypeConstructor, tags map (_.in(jm).tpe))
+ }
+ tpe.asInstanceOf[U # Type]
+ case u =>
+ u.internal.manifestToTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe
+ }
+ }
+ })
+ }
+
// can't put this in runtime.Trees since that's mixed with Global in ReflectGlobal, which has the definition from internal.Trees
object treeInfo extends {
val global: JavaUniverse.this.type = JavaUniverse.this
- } with internal.TreeInfo
+ } with TreeInfo
init()
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 0fcf215580..be8a2865d3 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -26,11 +26,12 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
TypeTag.Null.tpe
this.settings
+ this.internal
this.treeInfo
this.rootMirror
- this.treeBuild
this.traceSymbols
this.perRunCaches
+ this.treeBuild
this.FreshNameExtractor
this.FixedMirrorTreeCreator
this.FixedMirrorTypeCreator
@@ -279,6 +280,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.ReflectPackage
definitions.ReflectApiPackage
definitions.ReflectRuntimePackage
+ definitions.UniverseClass
definitions.PartialManifestModule
definitions.FullManifestClass
definitions.FullManifestModule