diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-01-30 10:01:31 +0300 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-02-14 23:51:22 +0100 |
commit | 114c99691674873393223a11a9aa9168c3f41d77 (patch) | |
tree | d855c67a565faf4dbe414cc8f1a1aaff68a8df79 /src/reflect/scala/reflect/runtime | |
parent | 27805570cbf130260eab04fe1491e58fa95e8108 (diff) | |
download | scala-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.scala | 42 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaUniverseForce.scala | 4 |
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 |