summaryrefslogtreecommitdiff
path: root/src/library/scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-12 01:59:46 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-04-12 02:04:14 +0200
commit814cf34fb00f9ccb001249f4b3445ebc4f9942c9 (patch)
tree24dd54da571d27f10b0c482a6e08932c318fd7b2 /src/library/scala
parentdb3056f11730da19e4e56f09f12e300bda62f57c (diff)
downloadscala-814cf34fb00f9ccb001249f4b3445ebc4f9942c9.tar.gz
scala-814cf34fb00f9ccb001249f4b3445ebc4f9942c9.tar.bz2
scala-814cf34fb00f9ccb001249f4b3445ebc4f9942c9.zip
Next generation of macros
Implements SIP 16: Self-cleaning macros: http://bit.ly/wjjXTZ Features: * Macro defs * Reification * Type tags * Manifests aliased to type tags * Extended reflection API * Several hundred tests * 1111 changed files Not yet implemented: * Reification of refined types * Expr.value splicing * Named and default macro expansions * Intricacies of interaction between macros and implicits * Emission of debug information for macros (compliant with JSR-45) Dedicated to Yuri Alekseyevich Gagarin
Diffstat (limited to 'src/library/scala')
-rw-r--r--src/library/scala/Predef.scala29
-rw-r--r--src/library/scala/collection/mutable/ArrayBuilder.scala18
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala10
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala2
-rw-r--r--src/library/scala/collection/mutable/WrappedArrayBuilder.scala14
-rw-r--r--src/library/scala/reflect/ArrayTags.scala19
-rw-r--r--src/library/scala/reflect/ClassManifest.scala263
-rw-r--r--src/library/scala/reflect/ClassTags.scala158
-rw-r--r--src/library/scala/reflect/Manifest.scala302
-rw-r--r--src/library/scala/reflect/NoManifest.scala15
-rw-r--r--src/library/scala/reflect/OptManifest.scala17
-rw-r--r--src/library/scala/reflect/ReflectionUtils.scala26
-rw-r--r--src/library/scala/reflect/TagMaterialization.scala154
-rw-r--r--src/library/scala/reflect/api/Attachments.scala16
-rw-r--r--src/library/scala/reflect/api/ClassLoaders.scala16
-rw-r--r--src/library/scala/reflect/api/Exprs.scala48
-rw-r--r--src/library/scala/reflect/api/FreeVars.scala42
-rw-r--r--src/library/scala/reflect/api/Importers.scala19
-rw-r--r--src/library/scala/reflect/api/Mirror.scala17
-rw-r--r--src/library/scala/reflect/api/Positions.scala215
-rw-r--r--src/library/scala/reflect/api/Reporters.scala65
-rw-r--r--src/library/scala/reflect/api/RuntimeTypes.scala20
-rwxr-xr-xsrc/library/scala/reflect/api/Scopes.scala9
-rwxr-xr-xsrc/library/scala/reflect/api/StandardDefinitions.scala68
-rw-r--r--src/library/scala/reflect/api/StandardNames.scala156
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala61
-rw-r--r--src/library/scala/reflect/api/ToolBoxes.scala90
-rw-r--r--src/library/scala/reflect/api/TreeBuildUtil.scala111
-rw-r--r--src/library/scala/reflect/api/TreePrinters.scala6
-rw-r--r--src/library/scala/reflect/api/Trees.scala178
-rw-r--r--src/library/scala/reflect/api/TypeTags.scala193
-rwxr-xr-xsrc/library/scala/reflect/api/Types.scala91
-rwxr-xr-xsrc/library/scala/reflect/api/Universe.scala79
-rw-r--r--src/library/scala/reflect/macro/Context.scala36
-rw-r--r--src/library/scala/reflect/makro/Aliases.scala26
-rw-r--r--src/library/scala/reflect/makro/CapturedVariables.scala20
-rw-r--r--src/library/scala/reflect/makro/Context.scala59
-rw-r--r--src/library/scala/reflect/makro/Enclosures.scala53
-rw-r--r--src/library/scala/reflect/makro/Infrastructure.scala73
-rw-r--r--src/library/scala/reflect/makro/Names.scala14
-rw-r--r--src/library/scala/reflect/makro/Reifiers.scala82
-rw-r--r--src/library/scala/reflect/makro/Reporters.scala39
-rw-r--r--src/library/scala/reflect/makro/Settings.scala38
-rw-r--r--src/library/scala/reflect/makro/Symbols.scala17
-rw-r--r--src/library/scala/reflect/makro/Typers.scala85
-rw-r--r--src/library/scala/reflect/makro/Util.scala31
-rw-r--r--src/library/scala/reflect/makro/internal/macroImpl.scala5
-rw-r--r--src/library/scala/reflect/makro/internal/typeTagImpl.scala133
-rw-r--r--src/library/scala/reflect/package.scala43
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala2
-rw-r--r--src/library/scala/util/Marshal.scala3
51 files changed, 2531 insertions, 755 deletions
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index b5006e7948..d241d2ddc0 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -99,17 +99,40 @@ object Predef extends LowPriorityImplicits {
// def AnyRef = scala.AnyRef
// Manifest types, companions, and incantations for summoning
+ @deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
type ClassManifest[T] = scala.reflect.ClassManifest[T]
- type Manifest[T] = scala.reflect.Manifest[T]
+ @deprecated("OptManifest is no longer supported and using it may lead to incorrect results, use `@scala.reflect.TypeTag` instead", "2.10.0")
type OptManifest[T] = scala.reflect.OptManifest[T]
+ @deprecated("Use `@scala.reflect.GroundTypeTag` instead", "2.10.0")
+ type Manifest[T] = scala.reflect.Manifest[T]
+ @deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
val ClassManifest = scala.reflect.ClassManifest
- val Manifest = scala.reflect.Manifest
- val NoManifest = scala.reflect.NoManifest
+ // [Paul to Eugene] No lazy vals in Predef. Too expensive. Have to work harder on breaking initialization dependencies.
+ @deprecated("Use `@scala.reflect.GroundTypeTag` instead", "2.10.0")
+ lazy val Manifest = scala.reflect.Manifest // needs to be lazy, because requires scala.reflect.mirror instance
+ @deprecated("NoManifest is no longer supported and using it may lead to incorrect results, use `@scala.reflect.TypeTag` instead", "2.10.0")
+ lazy val NoManifest = scala.reflect.NoManifest // needs to be lazy, because requires scala.reflect.mirror instance
def manifest[T](implicit m: Manifest[T]) = m
def classManifest[T](implicit m: ClassManifest[T]) = m
def optManifest[T](implicit m: OptManifest[T]) = m
+ // Tag types and companions, and incantations for summoning
+ type ClassTag[T] = scala.reflect.ClassTag[T]
+ type TypeTag[T] = scala.reflect.TypeTag[T]
+ type GroundTypeTag[T] = scala.reflect.GroundTypeTag[T]
+ val ClassTag = scala.reflect.ClassTag // doesn't need to be lazy, because it's not a path-dependent type
+ // [Paul to Eugene] No lazy vals in Predef. Too expensive. Have to work harder on breaking initialization dependencies.
+ lazy val TypeTag = scala.reflect.TypeTag // needs to be lazy, because requires scala.reflect.mirror instance
+ lazy val GroundTypeTag = scala.reflect.GroundTypeTag
+
+ // [Eugene to Martin] it's really tedious to type "implicitly[...]" all the time, so I'm reintroducing these shortcuts
+ def classTag[T](implicit ctag: ClassTag[T]) = ctag
+ def tag[T](implicit ttag: TypeTag[T]) = ttag
+ def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+ def groundTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+ def groundTypeTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+
// Minor variations on identity functions
def identity[A](x: A): A = x // @see `conforms` for the implicit version
@inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero`
diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala
index f0e4c79abf..e396b0695e 100644
--- a/src/library/scala/collection/mutable/ArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/ArrayBuilder.scala
@@ -33,8 +33,22 @@ object ArrayBuilder {
* @tparam T type of the elements for the array builder, with a `ClassManifest` context bound.
* @return a new empty array builder.
*/
- def make[T: ClassManifest](): ArrayBuilder[T] =
- implicitly[ClassManifest[T]].newArrayBuilder()
+ def make[T: ClassManifest](): ArrayBuilder[T] = {
+ val manifest = implicitly[ClassManifest[T]]
+ val erasure = manifest.erasure
+ erasure match {
+ case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
+ case _ => new ArrayBuilder.ofRef[T with AnyRef]()(manifest.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
+ }
+ }
/** A class for array builders for arrays of reference types.
*
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 5f7c508181..3e7b8071be 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -39,8 +39,8 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
private def rowBuilder[U]: Builder[U, Array[U]] =
Array.newBuilder(
- ClassManifest.fromClass(
- repr.getClass.getComponentType.getComponentType.asInstanceOf[Predef.Class[U]]))
+ ClassManifest[U](
+ repr.getClass.getComponentType.getComponentType))
override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
var l = math.min(len, repr.length)
@@ -87,8 +87,8 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
}
}
val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(
- ClassManifest.fromClass(
- repr.getClass.getComponentType.asInstanceOf[Predef.Class[Array[U]]]))
+ ClassManifest[Array[U]](
+ repr.getClass.getComponentType))
for (b <- bs) bb += b.result
bb.result
}
@@ -110,7 +110,7 @@ object ArrayOps {
override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(
- ClassManifest.classType[T](repr.getClass.getComponentType))
+ ClassManifest[T](repr.getClass.getComponentType))
def length: Int = repr.length
def apply(index: Int): T = repr(index)
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 4287bac249..fac4eb77bb 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -112,7 +112,7 @@ object WrappedArray {
def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer
final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable {
- lazy val elemManifest = ClassManifest.classType[T](array.getClass.getComponentType)
+ lazy val elemManifest = ClassManifest[T](array.getClass.getComponentType)
def length: Int = array.length
def apply(index: Int): T = array(index).asInstanceOf[T]
def update(index: Int, elem: T) { array(index) = elem }
diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
index 9771a45a28..fce65468e9 100644
--- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
@@ -28,7 +28,19 @@ class WrappedArrayBuilder[A](manifest: ClassManifest[A]) extends Builder[A, Wrap
private var size: Int = 0
private def mkArray(size: Int): WrappedArray[A] = {
- val newelems = manifest.newWrappedArray(size)
+ val erasure = manifest.erasure
+ val newelems = erasure match {
+ case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Integer.TYPE => new WrappedArray.ofInt(new Array[Int](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Long.TYPE => new WrappedArray.ofLong(new Array[Long](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Float.TYPE => new WrappedArray.ofFloat(new Array[Float](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Double.TYPE => new WrappedArray.ofDouble(new Array[Double](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(new Array[Boolean](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Void.TYPE => new WrappedArray.ofUnit(new Array[Unit](size)).asInstanceOf[WrappedArray[A]]
+ case _ => new WrappedArray.ofRef[A with AnyRef](manifest.newArray(size).asInstanceOf[Array[A with AnyRef]]).asInstanceOf[WrappedArray[A]]
+ }
if (this.size > 0) Array.copy(elems.array, 0, newelems.array, 0, this.size)
newelems
}
diff --git a/src/library/scala/reflect/ArrayTags.scala b/src/library/scala/reflect/ArrayTags.scala
new file mode 100644
index 0000000000..8df7fe5f4e
--- /dev/null
+++ b/src/library/scala/reflect/ArrayTags.scala
@@ -0,0 +1,19 @@
+package scala.reflect
+
+/** An `ArrayTag[T]` is a descriptor that is requested by the compiler every time
+ * when an array is instantiated, but the element type is unknown at compile time.
+ *
+ * Scala library provides a standard implementation of this trait,
+ * `ClassTag[T]` that explicitly carries the `java.lang.Class` erasure of type T.
+ *
+ * However other platforms (e.g. a Scala -> JS crosscompiler) may reimplement this trait as they see fit
+ * and then expose the implementation via an implicit macro.
+ */
+@annotation.implicitNotFound(msg = "No ArrayTag available for ${T}")
+trait ArrayTag[T] {
+ /** Produces an `ArrayTag` that knows how to build `Array[Array[T]]` */
+ def wrap: ArrayTag[Array[T]]
+
+ /** Produces a new array with element type `T` and length `len` */
+ def newArray(len: Int): Array[T]
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala
deleted file mode 100644
index 37be067614..0000000000
--- a/src/library/scala/reflect/ClassManifest.scala
+++ /dev/null
@@ -1,263 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-/* [Martin]
- * Todo: ClassManifests currently contain all available type arguments.
- * That's a waste of cycles if all that's needed is the class.
- * We should have instead consider a structure like this:
- *
- * OptManifest
- * / \
- * / \
- * PartialManifest ClassManifest
- * \ /
- * \ /
- * Manifest
- *
- * where PartialManifest means: generate as much as you can, use NoManifest
- * where nothing is known, and
- * ClassManifest means: generate exactly the top-level class, and nothing else.
- */
-package scala.reflect
-
-import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
-import java.lang.{ Class => jClass }
-
-/** A `ClassManifest[T]` is an opaque descriptor for type `T`.
- * It is used by the compiler to preserve information necessary
- * for instantiating `Arrays` in those cases where the element type
- * is unknown at compile time.
- *
- * The type-relation operators make an effort to present a more accurate
- * picture than can be realized with erased types, but they should not be
- * relied upon to give correct answers. In particular they are likely to
- * be wrong when variance is involved or when a subtype has a different
- * number of type arguments than a supertype.
- */
-trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
- /** A class representing the type `U` to which `T` would be erased. Note
- * that there is no subtyping relationship between `T` and `U`. */
- def erasure: jClass[_]
-
- /** The Scala type described by this manifest.
- */
- lazy val tpe: mirror.Type = mirror.classToType(erasure)
-
- def symbol: mirror.Symbol = mirror.classToSymbol(erasure)
-
- private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = {
- def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = {
- left.nonEmpty && {
- val next = left.head
- val supers = next.getInterfaces.toSet ++ Option(next.getSuperclass)
- supers(sup) || {
- val xs = left ++ supers filterNot seen
- loop(xs - next, seen + next)
- }
- }
- }
- loop(Set(sub), Set())
- }
-
- private def subargs(args1: List[OptManifest[_]], args2: List[OptManifest[_]]) = (args1 corresponds args2) {
- // !!! [Martin] this is wrong, need to take variance into account
- case (x: ClassManifest[_], y: ClassManifest[_]) => x <:< y
- case (x, y) => (x eq NoManifest) && (y eq NoManifest)
- }
-
- /** Tests whether the type represented by this manifest is a subtype
- * of the type represented by `that` manifest, subject to the limitations
- * described in the header.
- */
- def <:<(that: ClassManifest[_]): Boolean = {
- // All types which could conform to these types will override <:<.
- def cannotMatch = {
- import Manifest._
- that.isInstanceOf[AnyValManifest[_]] || (that eq AnyVal) || (that eq Nothing) || (that eq Null)
- }
-
- // This is wrong, and I don't know how it can be made right
- // without more development of Manifests, due to arity-defying
- // relationships like:
- //
- // List[String] <: AnyRef
- // Map[Int, Int] <: Iterable[(Int, Int)]
- //
- // Given the manifest for Map[A, B] how do I determine that a
- // supertype has single type argument (A, B) ? I don't see how we
- // can say whether X <:< Y when type arguments are involved except
- // when the erasure is the same, even before considering variance.
- !cannotMatch && {
- // this part is wrong for not considering variance
- if (this.erasure == that.erasure)
- subargs(this.typeArguments, that.typeArguments)
- // this part is wrong for punting unless the rhs has no type
- // arguments, but it's better than a blindfolded pinata swing.
- else
- that.typeArguments.isEmpty && subtype(this.erasure, that.erasure)
- }
- }
-
- /** Tests whether the type represented by this manifest is a supertype
- * of the type represented by `that` manifest, subject to the limitations
- * described in the header.
- */
- def >:>(that: ClassManifest[_]): Boolean =
- that <:< this
-
- def canEqual(other: Any) = other match {
- case _: ClassManifest[_] => true
- case _ => false
- }
-
- /** Tests whether the type represented by this manifest is equal to
- * the type represented by `that` manifest, subject to the limitations
- * described in the header.
- */
- override def equals(that: Any): Boolean = that match {
- case m: ClassManifest[_] => (m canEqual this) && (this.erasure == m.erasure)
- case _ => false
- }
- override def hashCode = this.erasure.##
-
- protected def arrayClass[T](tp: jClass[_]): jClass[Array[T]] =
- java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[T]]]
-
- def arrayManifest: ClassManifest[Array[T]] =
- ClassManifest.classType[Array[T]](arrayClass[T](erasure), this)
-
- def newArray(len: Int): Array[T] =
- java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
-
- def newArray2(len: Int): Array[Array[T]] =
- java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len)
- .asInstanceOf[Array[Array[T]]]
-
- def newArray3(len: Int): Array[Array[Array[T]]] =
- java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len)
- .asInstanceOf[Array[Array[Array[T]]]]
-
- def newArray4(len: Int): Array[Array[Array[Array[T]]]] =
- java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len)
- .asInstanceOf[Array[Array[Array[Array[T]]]]]
-
- def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] =
- java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len)
- .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]]
-
- def newWrappedArray(len: Int): WrappedArray[T] =
- // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests
- new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]]
-
- def newArrayBuilder(): ArrayBuilder[T] =
- // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests
- new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
-
- def typeArguments: List[OptManifest[_]] = List()
-
- protected def argString =
- if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]")
- else if (erasure.isArray) "["+ClassManifest.fromClass(erasure.getComponentType)+"]"
- else ""
-}
-
-/** The object `ClassManifest` defines factory methods for manifests.
- * It is intended for use by the compiler and should not be used in client code.
- */
-object ClassManifest {
- val Byte = Manifest.Byte
- val Short = Manifest.Short
- val Char = Manifest.Char
- val Int = Manifest.Int
- val Long = Manifest.Long
- val Float = Manifest.Float
- val Double = Manifest.Double
- val Boolean = Manifest.Boolean
- val Unit = Manifest.Unit
- val Any = Manifest.Any
- val Object = Manifest.Object
- val AnyVal = Manifest.AnyVal
- val Nothing = Manifest.Nothing
- val Null = Manifest.Null
-
- def fromClass[T](clazz: jClass[T]): ClassManifest[T] = clazz match {
- case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]]
- case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]]
- case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]]
- case java.lang.Integer.TYPE => Int.asInstanceOf[ClassManifest[T]]
- case java.lang.Long.TYPE => Long.asInstanceOf[ClassManifest[T]]
- case java.lang.Float.TYPE => Float.asInstanceOf[ClassManifest[T]]
- case java.lang.Double.TYPE => Double.asInstanceOf[ClassManifest[T]]
- case java.lang.Boolean.TYPE => Boolean.asInstanceOf[ClassManifest[T]]
- case java.lang.Void.TYPE => Unit.asInstanceOf[ClassManifest[T]]
- case _ => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]]
- }
-
- def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest.singleType(value)
-
- /** ClassManifest for the class type `clazz`, where `clazz` is
- * a top-level or static class.
- * @note This no-prefix, no-arguments case is separate because we
- * it's called from ScalaRunTime.boxArray itself. If we
- * pass varargs as arrays into this, we get an infinitely recursive call
- * to boxArray. (Besides, having a separate case is more efficient)
- */
- def classType[T](clazz: jClass[_]): ClassManifest[T] =
- new ClassTypeManifest[T](None, clazz, Nil)
-
- /** ClassManifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class and `args` are its type arguments */
- def classType[T](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
- new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
-
- /** ClassManifest for the class type `clazz[args]`, where `clazz` is
- * a class with non-package prefix type `prefix` and type arguments `args`.
- */
- def classType[T](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
- new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
-
- def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
- case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]]
- case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest
- }
-
- /** ClassManifest for the abstract type `prefix # name`. `upperBound` is not
- * strictly necessary as it could be obtained by reflection. It was
- * added so that erasure can be calculated without reflection. */
- def abstractType[T](prefix: OptManifest[_], name: String, clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
- new ClassManifest[T] {
- def erasure = clazz
- override val typeArguments = args.toList
- override def toString = prefix.toString+"#"+name+argString
- }
-
- /** ClassManifest for the abstract type `prefix # name`. `upperBound` is not
- * strictly necessary as it could be obtained by reflection. It was
- * added so that erasure can be calculated without reflection.
- * todo: remove after next boostrap
- */
- def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] =
- new ClassManifest[T] {
- def erasure = upperbound.erasure
- override val typeArguments = args.toList
- override def toString = prefix.toString+"#"+name+argString
- }
-}
-
-/** Manifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class: todo: we should try to merge this with Manifest's class */
-private class ClassTypeManifest[T](
- prefix: Option[OptManifest[_]],
- val erasure: jClass[_],
- override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
-{
- override def toString =
- (if (prefix.isEmpty) "" else prefix.get.toString+"#") +
- (if (erasure.isArray) "Array" else erasure.getName) +
- argString
-}
diff --git a/src/library/scala/reflect/ClassTags.scala b/src/library/scala/reflect/ClassTags.scala
new file mode 100644
index 0000000000..2833e7cc8e
--- /dev/null
+++ b/src/library/scala/reflect/ClassTags.scala
@@ -0,0 +1,158 @@
+package scala.reflect
+
+import java.lang.{ Class => jClass }
+import scala.reflect.{ mirror => rm }
+
+/** A `ClassTag[T]` wraps a Java class, which can be accessed via the `erasure` method.
+ * This is useful in itself, but also enables very important use case.
+ * Having this knowledge ClassTag can instantiate `Arrays`
+ * in those cases where the element type is unknown at compile time.
+ * Hence, ClassTag[T] conforms to the ArrayTag[T] trait.
+ */
+// please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
+// class tags, and all tags in general, should be as minimalistic as possible
+@annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
+abstract case class ClassTag[T](erasure: jClass[_]) extends ArrayTag[T] {
+ // quick and dirty fix to a deadlock in Predef:
+ // http://groups.google.com/group/scala-internals/browse_thread/thread/977de028a4e75d6f
+ // todo. fix that in a sane way
+ // assert(erasure != null)
+
+ /** A Scala reflection type representing T.
+ * For ClassTags this representation is lossy (in their case tpe is retrospectively constructed from erasure).
+ * For TypeTags and GroundTypeTags the representation is almost precise, because it uses reification
+ * (information is lost only when T refers to non-locatable symbols, which are then reified as free variables). */
+ def tpe: rm.Type = rm.classToType(erasure)
+
+ /** A Scala reflection symbol representing T. */
+ def symbol: rm.Symbol = rm.classToSymbol(erasure)
+
+ /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
+ def wrap: ClassTag[Array[T]] = {
+ val arrayClazz = java.lang.reflect.Array.newInstance(erasure, 0).getClass.asInstanceOf[jClass[Array[T]]]
+ ClassTag[Array[T]](arrayClazz)
+ }
+
+ /** Produces a new array with element type `T` and length `len` */
+ def newArray(len: Int): Array[T] =
+ erasure match {
+ case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
+ case java.lang.Short.TYPE => new Array[Short](len).asInstanceOf[Array[T]]
+ case java.lang.Character.TYPE => new Array[Char](len).asInstanceOf[Array[T]]
+ case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
+ case java.lang.Long.TYPE => new Array[Long](len).asInstanceOf[Array[T]]
+ case java.lang.Float.TYPE => new Array[Float](len).asInstanceOf[Array[T]]
+ case java.lang.Double.TYPE => new Array[Double](len).asInstanceOf[Array[T]]
+ case java.lang.Boolean.TYPE => new Array[Boolean](len).asInstanceOf[Array[T]]
+ case java.lang.Void.TYPE => new Array[Unit](len).asInstanceOf[Array[T]]
+ case _ => java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
+ }
+}
+
+object ClassTag {
+ private val ObjectTYPE = classOf[java.lang.Object]
+ private val StringTYPE = classOf[java.lang.String]
+
+ val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte](java.lang.Byte.TYPE) { private def readResolve() = ClassTag.Byte }
+ val Short : ClassTag[scala.Short] = new ClassTag[scala.Short](java.lang.Short.TYPE) { private def readResolve() = ClassTag.Short }
+ val Char : ClassTag[scala.Char] = new ClassTag[scala.Char](java.lang.Character.TYPE) { private def readResolve() = ClassTag.Char }
+ val Int : ClassTag[scala.Int] = new ClassTag[scala.Int](java.lang.Integer.TYPE) { private def readResolve() = ClassTag.Int }
+ val Long : ClassTag[scala.Long] = new ClassTag[scala.Long](java.lang.Long.TYPE) { private def readResolve() = ClassTag.Long }
+ val Float : ClassTag[scala.Float] = new ClassTag[scala.Float](java.lang.Float.TYPE) { private def readResolve() = ClassTag.Float }
+ val Double : ClassTag[scala.Double] = new ClassTag[scala.Double](java.lang.Double.TYPE) { private def readResolve() = ClassTag.Double }
+ val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean](java.lang.Boolean.TYPE) { private def readResolve() = ClassTag.Boolean }
+ val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit](java.lang.Void.TYPE) { private def readResolve() = ClassTag.Unit }
+ val Any : ClassTag[scala.Any] = new ClassTag[scala.Any](ObjectTYPE) { private def readResolve() = ClassTag.Any }
+ val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object](ObjectTYPE) { private def readResolve() = ClassTag.Object }
+ val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal](ObjectTYPE) { private def readResolve() = ClassTag.AnyVal }
+ val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef](ObjectTYPE) { private def readResolve() = ClassTag.AnyRef }
+ val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing](ObjectTYPE) { private def readResolve() = ClassTag.Nothing }
+ val Null : ClassTag[scala.Null] = new ClassTag[scala.Null](ObjectTYPE) { private def readResolve() = ClassTag.Null }
+ val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String](StringTYPE) { private def readResolve() = ClassTag.String }
+
+ def apply[T](clazz: jClass[_]): ClassTag[T] =
+ clazz match {
+ case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
+ case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
+ case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
+ case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
+ case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
+ case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
+ case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
+ case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
+ case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
+ case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
+ case StringTYPE => ClassTag.String.asInstanceOf[ClassTag[T]]
+ case _ => new ClassTag[T](clazz) {}
+ }
+
+ def apply[T](tpe: rm.Type): ClassTag[T] =
+ tpe match {
+ case rm.ByteTpe => ClassTag.Byte.asInstanceOf[ClassTag[T]]
+ case rm.ShortTpe => ClassTag.Short.asInstanceOf[ClassTag[T]]
+ case rm.CharTpe => ClassTag.Char.asInstanceOf[ClassTag[T]]
+ case rm.IntTpe => ClassTag.Int.asInstanceOf[ClassTag[T]]
+ case rm.LongTpe => ClassTag.Long.asInstanceOf[ClassTag[T]]
+ case rm.FloatTpe => ClassTag.Float.asInstanceOf[ClassTag[T]]
+ case rm.DoubleTpe => ClassTag.Double.asInstanceOf[ClassTag[T]]
+ case rm.BooleanTpe => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
+ case rm.UnitTpe => ClassTag.Unit.asInstanceOf[ClassTag[T]]
+ case rm.AnyTpe => ClassTag.Any.asInstanceOf[ClassTag[T]]
+ case rm.ObjectTpe => ClassTag.Object.asInstanceOf[ClassTag[T]]
+ case rm.AnyValTpe => ClassTag.AnyVal.asInstanceOf[ClassTag[T]]
+ case rm.AnyRefTpe => ClassTag.AnyRef.asInstanceOf[ClassTag[T]]
+ case rm.NothingTpe => ClassTag.Nothing.asInstanceOf[ClassTag[T]]
+ case rm.NullTpe => ClassTag.Null.asInstanceOf[ClassTag[T]]
+ case rm.StringTpe => ClassTag.String.asInstanceOf[ClassTag[T]]
+ case _ => apply[T](rm.typeToClass(tpe.erasure))
+ }
+
+ implicit def toDeprecatedClassManifestApis[T](ctag: ClassTag[T]): DeprecatedClassManifestApis[T] = new DeprecatedClassManifestApis[T](ctag)
+}
+
+// this class should not be used directly in client code
+class DeprecatedClassManifestApis[T](ctag: ClassTag[T]) {
+ import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
+
+ @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
+ def <:<(that: ClassManifest[_]): Boolean = ctag.tpe <:< that.tpe
+
+ @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
+ def >:>(that: ClassManifest[_]): Boolean = that <:< ctag
+
+ @deprecated("Use `wrap` instead", "2.10.0")
+ def arrayManifest: ClassManifest[Array[T]] = ctag.wrap
+
+ @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
+ def newArray2(len: Int): Array[Array[T]] = ctag.wrap.newArray(len)
+
+ @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
+ def newArray3(len: Int): Array[Array[Array[T]]] = ctag.wrap.wrap.newArray(len)
+
+ @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
+ def newArray4(len: Int): Array[Array[Array[Array[T]]]] = ctag.wrap.wrap.wrap.newArray(len)
+
+ @deprecated("Use a combination of `wrap` and `newArray` instead", "2.10.0")
+ def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = ctag.wrap.wrap.wrap.wrap.newArray(len)
+
+ @deprecated("Use `@scala.collection.mutable.WrappedArray` object instead", "2.10.0")
+ def newWrappedArray(len: Int): WrappedArray[T] =
+ ctag.erasure match {
+ case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Integer.TYPE => new WrappedArray.ofInt(new Array[Int](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Long.TYPE => new WrappedArray.ofLong(new Array[Long](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Float.TYPE => new WrappedArray.ofFloat(new Array[Float](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Double.TYPE => new WrappedArray.ofDouble(new Array[Double](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(new Array[Boolean](len)).asInstanceOf[WrappedArray[T]]
+ case java.lang.Void.TYPE => new WrappedArray.ofUnit(new Array[Unit](len)).asInstanceOf[WrappedArray[T]]
+ case _ => new WrappedArray.ofRef[T with AnyRef](ctag.newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]]
+ }
+
+ @deprecated("Use `@scala.collection.mutable.ArrayBuilder` object instead", "2.10.0")
+ def newArrayBuilder(): ArrayBuilder[T] = ArrayBuilder.make[T]()(ctag)
+
+ @deprecated("`typeArguments` is no longer supported, and will always return an empty list. Use `@scala.reflect.TypeTag` or `@scala.reflect.GroundTypeTag` to capture and analyze type arguments", "2.10.0")
+ def typeArguments: List[OptManifest[_]] = List()
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
deleted file mode 100644
index e5df487be9..0000000000
--- a/src/library/scala/reflect/Manifest.scala
+++ /dev/null
@@ -1,302 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.reflect
-
-import scala.collection.mutable.{ ArrayBuilder, WrappedArray }
-import mirror._
-
-/** A `Manifest[T]` is an opaque descriptor for type T. Its supported use
- * is to give access to the erasure of the type as a `Class` instance, as
- * is necessary for the creation of native `Arrays` if the class is not
- * known at compile time.
- *
- * The type-relation operators `<:<` and `=:=` should be considered
- * approximations only, as there are numerous aspects of type conformance
- * which are not yet adequately represented in manifests.
- *
- * Example usages:
-{{{
- def arr[T] = new Array[T](0) // does not compile
- def arr[T](implicit m: Manifest[T]) = new Array[T](0) // compiles
- def arr[T: Manifest] = new Array[T](0) // shorthand for the preceding
-
- // Methods manifest, classManifest, and optManifest are in [[scala.Predef]].
- def isApproxSubType[T: Manifest, U: Manifest] = manifest[T] <:< manifest[U]
- isApproxSubType[List[String], List[AnyRef]] // true
- isApproxSubType[List[String], List[Int]] // false
-
- def methods[T: ClassManifest] = classManifest[T].erasure.getMethods
- def retType[T: ClassManifest](name: String) =
- methods[T] find (_.getName == name) map (_.getGenericReturnType)
-
- retType[Map[_, _]]("values") // Some(scala.collection.Iterable<B>)
-}}}
- *
- */
-@annotation.implicitNotFound(msg = "No Manifest available for ${T}.")
-trait Manifest[T] extends ClassManifest[T] with Equals {
- override def typeArguments: List[Manifest[_]] = Nil
-
- override def arrayManifest: Manifest[Array[T]] =
- Manifest.classType[Array[T]](arrayClass[T](erasure), this)
-
- override def canEqual(that: Any): Boolean = that match {
- case _: Manifest[_] => true
- case _ => false
- }
- /** Note: testing for erasure here is important, as it is many times
- * faster than <:< and rules out most comparisons.
- */
- override def equals(that: Any): Boolean = that match {
- case m: Manifest[_] => (m canEqual this) && (this.erasure == m.erasure) && (this <:< m) && (m <:< this)
- case _ => false
- }
- override def hashCode = this.erasure.##
-}
-
-abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals {
- override def <:<(that: ClassManifest[_]): Boolean =
- (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal)
- override def canEqual(other: Any) = other match {
- case _: AnyValManifest[_] => true
- case _ => false
- }
- override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
- override val hashCode = System.identityHashCode(this)
-}
-
-/** The object `Manifest` defines factory methods for manifests.
- * It is intended for use by the compiler and should not be used
- * in client code.
- */
-object Manifest {
- import mirror.{ definitions => mdefs }
-
- def valueManifests: List[AnyValManifest[_]] =
- List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit)
-
- val Byte: AnyValManifest[Byte] = new AnyValManifest[scala.Byte]("Byte") {
- def erasure = java.lang.Byte.TYPE
- override def newArray(len: Int): Array[Byte] = new Array[Byte](len)
- override def newWrappedArray(len: Int): WrappedArray[Byte] = new WrappedArray.ofByte(new Array[Byte](len))
- override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte()
- private def readResolve(): Any = Manifest.Byte
- }
-
- val Short: AnyValManifest[Short] = new AnyValManifest[scala.Short]("Short") {
- def erasure = java.lang.Short.TYPE
- override def newArray(len: Int): Array[Short] = new Array[Short](len)
- override def newWrappedArray(len: Int): WrappedArray[Short] = new WrappedArray.ofShort(new Array[Short](len))
- override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort()
- private def readResolve(): Any = Manifest.Short
- }
-
- val Char: AnyValManifest[Char] = new AnyValManifest[scala.Char]("Char") {
- def erasure = java.lang.Character.TYPE
- override def newArray(len: Int): Array[Char] = new Array[Char](len)
- override def newWrappedArray(len: Int): WrappedArray[Char] = new WrappedArray.ofChar(new Array[Char](len))
- override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar()
- private def readResolve(): Any = Manifest.Char
- }
-
- val Int: AnyValManifest[Int] = new AnyValManifest[scala.Int]("Int") {
- def erasure = java.lang.Integer.TYPE
- override def newArray(len: Int): Array[Int] = new Array[Int](len)
- override def newWrappedArray(len: Int): WrappedArray[Int] = new WrappedArray.ofInt(new Array[Int](len))
- override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt()
- private def readResolve(): Any = Manifest.Int
- }
-
- val Long: AnyValManifest[Long] = new AnyValManifest[scala.Long]("Long") {
- def erasure = java.lang.Long.TYPE
- override def newArray(len: Int): Array[Long] = new Array[Long](len)
- override def newWrappedArray(len: Int): WrappedArray[Long] = new WrappedArray.ofLong(new Array[Long](len))
- override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong()
- private def readResolve(): Any = Manifest.Long
- }
-
- val Float: AnyValManifest[Float] = new AnyValManifest[scala.Float]("Float") {
- def erasure = java.lang.Float.TYPE
- override def newArray(len: Int): Array[Float] = new Array[Float](len)
- override def newWrappedArray(len: Int): WrappedArray[Float] = new WrappedArray.ofFloat(new Array[Float](len))
- override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat()
- private def readResolve(): Any = Manifest.Float
- }
-
- val Double: AnyValManifest[Double] = new AnyValManifest[scala.Double]("Double") {
- def erasure = java.lang.Double.TYPE
- override def newArray(len: Int): Array[Double] = new Array[Double](len)
- override def newWrappedArray(len: Int): WrappedArray[Double] = new WrappedArray.ofDouble(new Array[Double](len))
- override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble()
- private def readResolve(): Any = Manifest.Double
- }
-
- val Boolean: AnyValManifest[Boolean] = new AnyValManifest[scala.Boolean]("Boolean") {
- def erasure = java.lang.Boolean.TYPE
- override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len)
- override def newWrappedArray(len: Int): WrappedArray[Boolean] = new WrappedArray.ofBoolean(new Array[Boolean](len))
- override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean()
- private def readResolve(): Any = Manifest.Boolean
- }
-
- val Unit: AnyValManifest[Unit] = new AnyValManifest[scala.Unit]("Unit") {
- def erasure = java.lang.Void.TYPE
- override def newArray(len: Int): Array[Unit] = new Array[Unit](len)
- override def newWrappedArray(len: Int): WrappedArray[Unit] = new WrappedArray.ofUnit(new Array[Unit](len))
- override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit()
- private def readResolve(): Any = Manifest.Unit
- }
-
- val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") {
- override def symbol = mdefs.AnyClass
- override def <:<(that: ClassManifest[_]): Boolean = (that eq this)
- private def readResolve(): Any = Manifest.Any
- }
-
- val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") {
- override def symbol = mdefs.ObjectClass
- override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
- private def readResolve(): Any = Manifest.Object
- }
-
- val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") {
- override def symbol = mdefs.AnyValClass
- override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
- private def readResolve(): Any = Manifest.AnyVal
- }
-
- val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") {
- override def symbol = mdefs.NullClass
- override def <:<(that: ClassManifest[_]): Boolean =
- (that ne null) && (that ne Nothing) && !(that <:< AnyVal)
- private def readResolve(): Any = Manifest.Null
- }
-
- val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") {
- override def symbol = mdefs.NothingClass
- override def <:<(that: ClassManifest[_]): Boolean = (that ne null)
- private def readResolve(): Any = Manifest.Nothing
- }
-
- private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] {
- lazy val erasure = value.getClass
- override lazy val symbol = InstanceRefSymbol(value) // todo: change to freevar
- override lazy val tpe = mirror.SingleType(mirror.NoPrefix, symbol)
- override lazy val toString = value.toString + ".type"
- }
-
- /** Manifest for the singleton type `value.type`. */
- def singleType[T <: AnyRef](value: AnyRef): Manifest[T] =
- new SingletonTypeManifest[T](value)
-
- /** Manifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class.
- * @note This no-prefix, no-arguments case is separate because we
- * it's called from ScalaRunTime.boxArray itself. If we
- * pass varargs as arrays into this, we get an infinitely recursive call
- * to boxArray. (Besides, having a separate case is more efficient)
- */
- def classType[T](clazz: Predef.Class[_]): Manifest[T] =
- new ClassTypeManifest[T](None, clazz, Nil)
-
- /** Manifest for the class type `clazz`, where `clazz` is
- * a top-level or static class and args are its type arguments. */
- def classType[T](clazz: Predef.Class[T], arg1: Manifest[_], args: Manifest[_]*): Manifest[T] =
- new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
-
- /** Manifest for the class type `clazz[args]`, where `clazz` is
- * a class with non-package prefix type `prefix` and type arguments `args`.
- */
- def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
- new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
-
- /** Phantom types have no runtime representation; they all erase to Object,
- * but the Symbol preserves their identity.
- */
- private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) {
- override lazy val tpe = namedType(mirror.NoPrefix, symbol, Nil)
- override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
- override val hashCode = System.identityHashCode(this)
- }
-
- /** Manifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class. */
- private class ClassTypeManifest[T](prefix: Option[Manifest[_]],
- val erasure: Predef.Class[_],
- override val typeArguments: List[Manifest[_]]) extends Manifest[T] {
-
- override lazy val tpe = {
- val pre = prefix match {
- case Some(pm) => pm.tpe
- case None => symbol.owner.thisPrefix
- }
- namedType(pre, symbol, typeArguments map (_.tpe))
- }
-
- override def toString =
- (if (prefix.isEmpty) "" else prefix.get.toString+"#") +
- (if (erasure.isArray) "Array" else erasure.getName) +
- argString
- }
-
- def arrayType[T](arg: Manifest[_]): Manifest[Array[T]] =
- arg.asInstanceOf[Manifest[T]].arrayManifest
-
- /** Manifest for the abstract type `prefix # name'. `upperBound` is not
- * strictly necessary as it could be obtained by reflection. It was
- * added so that erasure can be calculated without reflection. */
- def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
- new Manifest[T] {
- def erasure = upperBound
- override lazy val tpe = namedType(prefix.tpe, prefix.tpe.member(newTypeName(name)), args map (_.tpe) toList)
- override val typeArguments = args.toList
- override def toString = prefix.toString+"#"+name+argString
- }
-
- /** Manifest for the unknown type `_ >: L <: U` in an existential.
- */
- def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] =
- new Manifest[T] {
- def erasure = upperBound.erasure
- override lazy val tpe = mirror.TypeBounds(lowerBound.tpe, upperBound.tpe)
- override def toString =
- "_" +
- (if (lowerBound eq Nothing) "" else " >: "+lowerBound) +
- (if (upperBound eq Nothing) "" else " <: "+upperBound)
- }
-
- /** Manifest for the intersection type `parents_0 with ... with parents_n'. */
- def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
- new Manifest[T] {
- def erasure = parents.head.erasure
- override lazy val tpe = mirror.RefinedType((parents map (_.tpe)).toList, newScope)
- override def toString = parents.mkString(" with ")
- }
-
- /** A generic manifest factory from a reflect.Type. Except where
- * mandated by performance considerations, we should replace most
- * other manifest factories by this one. There's just one thing
- * that needs to be done first: A Manifest's type can refer
- * to type variables that are controlled by manifests. In that
- * case the reified type needs to contain the type passed in the manifest
- * instead of the reference to the manifest. Note that splicing manifests
- * into manfifests is completely analogous to splicing code blocks into
- * code blocks. Manifest[T] and Code[T] are really the same thing, only one
- * works for types, the other for trees.
- * Another complication is that once we generate manifests from types, we really
- * should have reflection as a standard component shipped with the standard library,
- * instead of in scala-compiler.jar.
- */
- def apply[T](_tpe: mirror.Type): Manifest[T] = new Manifest[T] {
- override def symbol = _tpe.typeSymbol
- override lazy val tpe = _tpe
- override def erasure = mirror.typeToClass(_tpe.erasedType)
- override def toString = _tpe.toString
- }
-}
diff --git a/src/library/scala/reflect/NoManifest.scala b/src/library/scala/reflect/NoManifest.scala
deleted file mode 100644
index 191e46ae39..0000000000
--- a/src/library/scala/reflect/NoManifest.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.reflect
-
-/** One of the branches of an [[scala.reflect.OptManifest]].
- */
-object NoManifest extends OptManifest[Nothing] with Serializable {
- override def toString = "<?>"
-}
diff --git a/src/library/scala/reflect/OptManifest.scala b/src/library/scala/reflect/OptManifest.scala
deleted file mode 100644
index 2a955deb2c..0000000000
--- a/src/library/scala/reflect/OptManifest.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.reflect
-
-/** A `OptManifest[T]` is an optional [[scala.reflect.Manifest]].
- *
- * It is either a `Manifest` or the value `NoManifest`.
- *
- * @author Martin Odersky
- */
-trait OptManifest[+T] extends Serializable
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala
index 510f0819c6..1be46eac55 100644
--- a/src/library/scala/reflect/ReflectionUtils.scala
+++ b/src/library/scala/reflect/ReflectionUtils.scala
@@ -27,7 +27,17 @@ object ReflectionUtils {
case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex))
}
- def singletonInstance(className: String, cl: ClassLoader = getClass.getClassLoader): AnyRef = {
+ def defaultReflectionClassLoader() = {
+ // say no to non-determinism of mirror classloaders
+ // default classloader will be instantiated using current system classloader
+ // if you wish so, you can rebind it by setting ``mirror.classLoader'' to whatever is necessary
+// val cl = Thread.currentThread.getContextClassLoader
+// if (cl == null) getClass.getClassLoader else cl
+// cl
+ getClass.getClassLoader
+ }
+
+ def singletonInstance(cl: ClassLoader, className: String): AnyRef = {
val name = if (className endsWith "$") className else className + "$"
val clazz = java.lang.Class.forName(name, true, cl)
val singleton = clazz getField "MODULE$" get null
@@ -35,7 +45,17 @@ object ReflectionUtils {
}
// Retrieves the MODULE$ field for the given class name.
- def singletonInstanceOpt(className: String, cl: ClassLoader = getClass.getClassLoader): Option[AnyRef] =
- try Some(singletonInstance(className, cl))
+ def singletonInstanceOpt(cl: ClassLoader, className: String): Option[AnyRef] =
+ try Some(singletonInstance(cl, className))
+ catch { case _: ClassNotFoundException => None }
+
+ def invokeFactory(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): AnyRef = {
+ val singleton = singletonInstance(cl, className)
+ val method = singleton.getClass.getMethod(methodName, classOf[ClassLoader])
+ method.invoke(singleton, args: _*)
+ }
+
+ def invokeFactoryOpt(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): Option[AnyRef] =
+ try Some(invokeFactory(cl, className, methodName, args: _*))
catch { case _: ClassNotFoundException => None }
}
diff --git a/src/library/scala/reflect/TagMaterialization.scala b/src/library/scala/reflect/TagMaterialization.scala
new file mode 100644
index 0000000000..991feb3bac
--- /dev/null
+++ b/src/library/scala/reflect/TagMaterialization.scala
@@ -0,0 +1,154 @@
+package scala.reflect
+
+import api.Universe
+import makro.Context
+
+// todo. unfortunately, current type inferencer doesn't infer type parameters of implicit values
+// this means that during macro expansion these macros will get Nothing instead of real T
+// Oh how much I'd love to implement this now, but I have to postpone this until we have a solution for type inference
+
+/** This object is required by the compiler and <b>should not be used in client code</b>. */
+object TagMaterialization {
+ def materializeClassTag[T: c.TypeTag](c: Context): c.Expr[ClassTag[T]] = {
+ import c.mirror._
+ val tpe = implicitly[c.TypeTag[T]].tpe
+ c.materializeClassTag(tpe)
+ }
+
+ def materializeTypeTag[T: c.TypeTag](c: Context { type PrefixType = Universe }): c.Expr[c.prefix.value.TypeTag[T]] = {
+ import c.mirror._
+ val tpe = implicitly[c.TypeTag[T]].tpe
+ c.materializeTypeTag(tpe, requireGroundTypeTag = false)
+ }
+
+ def materializeGroundTypeTag[T: c.TypeTag](c: Context { type PrefixType = Universe }): c.Expr[c.prefix.value.GroundTypeTag[T]] = {
+ import c.mirror._
+ val tpe = implicitly[c.TypeTag[T]].tpe
+ c.materializeTypeTag(tpe, requireGroundTypeTag = true)
+ }
+
+ private implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils
+
+ private abstract class Utils {
+ val c: Context
+
+ import c.mirror._
+ import definitions._
+
+ val coreTags = Map(
+ ByteClass.asType -> newTermName("Byte"),
+ ShortClass.asType -> newTermName("Short"),
+ CharClass.asType -> newTermName("Char"),
+ IntClass.asType -> newTermName("Int"),
+ LongClass.asType -> newTermName("Long"),
+ FloatClass.asType -> newTermName("Float"),
+ DoubleClass.asType -> newTermName("Double"),
+ BooleanClass.asType -> newTermName("Boolean"),
+ UnitClass.asType -> newTermName("Unit"),
+ AnyClass.asType -> newTermName("Any"),
+ ObjectClass.asType -> newTermName("Object"),
+ AnyValClass.asType -> newTermName("AnyVal"),
+ AnyRefClass.asType -> newTermName("AnyRef"),
+ NothingClass.asType -> newTermName("Nothing"),
+ NullClass.asType -> newTermName("Null"))
+
+ val ReflectPackage = staticModule("scala.reflect.package")
+ val Reflect_mirror = selectTerm(ReflectPackage, "mirror")
+ val ClassTagClass = staticClass("scala.reflect.ClassTag")
+ val ClassTagErasure = selectTerm(ClassTagClass, "erasure")
+ val ClassTagModule = staticModule("scala.reflect.ClassTag")
+ val TypeTagsClass = staticClass("scala.reflect.api.TypeTags")
+ val TypeTagClass = selectType(TypeTagsClass, "TypeTag")
+ val TypeTagTpe = selectTerm(TypeTagClass, "tpe")
+ val TypeTagModule = selectTerm(TypeTagsClass, "TypeTag")
+ val GroundTypeTagClass = selectType(TypeTagsClass, "GroundTypeTag")
+ val GroundTypeTagModule = selectTerm(TypeTagsClass, "GroundTypeTag")
+
+ def materializeClassTag(tpe: Type): Tree = {
+ val prefix = gen.mkAttributedRef(Reflect_mirror) setType singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror)
+ materializeClassTag(prefix, tpe)
+ }
+
+ def materializeClassTag(prefix: Tree, tpe: Type): Tree = {
+ val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, TypeTagClass, Nil), List(tpe)))
+ def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == GroundTypeTagModule))
+ typetagInScope match {
+ case success if !success.isEmpty && !typetagIsSynthetic(success) =>
+ val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe)))
+ Apply(factory, List(Select(typetagInScope, newTermName("tpe"))))
+ case _ =>
+ val result =
+ tpe match {
+ case coreTpe if coreTags contains coreTpe =>
+ Select(Ident(ClassTagModule), coreTags(coreTpe))
+ case _ =>
+ if (tpe.typeSymbol == ArrayClass) {
+ val componentTpe = tpe.typeArguments(0)
+ val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe)))
+ val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe)
+ Select(componentTag, newTermName("wrap"))
+ } else {
+ // [Eugene] what's the intended behavior? there's no spec on ClassManifests
+ // for example, should we ban Array[T] or should we tag them with Array[AnyRef]?
+ // if its the latter, what should be the result of tagging Array[T] where T <: Int?
+ if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type")
+ val erasure =
+ if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct?
+ else tpe.erasure.normalize // necessary to deal with erasures of HK types
+ val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe)))
+ Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure)))))
+ }
+ }
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
+ }
+ }
+
+ def materializeTypeTag(tpe: Type, requireGroundTypeTag: Boolean): Tree = {
+ def prefix: Tree = ??? // todo. needs to be synthesized from c.prefix
+ materializeTypeTag(prefix, tpe, requireGroundTypeTag)
+ }
+
+ def materializeTypeTag(prefix: Tree, tpe: Type, requireGroundTypeTag: Boolean): Tree = {
+ val tagModule = if (requireGroundTypeTag) GroundTypeTagModule else TypeTagModule
+ val result =
+ tpe match {
+ case coreTpe if coreTags contains coreTpe =>
+ Select(Select(prefix, tagModule.name), coreTags(coreTpe))
+ case _ =>
+ try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireGroundTypeTag = requireGroundTypeTag)
+ catch {
+ case ex: Throwable =>
+ // [Eugene] cannot pattern match on an abstract type, so had to do this
+ val ex1 = ex
+ if (ex.getClass.toString.endsWith("$ReificationError")) {
+ ex match {
+ case c.ReificationError(pos, msg) =>
+ c.error(pos, msg)
+ EmptyTree
+ }
+ } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
+ ex match {
+ case c.UnexpectedReificationError(pos, err, cause) =>
+ if (cause != null) throw cause else throw ex
+ }
+ } else {
+ throw ex
+ }
+ }
+ }
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
+ }
+
+ private def fail(reason: Any): Nothing = {
+ val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication
+ val tpe = tpeTree.tpe
+ val PolyType(_, MethodType(_, tagTpe)) = fun.tpe
+ val tagModule = tagTpe.typeSymbol.companionSymbol
+ if (c.compilerSettings.contains("-Xlog-implicits"))
+ c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason)
+ c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe))
+ }
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Attachments.scala b/src/library/scala/reflect/api/Attachments.scala
new file mode 100644
index 0000000000..dfd362ebe0
--- /dev/null
+++ b/src/library/scala/reflect/api/Attachments.scala
@@ -0,0 +1,16 @@
+package scala.reflect
+package api
+
+/** Attachment is a generalisation of Position.
+ * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads.
+ *
+ * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree
+ * imposing an unnecessary memory tax because of something that will not be used in most cases.
+ */
+trait Attachment {
+ /** Gets the underlying position */
+ def pos: Position
+
+ /** Creates a copy of this attachment with its position updated */
+ def withPos(pos: Position): Attachment
+}
diff --git a/src/library/scala/reflect/api/ClassLoaders.scala b/src/library/scala/reflect/api/ClassLoaders.scala
new file mode 100644
index 0000000000..7be402d3df
--- /dev/null
+++ b/src/library/scala/reflect/api/ClassLoaders.scala
@@ -0,0 +1,16 @@
+package scala.reflect
+package api
+
+trait ClassLoaders { self: Universe =>
+
+ /** The symbol corresponding to the globally accessible class with the
+ * given fully qualified name `fullName`.
+ */
+ def staticClass(fullName: String): Symbol
+
+ /** The symbol corresponding to the globally accessible object with the
+ * given fully qualified name `fullName`.
+ */
+ def staticModule(fullName: String): Symbol
+
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Exprs.scala b/src/library/scala/reflect/api/Exprs.scala
new file mode 100644
index 0000000000..8c3f12783b
--- /dev/null
+++ b/src/library/scala/reflect/api/Exprs.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package api
+
+trait Exprs { self: Universe =>
+
+ /** An expression tree tagged with its type */
+ case class Expr[+T: TypeTag](tree: Tree) {
+ def tpe: Type = implicitly[TypeTag[T]].tpe
+ def eval: T = mkToolBox().runExpr(tree).asInstanceOf[T]
+ lazy val value: T = eval
+ override def toString = "Expr["+tpe+"]("+tree+")"
+ }
+
+ // [Eugene] had to move this to the companion of Tree to make stuff compile. weirdo!
+// object Expr {
+// // would be great if in future this generated an Expr[Magic]
+// // where Magic is a magic untyped type that propagates through the entire quasiquote
+// // and turns off typechecking whenever it's involved
+// // that'd allow us to splice trees into quasiquotes and still have these qqs to be partially typechecked
+// // see some exploration of these ideas here: https://github.com/xeno-by/alphakeplerdemo
+// implicit def tree2expr(tree: Tree): Expr[Nothing] = Expr[Nothing](tree)
+// implicit def expr2tree(expr: Expr[_]): Tree = expr.tree
+//
+// // [Eugene] good idea?
+// implicit def trees2exprs(trees: List[Tree]): List[Expr[Nothing]] = trees map tree2expr
+// implicit def exprs2trees(exprs: List[Expr[_]]): List[Tree] = exprs map expr2tree
+// }
+
+ // [Eugene] even weirder - implicits didn't feel at home in Trees :(
+
+ // would be great if in future this generated an Expr[Magic]
+ // where Magic is a magic untyped type that propagates through the entire quasiquote
+ // and turns off typechecking whenever it's involved
+ // that'd allow us to splice trees into quasiquotes and still have these qqs to be partially typechecked
+ // see some exploration of these ideas here: https://github.com/xeno-by/alphakeplerdemo
+ implicit def tree2expr(tree: Tree): Expr[Nothing] = Expr[Nothing](tree)(TypeTag.Nothing)
+ implicit def expr2tree(expr: Expr[_]): Tree = expr.tree
+
+ // [Eugene] good idea?
+ implicit def trees2exprs(trees: List[Tree]): List[Expr[Nothing]] = trees map tree2expr
+ implicit def exprs2trees(exprs: List[Expr[_]]): List[Tree] = exprs map expr2tree
+}
+
diff --git a/src/library/scala/reflect/api/FreeVars.scala b/src/library/scala/reflect/api/FreeVars.scala
new file mode 100644
index 0000000000..0bef099a55
--- /dev/null
+++ b/src/library/scala/reflect/api/FreeVars.scala
@@ -0,0 +1,42 @@
+package scala.reflect
+package api
+
+trait FreeVars {
+ self: Universe =>
+
+ /** Represents a free term captured by reification.
+ */
+ type FreeTerm <: Symbol
+
+ val FreeTerm: FreeTermExtractor
+
+ abstract class FreeTermExtractor {
+ def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)]
+ }
+
+ /** Extracts free terms from a tree that is reified or contains reified subtrees.
+ */
+ def freeTerms(tree: Tree): List[FreeTerm]
+
+ /** Represents a free type captured by reification.
+ */
+ type FreeType <: Symbol
+
+ val FreeType: FreeTypeExtractor
+
+ abstract class FreeTypeExtractor {
+ def unapply(freeType: FreeType): Option[(TypeName, Type, String)]
+ }
+
+ /** Extracts free types from a tree that is reified or contains reified subtrees.
+ */
+ def freeTypes(tree: Tree): List[FreeType]
+
+ /** Substitutes free types in a reified tree.
+ */
+ def substituteFreeTypes(tree: Tree, subs: Map[FreeType, Type]): Tree
+
+ /** Substitutes free types in a reified type.
+ */
+ def substituteFreeTypes(tpe: Type, subs: Map[FreeType, Type]): Type
+}
diff --git a/src/library/scala/reflect/api/Importers.scala b/src/library/scala/reflect/api/Importers.scala
new file mode 100644
index 0000000000..1d8890b7db
--- /dev/null
+++ b/src/library/scala/reflect/api/Importers.scala
@@ -0,0 +1,19 @@
+package scala.reflect
+package api
+
+trait Importers { self: Universe =>
+
+ def mkImporter(from0: Universe): Importer { val from: from0.type }
+
+ trait Importer {
+ val from: Universe
+
+ val reverse: from.Importer { val from: self.type }
+
+ def importSymbol(sym: from.Symbol): Symbol
+
+ def importType(tpe: from.Type): Type
+
+ def importTree(tree: from.Tree): Tree
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala
index cea9e1a37d..ed8ead7aaf 100644
--- a/src/library/scala/reflect/api/Mirror.scala
+++ b/src/library/scala/reflect/api/Mirror.scala
@@ -5,7 +5,22 @@ package api
* runtime entities such as class names and object instances
* with a reflexive universe.
*/
-trait Mirror extends Universe with RuntimeTypes with TreeBuildUtil {
+trait Mirror extends Universe {
+
+ /** Class loader that is a mastermind behind the reflexive mirror.
+ *
+ * By default it is set to system classloader (more precisely, to the classloader that loads the `scala.reflect.package` class).
+ * However, sometimes it is useful to have a mirror services by a custom classloader.
+ *
+ * There are two ways to customize the `classLoader`:
+ * 1) Create a new mirror using the `scala.reflect.mkMirror(classLoader: ClassLoader)` method
+ * 2) Set `classLoader` to the new value
+ *
+ * The first, immutable, way should be strongly preferred in most situation.
+ * However sometimes it is necessary to migrate the default reflexive mirror (`scala.reflect.mirror`) to a new classloader.
+ * In that and only that case, use the setter, but be very careful not to introduce inconsistencies.
+ */
+ var classLoader: ClassLoader
/** The Scala class symbol that has given fully qualified name
* @param name The fully qualified name of the class to be returned
diff --git a/src/library/scala/reflect/api/Positions.scala b/src/library/scala/reflect/api/Positions.scala
index 91f1081b4d..8f01e0ced1 100644
--- a/src/library/scala/reflect/api/Positions.scala
+++ b/src/library/scala/reflect/api/Positions.scala
@@ -1,21 +1,202 @@
package scala.reflect
package api
-trait Positions { self: Universe =>
- /** TreeAnnotation is a generalisation of Position.
- *
- * TreeAnnotation cannot be an upperbound of Position since the corresponding classes
- * must live outside of the universe for backwards compatibility (see scala.tools.nsc.util.Position).
- * Thus, represent subtyping as coercions.
- *
- * Typically, positionToAnnotation is the identity, and annotationToPosition returns annot.pos
- */
- type TreeAnnotation // <: { def pos: Position }
- def NoTreeAnnotation: TreeAnnotation
- implicit def positionToAnnotation(pos: Position): TreeAnnotation // = pos
- def annotationToPosition(annot: TreeAnnotation): Position // = annot.pos
- def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = () // check that annot may overwrite tree.annot
-
- type Position // <: TreeAnnotation, but not practical to enforce this (would require moving Position, SourceFile, Reporter,... into the universe)
+trait Positions {
+ self: Universe =>
+
+ // [Eugene] in quite a lot of situations (mostly related to error reporting) we need positions in the API
+ // however it seems that neither runtime compilation, nor macros need facilities to create positions from scratch
+ // both emit ASTs, which can be automatically transformed into synthetic sources and assigned with synthetic positions
+ // hence I added possibilities to inspect everything we can, but add any position factories
+ // this simplified a lot of things, the biggest of them is that we don't need to expose SourceFile/AbstractFile
+ type Position <: scala.reflect.api.Position
val NoPosition: Position
-} \ No newline at end of file
+
+ /** A position that wraps a set of trees.
+ * The point of the wrapping position is the point of the default position.
+ * If some of the trees are ranges, returns a range position enclosing all ranges
+ * Otherwise returns default position.
+ */
+ def wrappingPos(default: Position, trees: List[Tree]): Position
+
+ /** A position that wraps the non-empty set of trees.
+ * The point of the wrapping position is the point of the first trees' position.
+ * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
+ * Otherwise returns a synthetic offset position to point.
+ */
+ def wrappingPos(trees: List[Tree]): Position
+
+ /** Ensure that given tree has no positions that overlap with
+ * any of the positions of `others`. This is done by
+ * shortening the range or assigning TransparentPositions
+ * to some of the nodes in `tree`.
+ */
+ def ensureNonOverlapping(tree: Tree, others: List[Tree])
+
+ /** Assigns a given position to all position-less nodes of a given AST.
+ */
+ def atPos[T <: Tree](pos: Position)(tree: T): T
+}
+
+/** The Position class and its subclasses represent positions of ASTs and symbols.
+ * Except for NoPosition and FakePos, every position refers to a SourceFile
+ * and to an offset in the sourcefile (its `point`). For batch compilation,
+ * that's all. For interactive IDE's there are also RangePositions
+ * and TransparentPositions. A RangePosition indicates a start and an end
+ * in addition to its point. TransparentPositions are a subclass of RangePositions.
+ * Range positions that are not transparent are called opaque.
+ * Trees with RangePositions need to satisfy the following invariants.
+ *
+ * INV1: A tree with an offset position never contains a child
+ * with a range position
+ * INV2: If the child of a tree with a range position also has a range position,
+ * then the child's range is contained in the parent's range.
+ * INV3: Opaque range positions of children of the same node are non-overlapping
+ * (this means their overlap is at most a single point).
+ *
+ * The following tests are useful on positions:
+ *
+ * pos.isDefined true if position is not a NoPosition nor a FakePosition
+ * pos.isRange true if position is a range
+ * pos.isOpaqueRange true if position is an opaque range
+ *
+ * The following accessor methods are provided:
+ *
+ * pos.source The source file of the position, which must be defined
+ * pos.point The offset of the position's point, which must be defined
+ * pos.start The start of the position, which must be a range
+ * pos.end The end of the position, which must be a range
+ *
+ * There are also convenience methods, such as
+ *
+ * pos.startOrPoint
+ * pos.endOrPoint
+ * pos.pointOrElse(default)
+ *
+ * These are less strict about the kind of position on which they can be applied.
+ *
+ * The following conversion methods are often used:
+ *
+ * pos.focus converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged.
+ * pos.makeTransparent converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
+ */
+trait Position extends Attachment {
+
+ /** Java file corresponding to the source file of this position.
+ */
+ def fileInfo: java.io.File
+
+ /** Content of the source file that contains this position.
+ */
+ def fileContent: Array[Char]
+
+ /** Is this position neither a NoPosition nor a FakePosition?
+ * If isDefined is true, offset and source are both defined.
+ */
+ def isDefined: Boolean
+
+ /** Is this position a transparent position? */
+ def isTransparent: Boolean
+
+ /** Is this position a range position? */
+ def isRange: Boolean
+
+ /** Is this position a non-transparent range position? */
+ def isOpaqueRange: Boolean
+
+ /** if opaque range, make this position transparent */
+ def makeTransparent: Position
+
+ /** The start of the position's range, error if not a range position */
+ def start: Int
+
+ /** The start of the position's range, or point if not a range position */
+ def startOrPoint: Int
+
+ /** The point (where the ^ is) of the position */
+ def point: Int
+
+ /** The point (where the ^ is) of the position, or else `default` if undefined */
+ def pointOrElse(default: Int): Int
+
+ /** The end of the position's range, error if not a range position */
+ def end: Int
+
+ /** The end of the position's range, or point if not a range position */
+ def endOrPoint: Int
+
+ /** The same position with a different start value (if a range) */
+ def withStart(off: Int): Position
+
+ /** The same position with a different end value (if a range) */
+ def withEnd(off: Int): Position
+
+ /** The same position with a different point value (if a range or offset) */
+ def withPoint(off: Int): Position
+
+ /** If this is a range, the union with the other range, with the point of this position.
+ * Otherwise, this position
+ */
+ def union(pos: Position): Position
+
+ /** If this is a range position, the offset position of its start.
+ * Otherwise the position itself
+ */
+ def focusStart: Position
+
+ /** If this is a range position, the offset position of its point.
+ * Otherwise the position itself
+ */
+ def focus: Position
+
+ /** If this is a range position, the offset position of its end.
+ * Otherwise the position itself
+ */
+ def focusEnd: Position
+
+ /** Does this position include the given position `pos`.
+ * This holds if `this` is a range position and its range [start..end]
+ * is the same or covers the range of the given position, which may or may not be a range position.
+ */
+ def includes(pos: Position): Boolean
+
+ /** Does this position properly include the given position `pos` ("properly" meaning their
+ * ranges are not the same)?
+ */
+ def properlyIncludes(pos: Position): Boolean
+
+ /** Does this position precede that position?
+ * This holds if both positions are defined and the end point of this position
+ * is not larger than the start point of the given position.
+ */
+ def precedes(pos: Position): Boolean
+
+ /** Does this position properly precede the given position `pos` ("properly" meaning their ranges
+ * do not share a common point).
+ */
+ def properlyPrecedes(pos: Position): Boolean
+
+ /** Does this position overlap with that position?
+ * This holds if both positions are ranges and there is an interval of
+ * non-zero length that is shared by both position ranges.
+ */
+ def overlaps(pos: Position): Boolean
+
+ /** Does this position cover the same range as that position?
+ * Holds only if both position are ranges
+ */
+ def sameRange(pos: Position): Boolean
+
+ def line: Int
+
+ def column: Int
+
+ /** Convert this to a position around `point` that spans a single source line */
+ def toSingleLine: Position
+
+ def lineContent: String
+
+ def show: String
+}
diff --git a/src/library/scala/reflect/api/Reporters.scala b/src/library/scala/reflect/api/Reporters.scala
new file mode 100644
index 0000000000..b7428e1599
--- /dev/null
+++ b/src/library/scala/reflect/api/Reporters.scala
@@ -0,0 +1,65 @@
+package scala.reflect
+package api
+
+trait Reporters { self: Universe =>
+
+ trait Reporter {
+ object severity extends Enumeration
+ class Severity(val id: Int) extends severity.Value {
+ var count: Int = 0
+ override def toString() = this match {
+ case INFO => "INFO"
+ case WARNING => "WARNING"
+ case ERROR => "ERROR"
+ case _ => "<unknown>"
+ }
+ }
+ val INFO = new Severity(0)
+ val WARNING = new Severity(1)
+ val ERROR = new Severity(2)
+
+ case class Info(val pos: Position, val msg: String, val severity: Severity)
+ val infos = new collection.mutable.LinkedHashSet[Info]
+
+ /** Handles incoming info */
+ def log(pos: Position, msg: String, severity: Severity) {
+ infos += new Info(pos, msg, severity)
+ severity.count += 1
+ display(infos.last)
+ }
+
+ /** Displays incoming info */
+ def display(info: Info): Unit
+
+ /** Services a request to drop into interactive mode */
+ def interactive(): Unit
+
+ /** Refreshes the UI */
+ def flush(): Unit = {}
+
+ /** Resets the reporter */
+ def reset(): Unit = {
+ INFO.count = 0
+ WARNING.count = 0
+ ERROR.count = 0
+ infos.clear()
+ }
+ }
+
+ class SilentReporter extends Reporter {
+ def display(info: Info) {}
+ def interactive() {}
+ }
+
+ /** Creates a UI-less reporter that simply accumulates all the messages
+ */
+ def mkSilentReporter(): Reporter = new SilentReporter()
+
+ /** Creates a reporter that prints messages to the console according to the settings.
+ *
+ * ``minSeverity'' determines minimum severity of the messages to be printed.
+ * 0 stands for INFO, 1 stands for WARNING and 2 stands for ERROR.
+ */
+ // todo. untangle warningsAsErrors from Reporters. I don't feel like moving this flag here!
+ def mkConsoleReporter(minSeverity: Int = 1): Reporter
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/RuntimeTypes.scala b/src/library/scala/reflect/api/RuntimeTypes.scala
deleted file mode 100644
index f58b328868..0000000000
--- a/src/library/scala/reflect/api/RuntimeTypes.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package scala.reflect
-package api
-
-/** A mirror establishes connections of
- * runtime entities such as class names and object instances
- * with a refexive universe.
- */
-private[reflect] trait RuntimeTypes extends Universe {
-
- type InstanceRefSymbol >: Null <: Symbol
-
- val InstanceRefSymbol: InstanceRefSymbolExtractor
-
- private[reflect] def namedType(pre: Type, sym: Symbol, args: List[Type]): Type
-
- abstract class InstanceRefSymbolExtractor {
- def apply(value: AnyRef): InstanceRefSymbol
- def unapply(tpe: InstanceRefSymbol): Option[AnyRef]
- }
-}
diff --git a/src/library/scala/reflect/api/Scopes.scala b/src/library/scala/reflect/api/Scopes.scala
index d4e4e24f29..4a5702eadc 100755
--- a/src/library/scala/reflect/api/Scopes.scala
+++ b/src/library/scala/reflect/api/Scopes.scala
@@ -5,7 +5,12 @@ trait Scopes { self: Universe =>
type Scope <: Iterable[Symbol]
- def newScope(): Scope
-}
+ /** Create a new scope */
+ def newScope: Scope
+ /** Create a new scope nested in another one with which it shares its elements */
+ def newNestedScope(outer: Scope): Scope
+ /** Create a new scope with given initial elements */
+ def newScopeWith(elems: Symbol*): Scope
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala
index c3d989f971..b4fedbe055 100755
--- a/src/library/scala/reflect/api/StandardDefinitions.scala
+++ b/src/library/scala/reflect/api/StandardDefinitions.scala
@@ -8,6 +8,23 @@ package api
trait StandardDefinitions { self: Universe =>
+ val ByteTpe: Type
+ val ShortTpe: Type
+ val CharTpe: Type
+ val IntTpe: Type
+ val LongTpe: Type
+ val FloatTpe: Type
+ val DoubleTpe: Type
+ val BooleanTpe: Type
+ val UnitTpe: Type
+ val AnyTpe: Type
+ val ObjectTpe: Type
+ val AnyValTpe: Type
+ val AnyRefTpe: Type
+ val NothingTpe: Type
+ val NullTpe: Type
+ val StringTpe: Type
+
val definitions: AbsDefinitions
abstract class AbsDefinitions {
@@ -15,7 +32,11 @@ trait StandardDefinitions { self: Universe =>
def RootPackage: Symbol
def RootClass: Symbol
def EmptyPackage: Symbol
+ def EmptyPackageClass: Symbol
def ScalaPackage: Symbol
+ def ScalaPackageClass: Symbol
+ def JavaLangPackage: Symbol
+ def JavaLangPackageClass: Symbol
// top types
def AnyClass : Symbol
@@ -37,6 +58,7 @@ trait StandardDefinitions { self: Universe =>
def FloatClass : Symbol
def DoubleClass : Symbol
def BooleanClass: Symbol
+ def ScalaPrimitiveValueClasses: List[Symbol]
// fundamental reference classes
def SymbolClass : Symbol
@@ -48,13 +70,57 @@ trait StandardDefinitions { self: Universe =>
def ProductClass : Array[Symbol]
def FunctionClass : Array[Symbol]
- // fundamental modules
+ // Option classes
+ def OptionClass: Symbol
+ def SomeClass: Symbol
+ def NoneModule: Symbol
+ def SomeModule: Symbol
+
+ // collections classes
+ def ConsClass: Symbol
+ def IterableClass: Symbol
+ def IteratorClass: Symbol
+ def ListClass: Symbol
+ def SeqClass: Symbol
+ def StringBuilderClass: Symbol
+ def TraversableClass: Symbol
+
+ // collections modules
def PredefModule: Symbol
+ def ListModule: Symbol
+ def List_apply: Symbol
+ def NilModule: Symbol
+ def SeqModule: Symbol
+ def IteratorModule: Symbol
+ def Iterator_apply: Symbol
+
+ // arrays and their members
+ def ArrayModule: Symbol
+ def ArrayModule_overloadedApply: Symbol
+ def ArrayClass: Symbol
+ def Array_apply: Symbol
+ def Array_update: Symbol
+ def Array_length: Symbol
+ def Array_clone: Symbol
+
+ // special parameter types
+ def ByNameParamClass: Symbol
+ def JavaRepeatedParamClass: Symbol
+ def RepeatedParamClass: Symbol
+
+ // type tags
+ def ClassTagClass: Symbol
+ def ClassTagModule: Symbol
+ def TypeTagClass: Symbol
+ def TypeTagModule: Symbol
+ def GroundTypeTagClass: Symbol
+ def GroundTypeTagModule: Symbol
/** Given a type T, returns the type corresponding to the VM's
* representation: ClassClass's type constructor applied to `arg`.
*/
def vmClassType(arg: Type): Type // !!! better name?
+ // [Eugene] we already have arg.erasure, right?
/** The string representation used by the given type in the VM.
*/
diff --git a/src/library/scala/reflect/api/StandardNames.scala b/src/library/scala/reflect/api/StandardNames.scala
index 81517d2a6b..bfc165f613 100644
--- a/src/library/scala/reflect/api/StandardNames.scala
+++ b/src/library/scala/reflect/api/StandardNames.scala
@@ -8,14 +8,166 @@ package api
trait StandardNames { self: Universe =>
+ abstract class AbsNames {
+ type NameType <: Name
+
+ val EMPTY: NameType
+ val ANON_FUN_NAME: NameType
+ val ANON_CLASS_NAME: NameType
+ val EMPTY_PACKAGE_NAME: NameType
+ val IMPORT: NameType
+ val MODULE_VAR_SUFFIX: NameType
+ val ROOT: NameType
+ val PACKAGE: NameType
+ val SPECIALIZED_SUFFIX: NameType
+
+ val ERROR: NameType
+ val NO_NAME: NameType
+ val WILDCARD: NameType
+
+ def flattenedName(segments: Name*): NameType
+ }
+
val nme: AbsTermNames
- abstract class AbsTermNames {
+ abstract class AbsTermNames extends AbsNames {
+ val EXPAND_SEPARATOR_STRING: String
+
+ val ANYNAME: TermName
val CONSTRUCTOR: TermName
+ val FAKE_LOCAL_THIS: TermName
+ val INITIALIZER: TermName
+ val LAZY_LOCAL: TermName
+ val LOCAL_SUFFIX_STRING: String
+ val MIRROR_PREFIX: TermName
+ val MIRROR_SHORT: TermName
+ val MIRROR_FREE_PREFIX: TermName
+ val MIRROR_FREE_THIS_SUFFIX: TermName
+ val MIRROR_FREE_VALUE_SUFFIX: TermName
+ val MIXIN_CONSTRUCTOR: TermName
+ val MODULE_INSTANCE_FIELD: TermName
+ val OUTER: TermName
+ val OUTER_LOCAL: TermName
+ val OUTER_SYNTH: TermName
+ val SELECTOR_DUMMY: TermName
+ val SELF: TermName
+ val SPECIALIZED_INSTANCE: TermName
+ val STAR: TermName
+ val THIS: TermName
+
+ val BITMAP_NORMAL: TermName
+ val BITMAP_TRANSIENT: TermName
+ val BITMAP_PRIVATE: TermName
+ val BITMAP_CHECKINIT: TermName
+ val BITMAP_CHECKINIT_TRANSIENT: TermName
+
+ val INTERPRETER_IMPORT_WRAPPER: String
+ val INTERPRETER_LINE_PREFIX: String
+ val INTERPRETER_VAR_PREFIX: String
+ val INTERPRETER_WRAPPER_SUFFIX: String
+
+ val ROOTPKG: TermName
+
+ val ADD: TermName
+ val AND: TermName
+ val ASR: TermName
+ val DIV: TermName
+ val EQ: TermName
+ val EQL: TermName
+ val GE: TermName
+ val GT: TermName
+ val HASHHASH: TermName
+ val LE: TermName
+ val LSL: TermName
+ val LSR: TermName
+ val LT: TermName
+ val MINUS: TermName
+ val MOD: TermName
+ val MUL: TermName
+ val NE: TermName
+ val OR: TermName
+ val PLUS : TermName
+ val SUB: TermName
+ val XOR: TermName
+ val ZAND: TermName
+ val ZOR: TermName
+
+ // [Eugene] this doesn't compile. why?!
+// val UNARY_~: TermName
+// val UNARY_+: TermName
+// val UNARY_-: TermName
+// val UNARY_!: TermName
+ val UNARY_TILDE: TermName
+ val UNARY_PLUS: TermName
+ val UNARY_MINUS: TermName
+ val UNARY_NOT: TermName
+
+ // [Eugene] this doesn't compile. why?!
+// val ???: TermName
+ val QQQ: TermName
+
+ val MODULE_SUFFIX_NAME: TermName
+ val NAME_JOIN_NAME: TermName
+ val IMPL_CLASS_SUFFIX: String
+ val LOCALDUMMY_PREFIX: String
+ val PROTECTED_PREFIX: String
+ val PROTECTED_SET_PREFIX: String
+ val SINGLETON_SUFFIX: String
+ val SUPER_PREFIX_STRING: String
+ val TRAIT_SETTER_SEPARATOR_STRING: String
+ val SETTER_SUFFIX: TermName
+
+ def isConstructorName(name: Name): Boolean
+ def isExceptionResultName(name: Name): Boolean
+ def isImplClassName(name: Name): Boolean
+ def isLocalDummyName(name: Name): Boolean
+ def isLocalName(name: Name): Boolean
+ def isLoopHeaderLabel(name: Name): Boolean
+ def isProtectedAccessorName(name: Name): Boolean
+ def isSuperAccessorName(name: Name): Boolean
+ def isReplWrapperName(name: Name): Boolean
+ def isSetterName(name: Name): Boolean
+ def isTraitSetterName(name: Name): Boolean
+ def isSingletonName(name: Name): Boolean
+ def isModuleName(name: Name): Boolean
+ def isOpAssignmentName(name: Name): Boolean
+
+ def segments(name: String, assumeTerm: Boolean): List[Name]
+ def originalName(name: Name): Name
+ def stripModuleSuffix(name: Name): Name
+ def unspecializedName(name: Name): Name
+ def splitSpecializedName(name: Name): (Name, String, String)
+ def dropLocalSuffix(name: Name): Name
+
+ def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName
+ def expandedSetterName(name: TermName, base: Symbol): TermName
+ def protName(name: Name): TermName
+ def protSetterName(name: Name): TermName
+ def getterName(name: TermName): TermName
+ def getterToLocal(name: TermName): TermName
+ def getterToSetter(name: TermName): TermName
+ def localToGetter(name: TermName): TermName
+ def setterToGetter(name: TermName): TermName
+ def defaultGetterName(name: Name, pos: Int): TermName
+ def defaultGetterToMethod(name: Name): TermName
+
+ def dropSingletonName(name: Name): TypeName
+ def singletonName(name: Name): TypeName
+ def implClassName(name: Name): TypeName
+ def interfaceName(implname: Name): TypeName
+ def localDummyName(clazz: Symbol): TermName
+ def superName(name: Name): TermName
}
val tpnme: AbsTypeNames
- abstract class AbsTypeNames {
+ abstract class AbsTypeNames extends AbsNames {
+ val REFINE_CLASS_NAME: TypeName
+ val BYNAME_PARAM_CLASS_NAME: TypeName
+ val EQUALS_PATTERN_NAME: TypeName
+ val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName
+ val LOCAL_CHILD: TypeName
+ val REPEATED_PARAM_CLASS_NAME: TypeName
+ val WILDCARD_STAR: TypeName
}
}
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index ab59a4a39a..a154e5f7a0 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -7,6 +7,10 @@ trait Symbols { self: Universe =>
abstract class AbsSymbol { this: Symbol =>
+ /** The position of this symbol
+ */
+ def pos: Position
+
/** The modifiers of this symbol
*/
def modifiers: Set[Modifier]
@@ -47,6 +51,10 @@ trait Symbols { self: Universe =>
/** An id number which is unique for all symbols in this universe */
def id: Int
+ /** ...
+ */
+ def orElse[T](alt: => Symbol): Symbol
+
/**
* Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
*
@@ -112,6 +120,20 @@ trait Symbols { self: Universe =>
*/
def isTerm : Boolean
+ /** Does this symbol represent the definition of method?
+ * If yes, `isTerm` is also guaranteed to be true.
+ */
+ def isMethod : Boolean
+
+ /** Is this symbol an overloaded method?
+ */
+ def isOverloaded : Boolean
+
+ /** Does this symbol represent a free term captured by reification?
+ */
+ // needed for ones who wish to inspect reified trees
+ def isFreeTerm : Boolean
+
/** Does this symbol represent the definition of type?
* Note that every symbol is either a term or a type.
* So for every symbol `sym`, either `sym.isTerm` is true
@@ -124,6 +146,17 @@ trait Symbols { self: Universe =>
*/
def isClass : Boolean
+ /** Does this symbol represent the definition of a primitive class?
+ * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
+ * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ */
+ def isPrimitiveValueClass: Boolean
+
+ /** Does this symbol represent the definition of a custom value class?
+ * Namely, is AnyVal among its parent classes?
+ */
+ def isDerivedValueClass: Boolean
+
/** Does this symbol represent the definition of a type alias?
* If yes, `isType` is also guaranteed to be true.
*/
@@ -134,9 +167,28 @@ trait Symbols { self: Universe =>
*/
def isAbstractType : Boolean
- /** Is this symbol an overloaded method?
+ /** Does this symbol represent the definition of a skolem?
+ * Skolems are used during typechecking to represent type parameters viewed from inside their scopes.
+ * If yes, `isType` is also guaranteed to be true.
*/
- def isOverloaded: Boolean
+ def isSkolem : Boolean
+
+ /** Does this symbol represent a free type captured by reification?
+ */
+ // needed for ones who wish to inspect reified trees
+ def isFreeType : Boolean
+
+ /** Is the type parameter represented by this symbol contravariant?
+ */
+ def isContravariant : Boolean
+
+ /** Is the type parameter represented by this symbol contravariant?
+ */
+ def isCovariant : Boolean
+
+ /** Does this symbol or its underlying type represent a typechecking error?
+ */
+ def isErroneous : Boolean
/** The type signature of this symbol.
* Note if the symbol is a member of a class, one almost always is interested
@@ -192,7 +244,7 @@ trait Symbols { self: Universe =>
/** A fresh symbol with given name `name`, position `pos` and flags `flags` that has
* the current symbol as its owner.
*/
- def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol // needed by LiftCode
+ def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol // needed by LiftCode !!! not enough reason to have in the api
/** Low-level operation to set the symbol's flags
* @return the symbol itself
@@ -207,6 +259,9 @@ trait Symbols { self: Universe =>
/** Set symbol's annotations to given annotations `annots`.
*/
def setAnnotations(annots: AnnotationInfo*): this.type // needed by LiftCode !!! not enough reason to have in the api
+
+ /** The kind of this symbol; used for debugging */
+ def kind: String
}
val NoSymbol: Symbol
diff --git a/src/library/scala/reflect/api/ToolBoxes.scala b/src/library/scala/reflect/api/ToolBoxes.scala
new file mode 100644
index 0000000000..387ef5163b
--- /dev/null
+++ b/src/library/scala/reflect/api/ToolBoxes.scala
@@ -0,0 +1,90 @@
+package scala.reflect
+package api
+
+trait ToolBoxes { self: Universe =>
+
+ type ToolBox <: AbsToolBox
+
+ def mkToolBox(reporter: Reporter = mkSilentReporter(), options: String = ""): AbsToolBox
+
+ // [Eugene] what do you think about the interface? namely about the ``freeTypes'' part.
+ trait AbsToolBox {
+
+ /** UI of the toolbox.
+ *
+ * Accumulates and displays warnings and errors, can drop to interactive mode (if supported).
+ * The latter can be useful to study the typechecker or to debug complex macros.
+ */
+ def reporter: Reporter
+
+ /** Typechecks a tree using this ToolBox.
+ * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings.
+ *
+ * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols),
+ * then they might, might be partially or might not be specified in the ``freeTypes'' parameter.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Ydebug.
+ *
+ * Typechecking can be steered with the following optional parameters:
+ * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false
+ * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false
+ */
+ def typeCheck(tree: Tree, pt: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit value of the expected type ``pt'' in the macro callsite context.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context.
+ *
+ * Otional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported.
+ * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree
+
+ /** Recursively resets symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetAllAttrs[T <: Tree](tree: T): T
+
+ /** Recursively resets locally defined symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetLocalAttrs[T <: Tree](tree: T): T
+
+ /** Compiles and runs a tree using this ToolBox.
+ *
+ * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols),
+ * then they all have to be specified in the ``freeTypes'' parameter or an error occurs.
+ *
+ * This spawns the compiler at the Namer phase, and pipelines the tree through that compiler.
+ * Currently ``runExpr'' does not accept trees that already typechecked, because typechecking isn't idempotent.
+ * For more info, take a look at https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def runExpr(tree: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any
+
+ /** Represents an error during toolboxing
+ */
+ type ToolBoxError <: Throwable
+ val ToolBoxError: ToolBoxErrorExtractor
+ abstract class ToolBoxErrorExtractor {
+ def unapply(error: ToolBoxError): Option[(ToolBox, String)]
+ }
+ }
+} \ 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 f28008bc21..32d7eefa5b 100644
--- a/src/library/scala/reflect/api/TreeBuildUtil.scala
+++ b/src/library/scala/reflect/api/TreeBuildUtil.scala
@@ -1,46 +1,127 @@
-package scala.reflect.api
+package scala.reflect
+package api
-trait TreeBuildUtil extends Universe {
+trait TreeBuildUtil { self: Universe =>
- /** The symbol corresponding to the globally accessible class with the
- * given fully qualified name `fullName`.
+ /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`.
+ * Unlike `staticClassIfDefined`, throws `MissingRequirementError` is requested class cannot be found.
*/
def staticClass(fullName: String): Symbol
- /** The symbol corresponding to the globally accessible object with the
- * given fully qualified name `fullName`.
+ /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`.
+ * Unlike `staticClass`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested class cannot be found.
+ */
+ def staticClassIfDefined(fullName: String): Symbol
+
+ /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`.
+ * Unlike `staticModuleIfDefined`, throws `MissingRequirementError` is requested object cannot be found.
*/
def staticModule(fullName: String): Symbol
+ /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`.
+ * Unlike `staticModule`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested object cannot be found.
+ */
+ def staticModuleIfDefined(fullName: String): Symbol
+
/** The this-ptype of the globally accessible object with the
* given fully qualified name `fullName`.
*/
def thisModuleType(fullName: String): Type
/** Selects type symbol with given simple name `name` from the defined members of `owner`.
+ * Unlike `selectTypeIfDefined`, throws `MissingRequirementError` is requested type symbol cannot be found.
*/
def selectType(owner: Symbol, name: String): Symbol
+ /** Selects type symbol with given simple name `name` from the defined members of `owner`.
+ * Unlike `selectType`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested type symbol cannot be found.
+ */
+ def selectTypeIfDefined(owner: Symbol, name: String): Symbol
+
/** Selects term symbol with given name and type from the defined members of prefix type
- * @pre The prefix type
- * @name The name of the selected member
+ * Unlike `selectTermIfDefined`, throws `MissingRequirementError` is requested term symbol cannot be found.
*/
def selectTerm(owner: Symbol, name: String): Symbol
- def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol
+ /** Selects term symbol with given name and type from the defined members of prefix type
+ * Unlike `selectTerm`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested term symbol cannot be found.
+ */
+ def selectTermIfDefined(owner: Symbol, name: String): Symbol
- def selectParam(owner: Symbol, idx: Int): Symbol
+ /** Selects overloaded method symbol with given name and index
+ * Unlike `selectOverloadedMethodIfDefined`, throws `MissingRequirementError` is requested overloaded method cannot be found.
+ */
+ def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol
- def newScopeWith(decls: Symbol*): Scope
+ /** Selects overloaded method symbol with given name and index
+ * Unlike `selectOverloadedMethod`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested overloaded method cannot be found.
+ */
+ def selectOverloadedMethodIfDefined(owner: Symbol, name: String, index: Int): Symbol
- /** Create a fresh free variable symbol.
+ /** Create a fresh free term symbol.
* @param name the name of the free variable
- * @param tsig the type signature of the free variable
+ * @param info the type signature of the free variable
* @param value the value of the free variable at runtime
+ * @param origin debug information that tells where this symbol comes from
*/
- def newFreeVar(name: String, info: Type, value: Any): Symbol
+ def newFreeTerm(name: String, info: Type, value: => Any, origin: String): Symbol
+
+ /** Create a fresh free type symbol.
+ * @param name the name of the free variable
+ * @param info the type signature of the free variable
+ * @param value a type tag that captures the value of the free variable
+ * is completely phantom, since the captured type cannot be propagated to the runtime
+ * if it could be, we wouldn't be creating a free type to begin with
+ * the only usage for it is preserving the captured symbol for compile-time analysis
+ * @param origin debug information that tells where this symbol comes from
+ */
+ def newFreeType(name: String, info: Type, value: => Any, origin: String): Symbol
/** Create a Modiiers structure given internal flags, qualifier, annotations */
def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers
-} \ No newline at end of file
+ val gen: TreeGen { val global: TreeBuildUtil.this.type }
+
+ type TreeGen <: AbsTreeGen
+}
+
+// [Eugene to Paul] we need to expose some of the functionality provided by TreeGen
+// I added some stuff that was necessary for typetag materialization macros
+// but we should think it over and pick other generally useful stuff
+// same goes for tree traversers/transformers, type maps, etc
+// and once we expose all that, there's another question: how do we stay in sync?
+trait AbsTreeGen {
+ val global: Universe
+
+ import global._
+ import definitions._
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * The type must be suitable for this. For example, it
+ * must not be a TypeRef pointing to an abstract type variable.
+ */
+ def mkAttributedQualifier(tpe: Type): Tree
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * If the type is unsuitable, e.g. it is a TypeRef for an
+ * abstract type variable, then an Ident will be made using
+ * termSym as the Ident's symbol. In that case, termSym must
+ * not be NoSymbol.
+ */
+ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree
+
+ /** Builds a typed reference to given symbol with given stable prefix. */
+ def mkAttributedRef(pre: Type, sym: Symbol): Tree
+
+ /** Builds a typed reference to given symbol. */
+ def mkAttributedRef(sym: Symbol): Tree
+
+ /** Builds a typed This reference to given symbol. */
+ def mkAttributedThis(sym: Symbol): Tree
+
+ /** Builds a typed Ident with an underlying symbol. */
+ def mkAttributedIdent(sym: Symbol): Tree
+
+ /** Builds a typed Select with an underlying symbol. */
+ def mkAttributedSelect(qual: Tree, sym: Symbol): Tree
+}
diff --git a/src/library/scala/reflect/api/TreePrinters.scala b/src/library/scala/reflect/api/TreePrinters.scala
index 43865915d3..3d64ec8e40 100644
--- a/src/library/scala/reflect/api/TreePrinters.scala
+++ b/src/library/scala/reflect/api/TreePrinters.scala
@@ -29,17 +29,21 @@ trait TreePrinters { self: Universe =>
def newTreePrinter(out: PrintWriter): TreePrinter
// emits more or less verbatim representation of the provided tree
- // todo. when LiftCode becomes a macro, throw this code away and use that macro
class RawTreePrinter(out: PrintWriter) extends TreePrinter {
+ val EmptyValDef = self.emptyValDef
def print(args: Any*): Unit = args foreach {
case EmptyTree =>
print("EmptyTree")
+ case EmptyValDef =>
+ print("emptyValDef")
case tree @ TypeTree() =>
print("TypeTree()")
if (tree.tpe != null)
print(".setType(", tree.tpe, ")")
else if (tree.original != null)
print(".setOriginal(", tree.original, ")")
+ case Literal(Constant(s: String)) =>
+ print("Literal(Constant(\"" + s + "\"))")
case tree: Tree =>
print(tree.printingPrefix+"(")
val it = tree.productIterator
diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala
index d8180fe029..01f948809c 100644
--- a/src/library/scala/reflect/api/Trees.scala
+++ b/src/library/scala/reflect/api/Trees.scala
@@ -14,6 +14,7 @@ trait Trees { self: Universe =>
private[scala] var nodeCount = 0
type Modifiers >: Null <: AbsModifiers
+ val NoMods: Modifiers
abstract class AbsModifiers {
def modifiers: Set[Modifier]
@@ -80,18 +81,14 @@ trait Trees { self: Universe =>
*/
def printingPrefix = productPrefix
- def pos: Position = annotationToPosition(rawannot)
- def pos_=(pos: Position): Unit = annotation = pos
+ def pos: Position = rawatt.pos.asInstanceOf[Position] // [Eugene] how do we get rid of this cast?
+ def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) // the "withPos" part is crucial to robustness
def setPos(newpos: Position): this.type = { pos = newpos; this }
- private[this] var rawannot: TreeAnnotation = NoTreeAnnotation
- def annotation: TreeAnnotation = rawannot
- def annotation_=(annot: TreeAnnotation): Unit = {
- _checkSetAnnotation(this, annot)
- rawannot = annot
- }
-
- def setAnnotation(annot: TreeAnnotation): this.type = { annotation = annot; this }
+ private[this] var rawatt: Attachment = NoPosition
+ def attachment: Attachment = rawatt
+ def attachment_=(att: Attachment): Unit = rawatt = att
+ def setAttachment(att: Attachment): this.type = { rawatt = att; this }
private[this] var rawtpe: Type = _
@@ -143,6 +140,7 @@ trait Trees { self: Universe =>
def hasSymbol = false
def isDef = false
def isEmpty = false
+ def orElse(alt: => Tree) = if (!isEmpty) this else alt
def hasSymbolWhich(f: Symbol => Boolean) = hasSymbol && f(symbol)
@@ -179,6 +177,13 @@ trait Trees { self: Universe =>
}
def filter(f: Tree => Boolean): List[Tree] = withFilter(f)
+ /** Apply `pf' to each subtree on which the function is defined */
+ def collect[T](pf: PartialFunction[Tree, T]): List[T] = {
+ val ctt = new CollectTreeTraverser[T](pf)
+ ctt.traverse(this)
+ ctt.results.toList
+ }
+
/** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p`,
* or None if none exists.
*/
@@ -188,9 +193,12 @@ trait Trees { self: Universe =>
ft.result
}
- /** Is there part of this tree which satisfies predicate `p`? */
+ /** Is there exists a part of this tree which satisfies predicate `p`? */
def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty
+ /** Do all parts of this tree satisfy predicate `p`? */
+ def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty
+
def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _)
def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean =
f(this, that) || ((this.productArity == that.productArity) && {
@@ -230,7 +238,7 @@ trait Trees { self: Universe =>
duplicateTree(this).asInstanceOf[this.type]
private[scala] def copyAttrs(tree: Tree): this.type = {
- annotation = tree.annotation
+ attachment = tree.attachment
tpe = tree.tpe
if (hasSymbol) symbol = tree.symbol
this
@@ -241,6 +249,34 @@ trait Trees { self: Universe =>
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
}
+ // [Eugene] uh-oh
+ // locker.comp:
+ // [mkdir] Created dir: C:\Projects\Kepler\build\locker\classes\compiler
+ // [scalacfork] Compiling 471 files to C:\Projects\Kepler\build\locker\classes\compiler
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+ // [scalacfork] amb prefix: Importers.this.type#class Tree Importer.this.from.type#class Tree
+// object Tree {
+// // would be great if in future this generated an Expr[Magic]
+// // where Magic is a magic untyped type that propagates through the entire quasiquote
+// // and turns off typechecking whenever it's involved
+// // that'd allow us to splice trees into quasiquotes and still have these qqs to be partially typechecked
+// // see some exploration of these ideas here: https://github.com/xeno-by/alphakeplerdemo
+// implicit def tree2expr(tree: Tree): Expr[Nothing] = Expr[Nothing](tree)
+// implicit def expr2tree(expr: Expr[_]): Tree = expr.tree
+//
+// // [Eugene] good idea?
+// implicit def trees2exprs(trees: List[Tree]): List[Expr[Nothing]] = trees map tree2expr
+// implicit def exprs2trees(exprs: List[Expr[_]]): List[Tree] = exprs map expr2tree
+// }
+
/** A tree for a term. Not all terms are TermTrees; use isTerm
* to reliably identify terms.
*/
@@ -319,12 +355,23 @@ trait Trees { self: Universe =>
case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template)
extends ImplDef
+ /** @param sym the class symbol
+ * @return the implementation template
+ */
+ def ClassDef(sym: Symbol, impl: Template): ClassDef
+
/** An object definition, e.g. `object Foo`. Internally, objects are
* quite frequently called modules to reduce ambiguity.
*/
case class ModuleDef(mods: Modifiers, name: TermName, impl: Template)
extends ImplDef
+ /**
+ * @param sym the class symbol
+ * @param impl the implementation template
+ */
+ def ModuleDef(sym: Symbol, impl: Template): ModuleDef
+
/** A common base class for ValDefs and DefDefs.
*/
abstract class ValOrDefDef extends MemberDef {
@@ -343,17 +390,37 @@ trait Trees { self: Universe =>
*/
case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef
+ def ValDef(sym: Symbol, rhs: Tree): ValDef
+
+ def ValDef(sym: Symbol): ValDef
+
/** A method or macro definition.
* @param name The name of the method or macro. Can be a type name in case this is a type macro
*/
case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef
+ def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef
+
/** An abstract type, a type parameter, or a type alias.
*/
case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree)
extends MemberDef
+ /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */
+ def TypeDef(sym: Symbol, rhs: Tree): TypeDef
+
+ /** A TypeDef node which defines abstract type or type parameter for given `sym` */
+ def TypeDef(sym: Symbol): TypeDef
+
/** A labelled expression. Not expressible in language syntax, but
* generated by the compiler to simulate while/do-while loops, and
* also by the pattern matcher.
@@ -371,6 +438,8 @@ trait Trees { self: Universe =>
case class LabelDef(name: TermName, params: List[Ident], rhs: Tree)
extends DefTree with TermTree
+ def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef
+
/** Import selector
*
* Representation of an imported name its optional rename and their optional positions
@@ -415,12 +484,19 @@ trait Trees { self: Universe =>
case class Block(stats: List[Tree], expr: Tree)
extends TermTree
+ /** Block factory that flattens directly nested blocks.
+ */
+ def Block(stats: Tree*): Block
+
/** Case clause in a pattern match, eliminated during explicitouter
* (except for occurrences in switch statements)
*/
case class CaseDef(pat: Tree, guard: Tree, body: Tree)
extends Tree
+ /** casedef shorthand */
+ def CaseDef(pat: Tree, body: Tree): CaseDef
+
/** Alternatives of patterns, eliminated by explicitouter, except for
* occurrences in encoded Switch stmt (=remaining Match(CaseDef(...))
*/
@@ -439,6 +515,8 @@ trait Trees { self: Universe =>
case class Bind(name: Name, body: Tree)
extends DefTree
+ def Bind(sym: Symbol, body: Tree): Bind
+
case class UnApply(fun: Tree, args: List[Tree])
extends TermTree
@@ -489,10 +567,14 @@ trait Trees { self: Universe =>
case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree)
extends TermTree
+ def Try(body: Tree, cases: (Tree, Tree)*): Try
+
/** Throw expression */
case class Throw(expr: Tree)
extends TermTree
+ def Throw(tpe: Type, args: Tree*): Throw
+
/** Object instantiation
* One should always use factory method below to build a user level new.
*
@@ -503,14 +585,13 @@ trait Trees { self: Universe =>
/** Factory method for object creation `new tpt(args_1)...(args_n)`
* A `New(t, as)` is expanded to: `(new t).<init>(as)`
*/
- def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match {
- case Nil => new ApplyConstructor(tpt, Nil)
- case xs :: rest => rest.foldLeft(new ApplyConstructor(tpt, xs): Tree)(Apply)
- }
+ def New(tpt: Tree, argss: List[List[Tree]]): Tree
+
/** 0-1 argument list new, based on a type.
*/
- def New(tpe: Type, args: Tree*): Tree =
- new ApplyConstructor(TypeTree(tpe), args.toList)
+ def New(tpe: Type, args: Tree*): Tree
+
+ def New(sym: Symbol, args: Tree*): Tree
/** Type annotation, eliminated by explicit outer */
case class Typed(expr: Tree, tpt: Tree)
@@ -545,6 +626,8 @@ trait Trees { self: Universe =>
override def symbol_=(sym: Symbol) { fun.symbol = sym }
}
+ def Apply(sym: Symbol, args: Tree*): Tree
+
class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args)
class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args)
@@ -563,7 +646,9 @@ trait Trees { self: Universe =>
extends TermTree with SymTree
// The symbol of an ApplyDynamic is the function symbol of `qual`, or NoSymbol, if there is none.
- /** Super reference, qual = corresponding this reference */
+ /** Super reference, qual = corresponding this reference
+ * A super reference C.super[M] is represented as Super(This(C), M).
+ */
case class Super(qual: Tree, mix: TypeName) extends TermTree {
// The symbol of a Super is the class _from_ which the super reference is made.
// For instance in C.super(...), it would be C.
@@ -571,38 +656,47 @@ trait Trees { self: Universe =>
override def symbol_=(sym: Symbol) { qual.symbol = sym }
}
+ def Super(sym: Symbol, mix: TypeName): Tree
+
/** Self reference */
case class This(qual: TypeName)
extends TermTree with SymTree
// The symbol of a This is the class to which the this refers.
// For instance in C.this, it would be C.
- def This(sym: Symbol): Tree =
- This(sym.name.toTypeName) setSymbol sym
+ def This(sym: Symbol): Tree
/** Designator <qualifier> . <name> */
case class Select(qualifier: Tree, name: Name)
extends RefTree
- def Select(qualifier: Tree, name: String): Select =
- Select(qualifier, newTermName(name))
+ def Select(qualifier: Tree, name: String): Select
- def Select(qualifier: Tree, sym: Symbol): Select =
- Select(qualifier, sym.name) setSymbol sym
+ def Select(qualifier: Tree, sym: Symbol): Select
/** Identifier <name> */
case class Ident(name: Name) extends RefTree {
def qualifier: Tree = EmptyTree
}
- def Ident(name: String): Ident =
- Ident(newTermName(name))
+ def Ident(name: String): Ident
- def Ident(sym: Symbol): Ident =
- Ident(sym.name) setSymbol sym
+ def Ident(sym: Symbol): Ident
class BackQuotedIdent(name: Name) extends Ident(name)
+ /** Marks underlying reference to id as boxed.
+ * @pre: id must refer to a captured variable
+ * A reference such marked will refer to the boxed entity, no dereferencing
+ * with `.elem` is done on it.
+ * This tree node can be emitted by macros such as reify that call referenceCapturedVariable.
+ * It is eliminated in LambdaLift, where the boxing conversion takes place.
+ */
+ case class ReferenceToBoxed(ident: Ident) extends TermTree {
+ override def symbol: Symbol = ident.symbol
+ override def symbol_=(sym: Symbol) { ident.symbol = sym }
+ }
+
/** Literal */
case class Literal(value: Constant)
extends TermTree {
@@ -873,6 +967,8 @@ trait Trees { self: Universe =>
traverse(qualifier)
case Ident(_) =>
;
+ case ReferenceToBoxed(idt) =>
+ traverse(idt)
case Literal(_) =>
;
case TypeTree() =>
@@ -958,6 +1054,7 @@ trait Trees { self: Universe =>
def This(tree: Tree, qual: Name): This
def Select(tree: Tree, qualifier: Tree, selector: Name): Select
def Ident(tree: Tree, name: Name): Ident
+ def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
def Literal(tree: Tree, value: Constant): Literal
def TypeTree(tree: Tree): TypeTree
def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
@@ -1040,6 +1137,8 @@ trait Trees { self: Universe =>
new Select(qualifier, selector).copyAttrs(tree)
def Ident(tree: Tree, name: Name) =
new Ident(name).copyAttrs(tree)
+ def ReferenceToBoxed(tree: Tree, idt: Ident) =
+ new ReferenceToBoxed(idt).copyAttrs(tree)
def Literal(tree: Tree, value: Constant) =
new Literal(value).copyAttrs(tree)
def TypeTree(tree: Tree) =
@@ -1228,6 +1327,11 @@ trait Trees { self: Universe =>
if name0 == name => t
case _ => treeCopy.Ident(tree, name)
}
+ def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match {
+ case t @ ReferenceToBoxed(idt0)
+ if (idt0 == idt) => t
+ case _ => this.treeCopy.ReferenceToBoxed(tree, idt)
+ }
def Literal(tree: Tree, value: Constant) = tree match {
case t @ Literal(value0)
if value0 == value => t
@@ -1372,6 +1476,8 @@ trait Trees { self: Universe =>
treeCopy.Select(tree, transform(qualifier), selector)
case Ident(name) =>
treeCopy.Ident(tree, name)
+ case ReferenceToBoxed(idt) =>
+ treeCopy.ReferenceToBoxed(tree, transform(idt) match { case idt1: Ident => idt1 })
case Literal(value) =>
treeCopy.Literal(tree, value)
case TypeTree() =>
@@ -1443,6 +1549,14 @@ trait Trees { self: Universe =>
}
}
+ class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser {
+ val results = new ListBuffer[T]
+ override def traverse(t: Tree) {
+ if (pf.isDefinedAt(t)) results += pf(t)
+ super.traverse(t)
+ }
+ }
+
class FindTreeTraverser(p: Tree => Boolean) extends Traverser {
var result: Option[Tree] = None
override def traverse(t: Tree) {
@@ -1535,7 +1649,7 @@ trait Trees { self: Universe =>
case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup)
// fun(args)
case Super(qual, mix) =>
- // qual.super[mix] if qual and/or mix is empty, ther are tpnme.EMPTY
+ // qual.super[mix] qual is always This(something), if mix is empty, it is tpnme.EMPTY
case This(qual) =>
// qual.this
case Select(qualifier, selector) =>
@@ -1544,6 +1658,10 @@ trait Trees { self: Universe =>
// name
// note: type checker converts idents that refer to enclosing fields or methods
// to selects; name ==> this.name
+ case ReferenceToBoxed(ident) => (created by typer, eliminated by lambdalift)
+ // synthetic node emitted by macros to reference capture vars directly without going through ``elem''
+ // var x = ...; fun { x } will emit Ident(x), which gets transformed to Select(Ident(x), "elem")
+ // if ReferenceToBoxed were used instead of Ident, no transformation would be performed
case Literal(value) =>
// value
case TypeTree() => (introduced by refcheck)
diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala
new file mode 100644
index 0000000000..a38c21a9d4
--- /dev/null
+++ b/src/library/scala/reflect/api/TypeTags.scala
@@ -0,0 +1,193 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package api
+
+import scala.reflect.{ mirror => rm }
+
+/**
+ * Type tags encapsulate a representation of type T.
+ * They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]].
+ * TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler.
+ *
+ * Type tags are organized in a hierarchy of two classes:
+ * [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#GroundTypeTag]].
+ * A [[scala.reflect.ClassTag]] value wraps a Java class, which can be accessed via the erasure method.
+ * A [[scala.reflect.api.Universe#TypeTag]] value wraps a full Scala type in its tpe field.
+ * A [[scala.reflect.api.Universe#GroundTypeTag]] value is a type tag that is guaranteed not to contain any references to type parameters or abstract types.
+ *
+ * TypeTags correspond loosely to Manifests. More precisely:
+ * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
+ * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.mirror.GroundTypeTag,
+ * Whereas scala.reflect.mirror.TypeTag is approximated by the previous notion of [[scala.reflect.OptManifest]].
+ *
+ * Implicit in the contract for all Tag classes is that the reified type tpe represents the type parameter T.
+ * Tags are typically created by the compiler, which makes sure that this contract is kept.
+ *
+ * An example that illustrates the TypeTag embedding, consider the following function:
+ *
+ * import reflect.mirror._
+ * def f[T: TypeTag, U] = {
+ * type L = T => U
+ * implicitly[TypeTag[L]]
+ * }
+ *
+ * Then a call of f[String, Int] will yield a result of the form
+ *
+ * TypeTag(<[ String => U ]>).
+ *
+ * Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter.
+ */
+trait TypeTags { self: Universe =>
+
+ /**
+ * If an implicit value of type u.TypeTag[T] is required, the compiler will make one up on demand.
+ * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T.
+ * In that value, any occurrences of type parameters or abstract types U
+ * which come themselves with a TypeTag are represented by the type referenced by that TypeTag.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+ @annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
+ abstract case class TypeTag[T](tpe: Type) {
+ // it's unsafe to use assert here, because we might run into deadlocks with Predef
+ // also see comments in ClassTags.scala
+ // assert(tpe != null)
+
+ def sym = tpe.typeSymbol
+
+ def isGround = !isNotGround
+ def isNotGround = tpe exists (_.typeSymbol.isAbstractType)
+
+ def toGround: GroundTypeTag[T] = {
+ assert(isGround, tpe)
+ GroundTypeTag[T](tpe)
+ }
+
+ override def toString = {
+ var prefix = if (isGround) "GroundTypeTag" else "TypeTag"
+ if (prefix != this.productPrefix) prefix = "*" + prefix
+ prefix + "[" + tpe + "]"
+ }
+ }
+
+ object TypeTag {
+ val Byte : TypeTag[scala.Byte] = GroundTypeTag.Byte
+ val Short : TypeTag[scala.Short] = GroundTypeTag.Short
+ val Char : TypeTag[scala.Char] = GroundTypeTag.Char
+ val Int : TypeTag[scala.Int] = GroundTypeTag.Int
+ val Long : TypeTag[scala.Long] = GroundTypeTag.Long
+ val Float : TypeTag[scala.Float] = GroundTypeTag.Float
+ val Double : TypeTag[scala.Double] = GroundTypeTag.Double
+ val Boolean : TypeTag[scala.Boolean] = GroundTypeTag.Boolean
+ val Unit : TypeTag[scala.Unit] = GroundTypeTag.Unit
+ val Any : TypeTag[scala.Any] = GroundTypeTag.Any
+ val Object : TypeTag[java.lang.Object] = GroundTypeTag.Object
+ val AnyVal : TypeTag[scala.AnyVal] = GroundTypeTag.AnyVal
+ val AnyRef : TypeTag[scala.AnyRef] = GroundTypeTag.AnyRef
+ val Nothing : TypeTag[scala.Nothing] = GroundTypeTag.Nothing
+ val Null : TypeTag[scala.Null] = GroundTypeTag.Null
+ val String : TypeTag[java.lang.String] = GroundTypeTag.String
+
+ def apply[T](tpe: Type): TypeTag[T] =
+ tpe match {
+ case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]]
+ case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]]
+ case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]]
+ case IntTpe => TypeTag.Int.asInstanceOf[TypeTag[T]]
+ case LongTpe => TypeTag.Long.asInstanceOf[TypeTag[T]]
+ case FloatTpe => TypeTag.Float.asInstanceOf[TypeTag[T]]
+ case DoubleTpe => TypeTag.Double.asInstanceOf[TypeTag[T]]
+ case BooleanTpe => TypeTag.Boolean.asInstanceOf[TypeTag[T]]
+ case UnitTpe => TypeTag.Unit.asInstanceOf[TypeTag[T]]
+ case AnyTpe => TypeTag.Any.asInstanceOf[TypeTag[T]]
+ case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]]
+ case AnyValTpe => TypeTag.AnyVal.asInstanceOf[TypeTag[T]]
+ case AnyRefTpe => TypeTag.AnyRef.asInstanceOf[TypeTag[T]]
+ case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]]
+ case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]]
+ case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]]
+ case _ => new TypeTag[T](tpe) {}
+ }
+ }
+
+ /**
+ * If an implicit value of type u.GroundTypeTag[T] is required, the compiler will make one up on demand following the same procedure as for TypeTags.
+ * However, if the resulting type still contains references to type parameters or abstract types, a static error results.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+ @annotation.implicitNotFound(msg = "No GroundTypeTag available for ${T}")
+ class GroundTypeTag[T](tpe: Type) extends TypeTag[T](tpe) {
+ assert(isGround, tpe)
+ override def productPrefix = "GroundTypeTag"
+ }
+
+ object GroundTypeTag {
+ val Byte : GroundTypeTag[scala.Byte] = new GroundTypeTag[scala.Byte](ByteTpe) { private def readResolve() = GroundTypeTag.Byte }
+ val Short : GroundTypeTag[scala.Short] = new GroundTypeTag[scala.Short](ShortTpe) { private def readResolve() = GroundTypeTag.Short }
+ val Char : GroundTypeTag[scala.Char] = new GroundTypeTag[scala.Char](CharTpe) { private def readResolve() = GroundTypeTag.Char }
+ val Int : GroundTypeTag[scala.Int] = new GroundTypeTag[scala.Int](IntTpe) { private def readResolve() = GroundTypeTag.Int }
+ val Long : GroundTypeTag[scala.Long] = new GroundTypeTag[scala.Long](LongTpe) { private def readResolve() = GroundTypeTag.Long }
+ val Float : GroundTypeTag[scala.Float] = new GroundTypeTag[scala.Float](FloatTpe) { private def readResolve() = GroundTypeTag.Float }
+ val Double : GroundTypeTag[scala.Double] = new GroundTypeTag[scala.Double](DoubleTpe) { private def readResolve() = GroundTypeTag.Double }
+ val Boolean : GroundTypeTag[scala.Boolean] = new GroundTypeTag[scala.Boolean](BooleanTpe) { private def readResolve() = GroundTypeTag.Boolean }
+ val Unit : GroundTypeTag[scala.Unit] = new GroundTypeTag[scala.Unit](UnitTpe) { private def readResolve() = GroundTypeTag.Unit }
+ val Any : GroundTypeTag[scala.Any] = new GroundTypeTag[scala.Any](AnyTpe) { private def readResolve() = GroundTypeTag.Any }
+ val Object : GroundTypeTag[java.lang.Object] = new GroundTypeTag[java.lang.Object](ObjectTpe) { private def readResolve() = GroundTypeTag.Object }
+ val AnyVal : GroundTypeTag[scala.AnyVal] = new GroundTypeTag[scala.AnyVal](AnyValTpe) { private def readResolve() = GroundTypeTag.AnyVal }
+ val AnyRef : GroundTypeTag[scala.AnyRef] = new GroundTypeTag[scala.AnyRef](AnyRefTpe) { private def readResolve() = GroundTypeTag.AnyRef }
+ val Nothing : GroundTypeTag[scala.Nothing] = new GroundTypeTag[scala.Nothing](NothingTpe) { private def readResolve() = GroundTypeTag.Nothing }
+ val Null : GroundTypeTag[scala.Null] = new GroundTypeTag[scala.Null](NullTpe) { private def readResolve() = GroundTypeTag.Null }
+ val String : GroundTypeTag[java.lang.String] = new GroundTypeTag[java.lang.String](StringTpe) { private def readResolve() = GroundTypeTag.String }
+
+ def apply[T](tpe: Type): GroundTypeTag[T] =
+ tpe match {
+ case ByteTpe => GroundTypeTag.Byte.asInstanceOf[GroundTypeTag[T]]
+ case ShortTpe => GroundTypeTag.Short.asInstanceOf[GroundTypeTag[T]]
+ case CharTpe => GroundTypeTag.Char.asInstanceOf[GroundTypeTag[T]]
+ case IntTpe => GroundTypeTag.Int.asInstanceOf[GroundTypeTag[T]]
+ case LongTpe => GroundTypeTag.Long.asInstanceOf[GroundTypeTag[T]]
+ case FloatTpe => GroundTypeTag.Float.asInstanceOf[GroundTypeTag[T]]
+ case DoubleTpe => GroundTypeTag.Double.asInstanceOf[GroundTypeTag[T]]
+ case BooleanTpe => GroundTypeTag.Boolean.asInstanceOf[GroundTypeTag[T]]
+ case UnitTpe => GroundTypeTag.Unit.asInstanceOf[GroundTypeTag[T]]
+ case AnyTpe => GroundTypeTag.Any.asInstanceOf[GroundTypeTag[T]]
+ case ObjectTpe => GroundTypeTag.Object.asInstanceOf[GroundTypeTag[T]]
+ case AnyValTpe => GroundTypeTag.AnyVal.asInstanceOf[GroundTypeTag[T]]
+ case AnyRefTpe => GroundTypeTag.AnyRef.asInstanceOf[GroundTypeTag[T]]
+ case NothingTpe => GroundTypeTag.Nothing.asInstanceOf[GroundTypeTag[T]]
+ case NullTpe => GroundTypeTag.Null.asInstanceOf[GroundTypeTag[T]]
+ case StringTpe => GroundTypeTag.String.asInstanceOf[GroundTypeTag[T]]
+ case _ => new GroundTypeTag[T](tpe) {}
+ }
+
+ def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isGround) Some(ttag.tpe) else None
+
+ implicit def toClassTag[T](ttag: rm.GroundTypeTag[T]): ClassTag[T] = ClassTag[T](rm.typeToClass(ttag.tpe.erasure))
+
+ implicit def toDeprecatedManifestApis[T](ttag: rm.GroundTypeTag[T]): DeprecatedManifestApis[T] = new DeprecatedManifestApis[T](ttag)
+
+ // this class should not be used directly in client code
+ class DeprecatedManifestApis[T](ttag: rm.GroundTypeTag[T]) extends DeprecatedClassManifestApis[T](toClassTag(ttag)) {
+ @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
+ def <:<(that: Manifest[_]): Boolean = ttag.tpe <:< that.tpe
+
+ @deprecated("Use `tpe` to analyze the underlying type", "2.10.0")
+ def >:>(that: Manifest[_]): Boolean = that <:< ttag
+
+ @deprecated("Use `tpe` to analyze the type arguments", "2.10.0")
+ override def typeArguments: List[Manifest[_]] = ttag.tpe.typeArguments map (targ => rm.GroundTypeTag(targ))
+ }
+ }
+
+ // incantations for summoning
+ // moved to Context, since rm.tags have their own incantations in Predef, and these guys are only useful in macros
+// def tag[T](implicit ttag: TypeTag[T]) = ttag
+// def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+// def groundTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+// def groundTypeTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala
index 0371e2c5df..12aad453b1 100755
--- a/src/library/scala/reflect/api/Types.scala
+++ b/src/library/scala/reflect/api/Types.scala
@@ -105,7 +105,8 @@ trait Types { self: Universe =>
/** The erased type corresponding to this type after
* all transformations from Scala to Java have been performed.
*/
- def erasedType: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased")
+ def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased")
+ // why not name it "erasure"?
/** Apply `f` to each part of this type, returning
* a new type. children get mapped before their parents */
@@ -146,6 +147,33 @@ trait Types { self: Universe =>
* <o.x.type>.widen = o.C
*/
def widen: Type
+
+ /** The kind of this type; used for debugging */
+ def kind: String
+ }
+
+ /** An object representing an unknown type, used during type inference.
+ * If you see WildcardType outside of inference it is almost certainly a bug.
+ */
+ val WildcardType: Type
+
+ /** BoundedWildcardTypes, used only during type inference, are created in
+ * two places that I can find:
+ *
+ * 1. If the expected type of an expression is an existential type,
+ * its hidden symbols are replaced with bounded wildcards.
+ * 2. When an implicit conversion is being sought based in part on
+ * the name of a method in the converted type, a HasMethodMatching
+ * type is created: a MethodType with parameters typed as
+ * BoundedWildcardTypes.
+ */
+ type BoundedWildcardType >: Null <: Type
+
+ val BoundedWildcardType: BoundedWildcardTypeExtractor
+
+ abstract class BoundedWildcardTypeExtractor {
+ def apply(bounds: TypeBounds): BoundedWildcardType
+ def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
}
/** The type of Scala types, and also Scala type signatures.
@@ -424,5 +452,66 @@ trait Types { self: Universe =>
/** The greatest lower bound wrt <:< of a list of types */
def glb(ts: List[Type]): Type
+
+ // Creators ---------------------------------------------------------------
+ // too useful and too non-trivial to be left out of public API
+ // [Eugene to Paul] needs review!
+
+ /** The canonical creator for single-types */
+ def singleType(pre: Type, sym: Symbol): Type
+
+ /** the canonical creator for a refined type with a given scope */
+ def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type
+
+ /** The canonical creator for a refined type with an initially empty scope.
+ *
+ * @param parents ...
+ * @param owner ...
+ * @return ...
+ */
+ def refinedType(parents: List[Type], owner: Symbol): Type
+
+ /** The canonical creator for typerefs
+ */
+ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself. */
+ def intersectionType(tps: List[Type]): Type
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself, and repeated parent classes are merged.
+ *
+ * !!! Repeated parent classes are not merged - is this a bug in the
+ * comment or in the code?
+ */
+ def intersectionType(tps: List[Type], owner: Symbol): Type
+
+ /** A creator for type applications */
+ def appliedType(tycon: Type, args: List[Type]): Type
+
+ /** A creator for type parameterizations that strips empty type parameter lists.
+ * Use this factory method to indicate the type has kind * (it's a polymorphic value)
+ * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty).
+ */
+ def polyType(tparams: List[Symbol], tpe: Type): Type
+
+ /** A creator for existential types. This generates:
+ *
+ * tpe1 where { tparams }
+ *
+ * where `tpe1` is the result of extrapolating `tpe` wrt to `tparams`.
+ * Extrapolating means that type variables in `tparams` occurring
+ * in covariant positions are replaced by upper bounds, (minus any
+ * SingletonClass markers), type variables in `tparams` occurring in
+ * contravariant positions are replaced by upper bounds, provided the
+ * resulting type is legal wrt to stability, and does not contain any type
+ * variable in `tparams`.
+ *
+ * The abstraction drops all type parameters that are not directly or
+ * indirectly referenced by type `tpe1`. If there are no remaining type
+ * parameters, simply returns result type `tpe`.
+ */
+ def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type
}
diff --git a/src/library/scala/reflect/api/Universe.scala b/src/library/scala/reflect/api/Universe.scala
index a3cec3271b..60abd267cb 100755
--- a/src/library/scala/reflect/api/Universe.scala
+++ b/src/library/scala/reflect/api/Universe.scala
@@ -2,18 +2,87 @@ package scala.reflect
package api
abstract class Universe extends Symbols
+ with FreeVars
with Types
with Constants
with Scopes
with Names
with Trees
- with Positions
- with TreePrinters
with AnnotationInfos
+ with Positions
+ with Exprs
with StandardDefinitions
- with StandardNames {
- type Position
- val NoPosition: Position
+ with TypeTags
+ with TreePrinters
+ with StandardNames
+ with ClassLoaders
+ with TreeBuildUtil
+ with ToolBoxes
+ with Reporters
+ with Importers {
+ /** Given an expression, generate a tree that when compiled and executed produces the original tree.
+ * The produced tree will be bound to the Universe it was called from.
+ *
+ * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression:
+ *
+ * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
+ *
+ * The reifier transforms it to the following expression:
+ *
+ * <[
+ * val $mr: scala.reflect.api.Universe = <reference to the Universe that calls the reify>
+ * $mr.Expr[Int]($mr.Apply($mr.Select($mr.Ident($mr.newFreeVar("x", <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
+ * ]>
+ *
+ * Reification performs expression splicing (when processing Expr.eval and Expr.value)
+ * and type splicing (for every type T that has a TypeTag[T] implicit in scope):
+ *
+ * val two = mirror.reify(2) // Literal(Constant(2))
+ * val four = mirror.reify(two.eval + two.eval) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree))
+ *
+ * def macroImpl[T](c: Context) = {
+ * ...
+ * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion
+ * // however, if T were annotated with c.TypeTag (which would declare an implicit parameter for macroImpl)
+ * // then reification would subtitute T with the TypeTree that was used in a TypeApply of this particular macro invocation
+ * val factory = c.reify{ new Queryable[T] }
+ * ...
+ * }
+ *
+ * The transformation looks mostly straightforward, but it has its tricky parts:
+ * * Reifier retains symbols and types defined outside the reified tree, however
+ * locally defined entities get erased and replaced with their original trees
+ * * Free variables are detected and wrapped in symbols of the type FreeVar
+ * * Mutable variables that are accessed from a local function are wrapped in refs
+ * * Since reified trees can be compiled outside of the scope they've been created in,
+ * special measures are taken to ensure that all members accessed in the reifee remain visible
+ */
+ def reify[T](expr: T): Expr[T] = macro Universe.reify[T]
}
+object Universe {
+ def reify[T](cc: scala.reflect.makro.Context{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
+ import cc.mirror._
+ try cc.reifyTree(cc.prefix, expr)
+ catch {
+ case ex: Throwable =>
+ // [Eugene] cannot pattern match on an abstract type, so had to do this
+ val ex1 = ex
+ if (ex.getClass.toString.endsWith("$ReificationError")) {
+ ex match {
+ case cc.ReificationError(pos, msg) =>
+ cc.error(pos, msg)
+ EmptyTree
+ }
+ } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
+ ex match {
+ case cc.UnexpectedReificationError(pos, err, cause) =>
+ if (cause != null) throw cause else throw ex
+ }
+ } else {
+ throw ex
+ }
+ }
+ }
+}
diff --git a/src/library/scala/reflect/macro/Context.scala b/src/library/scala/reflect/macro/Context.scala
deleted file mode 100644
index 2fd9bb6484..0000000000
--- a/src/library/scala/reflect/macro/Context.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package scala.reflect
-package macro
-
-trait Context extends api.Universe {
-
- /** Mark a variable as captured; i.e. force boxing in a *Ref type.
- */
- def captureVariable(vble: Symbol): Unit
-
- /** Mark given identifier as a reference to a captured variable itself
- * suppressing dereferencing with the `elem` field.
- */
- def referenceCapturedVariable(id: Ident): Tree
-
- /** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
- * For instance, given the abstract syntax tree representation of the `x + 1` expression:
- *
- * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
- *
- * The reifier transforms it to the following tree:
- *
- * $mr.Apply($mr.Select($mr.Ident($mr.newFreeVar("x", <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
- *
- * The transformation looks mostly straightforward, but it has its tricky parts:
- * * Reifier retains symbols and types defined outside the reified tree, however
- * locally defined entities get erased and replaced with their original trees
- * * Free variables are detected and wrapped in symbols of the type FreeVar
- * * Mutable variables that are accessed from a local function are wrapped in refs
- * * Since reified trees can be compiled outside of the scope they've been created in,
- * special measures are taken to ensure that all freeVars remain visible
- *
- * Typical usage of this function is to retain some of the trees received/created by a macro
- * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime.
- */
- def reify(tree: Tree): Tree
-}
diff --git a/src/library/scala/reflect/makro/Aliases.scala b/src/library/scala/reflect/makro/Aliases.scala
new file mode 100644
index 0000000000..e8b847600c
--- /dev/null
+++ b/src/library/scala/reflect/makro/Aliases.scala
@@ -0,0 +1,26 @@
+package scala.reflect.makro
+
+trait Aliases {
+ self: Context =>
+
+ /** Aliases of mirror types */
+ type Symbol = mirror.Symbol
+ type Type = mirror.Type
+ type Name = mirror.Name
+ type Tree = mirror.Tree
+ type Position = mirror.Position
+ type Scope = mirror.Scope
+ type Modifiers = mirror.Modifiers
+ type Expr[+T] = mirror.Expr[T]
+ type TypeTag[T] = mirror.TypeTag[T]
+
+ /** Creator/extractor objects for Expr and TypeTag values */
+ val TypeTag = mirror.TypeTag
+ val Expr = mirror.Expr
+
+ /** incantations for summoning tags */
+ def tag[T](implicit ttag: TypeTag[T]) = ttag
+ def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+ def groundTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+ def groundTypeTag[T](implicit gttag: GroundTypeTag[T]) = gttag
+}
diff --git a/src/library/scala/reflect/makro/CapturedVariables.scala b/src/library/scala/reflect/makro/CapturedVariables.scala
new file mode 100644
index 0000000000..6ce832b2b3
--- /dev/null
+++ b/src/library/scala/reflect/makro/CapturedVariables.scala
@@ -0,0 +1,20 @@
+package scala.reflect.makro
+
+trait CapturedVariables {
+ self: Context =>
+
+ import mirror._
+
+ /** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ */
+ def captureVariable(vble: Symbol): Unit
+
+ /** Mark given identifier as a reference to a captured variable itself
+ * suppressing dereferencing with the `elem` field.
+ */
+ def referenceCapturedVariable(vble: Symbol): Tree
+
+ /** Convert type of a captured variable to *Ref type.
+ */
+ def capturedVariableType(vble: Symbol): Type
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala
new file mode 100644
index 0000000000..96a41377b3
--- /dev/null
+++ b/src/library/scala/reflect/makro/Context.scala
@@ -0,0 +1,59 @@
+package scala.reflect.makro
+
+// todo. introduce context hierarchy
+// the most lightweight context should just expose the stuff from the SIP
+// the full context should include all traits from scala.reflect.makro (and probably reside in scala-compiler.jar)
+
+trait Context extends Aliases
+ with CapturedVariables
+ with Enclosures
+ with Infrastructure
+ with Names
+ with Reifiers
+ with Reporters
+ with Settings
+ with Symbols
+ with Typers
+ with Util {
+
+ /** The mirror that corresponds to the compile-time universe */
+ val mirror: scala.reflect.api.Universe
+
+ /** The type of the prefix tree from which the macro is selected */
+ type PrefixType
+
+ /** The prefix tree from which the macro is selected */
+ val prefix: Expr[PrefixType]
+
+ /** Alias to the underlying mirror's reify */
+ def reify[T](expr: T): Expr[T] = macro Context.reify[T]
+}
+
+object Context {
+ def reify[T](cc: Context{ type PrefixType = Context })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
+ import cc.mirror._
+ // [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
+ val prefix: Tree = Select(cc.prefix, newTermName("mirror"))
+ val prefixTpe = cc.typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe
+ prefix setType prefixTpe
+ try cc.reifyTree(prefix, expr)
+ catch {
+ case ex: Throwable =>
+ // [Eugene] cannot pattern match on an abstract type, so had to do this
+ if (ex.getClass.toString.endsWith("$ReificationError")) {
+ ex match {
+ case cc.ReificationError(pos, msg) =>
+ cc.error(pos, msg)
+ EmptyTree
+ }
+ } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
+ ex match {
+ case cc.UnexpectedReificationError(pos, err, cause) =>
+ if (cause != null) throw cause else throw ex
+ }
+ } else {
+ throw ex
+ }
+ }
+ }
+}
diff --git a/src/library/scala/reflect/makro/Enclosures.scala b/src/library/scala/reflect/makro/Enclosures.scala
new file mode 100644
index 0000000000..136d39498e
--- /dev/null
+++ b/src/library/scala/reflect/makro/Enclosures.scala
@@ -0,0 +1,53 @@
+package scala.reflect.makro
+
+trait Enclosures {
+ self: Context =>
+
+ /** The tree that undergoes macro expansion.
+ * Can be useful to get an offset or a range position of the entire tree being processed.
+ */
+ val macroApplication: Tree
+
+ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only.
+ * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion.
+ *
+ * Is also priceless for emitting sane error messages for macros that are called by other macros on synthetic (i.e. position-less) trees.
+ * In that dire case navigate the ``enclosingMacros'' stack, and it will most likely contain at least one macro with a position-ful macro application.
+ * See ``enclosingPosition'' for a default implementation of this logic.
+ *
+ * Unlike `openMacros`, this is a val, which means that it gets initialized when the context is created
+ * and always stays the same regardless of whatever happens during macro expansion.
+ */
+ val enclosingMacros: List[Context]
+
+ /** Types along with corresponding trees for which implicit arguments are currently searched.
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ *
+ * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created
+ * and always stays the same regardless of whatever happens during macro expansion.
+ */
+ val enclosingImplicits: List[(Type, Tree)]
+
+ /** Tries to guess a position for the enclosing application.
+ * But that is simple, right? Just dereference ``pos'' of ``macroApplication''? Not really.
+ * If we're in a synthetic macro expansion (no positions), we must do our best to infer the position of something that triggerd this expansion.
+ * Surprisingly, quite often we can do this by navigation the ``enclosingMacros'' stack.
+ */
+ val enclosingPosition: Position
+
+ /** Tree that corresponds to the enclosing application, or EmptyTree if not applicable.
+ */
+ val enclosingApplication: Tree
+
+ /** Tree that corresponds to the enclosing method, or EmptyTree if not applicable.
+ */
+ val enclosingMethod: Tree
+
+ /** Tree that corresponds to the enclosing class, or EmptyTree if not applicable.
+ */
+ val enclosingClass: Tree
+
+ /** Compilation unit that contains this macro application.
+ */
+ val enclosingUnit: CompilationUnit
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Infrastructure.scala b/src/library/scala/reflect/makro/Infrastructure.scala
new file mode 100644
index 0000000000..2bf49dca77
--- /dev/null
+++ b/src/library/scala/reflect/makro/Infrastructure.scala
@@ -0,0 +1,73 @@
+package scala.reflect.makro
+
+trait Infrastructure {
+ self: Context =>
+
+ /** Determines whether the compiler expanding a macro targets JVM.
+ */
+ val forJVM: Boolean
+
+ /** Determines whether the compiler expanding a macro targets CLR.
+ */
+ val forMSIL: Boolean
+
+ /** Determines whether the compiler expanding a macro is a presentation compiler.
+ */
+ val forInteractive: Boolean
+
+ /** Determines whether the compiler expanding a macro is a Scaladoc compiler.
+ */
+ val forScaladoc: Boolean
+
+ /** Exposes current compilation run.
+ */
+ val currentRun: Run
+
+ /** As seen by macro API, compilation run is an opaque type that can be deconstructed into:
+ * 1) Current compilation unit
+ * 2) List of all compilation units that comprise the run
+ */
+ type Run
+
+ val Run: RunExtractor
+
+ abstract class RunExtractor {
+ def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])]
+ }
+
+ /** As seen by macro API, compilation unit is an opaque type that can be deconstructed into:
+ * 1) File that corresponds to the unit (if not applicable, null)
+ * 2) Content of the file (if not applicable, empty array)
+ * 3) Body, i.e. the AST that represents the compilation unit
+ */
+ type CompilationUnit
+
+ val CompilationUnit: CompilationUnitExtractor
+
+ abstract class CompilationUnitExtractor {
+ def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)]
+ }
+
+ /** Returns a macro definition which triggered this macro expansion.
+ */
+ val currentMacro: Symbol
+
+ // todo. redo caches as discussed on Reflecting Meeting 2012/03/29
+ // https://docs.google.com/document/d/1oUZGQpdt2qwioTlJcSt8ZFQwVLTvpxn8xa67P8OGVpU/edit
+
+ /** A cache shared by all invocations of all macros across all compilation runs.
+ *
+ * Needs to be used with extreme care, since memory leaks here will swiftly crash the presentation compiler.
+ * For example, Scala IDE typically launches a compiler run on every edit action so there might be hundreds of runs per minute.
+ */
+ val globalCache: collection.mutable.Map[Any, Any]
+
+ /** A cache shared by all invocations of the same macro within a single compilation run.
+ *
+ * This cache is cleared automatically after a compilation run is completed or abandoned.
+ * It is also specific to a particular macro definition.
+ *
+ * To share data between different macros and/or different compilation runs, use ``globalCache''.
+ */
+ val cache: collection.mutable.Map[Any, Any]
+}
diff --git a/src/library/scala/reflect/makro/Names.scala b/src/library/scala/reflect/makro/Names.scala
new file mode 100644
index 0000000000..8a823d19cb
--- /dev/null
+++ b/src/library/scala/reflect/makro/Names.scala
@@ -0,0 +1,14 @@
+package scala.reflect.makro
+
+trait Names {
+ self: Context =>
+
+ /** Creates a fresh string */
+ def fresh(): String
+
+ /** Creates a fresh string from the provided string */
+ def fresh(name: String): String
+
+ /** Creates a fresh name from the provided name */
+ def fresh(name: Name): Name
+}
diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala
new file mode 100644
index 0000000000..9bd25cf0f8
--- /dev/null
+++ b/src/library/scala/reflect/makro/Reifiers.scala
@@ -0,0 +1,82 @@
+package scala.reflect.makro
+
+trait Reifiers {
+ self: Context =>
+
+ /** Reification prefix that refers to the standard reflexive mirror, ``scala.reflect.mirror''.
+ * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a tree that can be inspected at runtime.
+ */
+ val reflectMirrorPrefix: Tree
+
+ /** Given a tree, generate a tree that when compiled and executed produces the original tree.
+ * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix'').
+ * For more information and examples see the documentation for ``Universe.reify''.
+ *
+ * This function is deeply connected to ``Universe.reify'', a macro that reifies arbitrary expressions into runtime trees.
+ * They do very similar things (``Universe.reify'' calls ``Context.reifyTree'' to implement itself), but they operate on different metalevels (see below).
+ *
+ * Let's study the differences between ``Context.reifyTree'' and ``Universe.reify'' on an example of using them inside a ``fooMacro'' macro:
+ *
+ * * Since reify itself is a macro, it will be executed when fooMacro is being compiled (metalevel -1)
+ * and will produce a tree that when evaluated during macro expansion of fooMacro (metalevel 0) will recreate the input tree.
+ *
+ * This provides a facility analogous to quasi-quoting. Writing "reify{ expr }" will generate an AST that represents expr.
+ * Afterwards this AST (or its parts) can be used to construct the return value of fooMacro.
+ *
+ * * reifyTree is evaluated during macro expansion (metalevel 0)
+ * and will produce a tree that when evaluated during the runtime of the program (metalevel 1) will recreate the input tree.
+ *
+ * This provides a way to retain certain trees from macro expansion time to be inspected later, in the runtime.
+ * For example, DSL authors may find it useful to capture DSL snippets into ASTs that are then processed at runtime in a domain-specific way.
+ *
+ * Also note the difference between universes of the runtime trees produced by two reifies:
+ *
+ * * The result of compiling and running the result of reify will be bound to the Universe that called reify.
+ * This is possible because it's a macro, so it can generate whatever code it wishes.
+ *
+ * * The result of compiling and running the result of reifyTree will be the ``prefix'' that needs to be passed explicitly.
+ * This happens because the Universe of the evaluated result is from a different metalevel than the Context the called reify.
+ *
+ * Typical usage of this function is to retain some of the trees received/created by a macro
+ * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime.
+ */
+ def reifyTree(prefix: Tree, tree: Tree): Tree
+
+ /** Given a type, generate a tree that when compiled and executed produces the original type.
+ * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix'').
+ * For more information and examples see the documentation for ``Context.reifyTree'' and ``Universe.reify''.
+ */
+ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireGroundTypeTag: Boolean = false): Tree
+
+ /** Undoes reification of a tree.
+ *
+ * This reversion doesn't simply restore the original tree (that would lose the context of reification),
+ * but does something more involved that conforms to the following laws:
+ *
+ * 1) unreifyTree(reifyTree(tree)) != tree // unreified tree is tree + saved context
+ * // in current implementation, the result of unreify is opaque
+ * // i.e. there's no possibility to inspect underlying tree/context
+ *
+ * 2) reifyTree(unreifyTree(reifyTree(tree))) == reifyTree(tree) // the result of reifying a tree in its original context equals to
+ * // the result of reifying a tree along with its saved context
+ *
+ * 3) compileAndEval(unreifyTree(reifyTree(tree))) ~ compileAndEval(tree) // at runtime original and unreified trees are behaviorally equivalent
+ */
+ def unreifyTree(tree: Tree): Tree
+
+ /** Represents an error during reification
+ */
+ type ReificationError <: Throwable
+ val ReificationError: ReificationErrorExtractor
+ abstract class ReificationErrorExtractor {
+ def unapply(error: ReificationError): Option[(Position, String)]
+ }
+
+ /** Wraps an unexpected error during reification
+ */
+ type UnexpectedReificationError <: Throwable
+ val UnexpectedReificationError: UnexpectedReificationErrorExtractor
+ abstract class UnexpectedReificationErrorExtractor {
+ def unapply(error: UnexpectedReificationError): Option[(Position, String, Throwable)]
+ }
+}
diff --git a/src/library/scala/reflect/makro/Reporters.scala b/src/library/scala/reflect/makro/Reporters.scala
new file mode 100644
index 0000000000..7341b0e0b7
--- /dev/null
+++ b/src/library/scala/reflect/makro/Reporters.scala
@@ -0,0 +1,39 @@
+package scala.reflect.makro
+
+trait Reporters {
+ self: Context =>
+
+ import mirror._
+
+ /** Exposes means to control the compiler UI */
+ def reporter: Reporter
+ def setReporter(reporter: Reporter): this.type
+ def withReporter[T](reporter: Reporter)(op: => T): T
+
+ /** For sending a message which should not be labeled as a warning/error,
+ * but also shouldn't require -verbose to be visible.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def echo(pos: Position, msg: String): Unit
+
+ /** Informational messages, suppressed unless -verbose or force=true.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def info(pos: Position, msg: String, force: Boolean): Unit
+
+ /** Warnings and errors.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def hasWarnings: Boolean
+ def hasErrors: Boolean
+ def warning(pos: Position, msg: String): Unit
+ def error(pos: Position, msg: String): Unit
+
+ /** Abruptly terminates current macro expansion leaving a note about what happened.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def abort(pos: Position, msg: String): Nothing
+
+ /** Drops into interactive mode if supported by the compiler UI */
+ def interactive(): Unit
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Settings.scala b/src/library/scala/reflect/makro/Settings.scala
new file mode 100644
index 0000000000..c4a8ebd1b5
--- /dev/null
+++ b/src/library/scala/reflect/makro/Settings.scala
@@ -0,0 +1,38 @@
+package scala.reflect.makro
+
+trait Settings {
+ self: Context =>
+
+ /** Exposes macro-specific settings as a list of strings.
+ * These settings are passed to the compiler via the "-Xmacro-settings:setting1,setting2...,settingN" command-line option.
+ */
+ def settings: List[String]
+
+ /** Exposes current compiler settings as a list of options.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ // [Eugene] ugly? yes, but I don't really fancy copy/pasting all our settings here and keep it synchronized at all times
+ // why all settings? because macros need to be in full control of the stuff going on
+ // maybe later we can implement a gettable/settable list of important settings, but for now let's leave it like that
+ def compilerSettings: List[String]
+
+ /** Updates current compiler settings with an option string.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def setCompilerSettings(options: String): this.type
+
+ /** Updates current compiler settings with a list of options.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def setCompilerSettings(options: List[String]): this.type
+
+ /** Temporary sets compiler settings to a given option string and executes a given closure.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def withCompilerSettings[T](options: String)(op: => T): T
+
+ /** Temporary sets compiler settings to a given list of options and executes a given closure.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def withCompilerSettings[T](options: List[String])(op: => T): T
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Symbols.scala b/src/library/scala/reflect/makro/Symbols.scala
new file mode 100644
index 0000000000..91a5f6d8a5
--- /dev/null
+++ b/src/library/scala/reflect/makro/Symbols.scala
@@ -0,0 +1,17 @@
+package scala.reflect.makro
+
+trait Symbols {
+ self: Context =>
+
+ /** Can this symbol be loaded by a reflective mirror?
+ *
+ * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs.
+ * Such annotations (also called "pickles") are applied on top-level classes and include information
+ * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block)
+ * are typically unreachable and information about them gets lost.
+ *
+ * This method is useful for macro writers who wish to save certain ASTs to be used at runtime.
+ * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment.
+ */
+ def isLocatable(sym: Symbol): Boolean
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Typers.scala b/src/library/scala/reflect/makro/Typers.scala
new file mode 100644
index 0000000000..1ced2daccd
--- /dev/null
+++ b/src/library/scala/reflect/makro/Typers.scala
@@ -0,0 +1,85 @@
+package scala.reflect.makro
+
+trait Typers {
+ self: Context =>
+
+ import mirror._
+
+ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only.
+ * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion.
+ *
+ * Is also priceless for emitting sane error messages for macros that are called by other macros on synthetic (i.e. position-less) trees.
+ * In that dire case navigate the ``openMacros'' stack, and it will most likely contain at least one macro with a position-ful macro application.
+ * See ``enclosingPosition'' for a default implementation of this logic.
+ *
+ * Unlike `enclosingMacros`, this is a def, which means that it gets recalculated on every invocation,
+ * so it might change depending on what is going on during macro expansion.
+ */
+ def openMacros: List[Context]
+
+ /** Types along with corresponding trees for which implicit arguments are currently searched.
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ *
+ * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation,
+ * so it might change depending on what is going on during macro expansion.
+ */
+ def openImplicits: List[(Type, Tree)]
+
+ /** Typechecks the provided tree against the expected type ``pt'' in the macro callsite context.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Ymacro-debug.
+ * Unlike in ``inferImplicitValue'' and ``inferImplicitView'', ``silent'' is false by default.
+ *
+ * Typechecking can be steered with the following optional parameters:
+ * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false
+ * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false
+ */
+ def typeCheck(tree: Tree, pt: Type = WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit value of the expected type ``pt'' in the macro callsite context.
+ * Optional ``pos'' parameter provides a position that will be associated with the implicit search.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree
+
+ /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context.
+ *
+ * Optional ``pos'' parameter provides a position that will be associated with the implicit search.
+ * Another optional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported.
+ * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree
+
+ /** Recursively resets symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetAllAttrs[T <: Tree](tree: T): T
+
+ /** Recursively resets locally defined symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetLocalAttrs[T <: Tree](tree: T): T
+
+ /** Represents an error during typechecking
+ */
+ type TypeError <: Throwable
+ val TypeError: TypeErrorExtractor
+ abstract class TypeErrorExtractor {
+ def unapply(error: TypeError): Option[(Position, String)]
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Util.scala b/src/library/scala/reflect/makro/Util.scala
new file mode 100644
index 0000000000..16eb2395a9
--- /dev/null
+++ b/src/library/scala/reflect/makro/Util.scala
@@ -0,0 +1,31 @@
+package scala.reflect.makro
+
+trait Util {
+ self: Context =>
+
+ def literalNull: Expr[Null]
+
+ def literalUnit: Expr[Unit]
+
+ def literalTrue: Expr[Boolean]
+
+ def literalFalse: Expr[Boolean]
+
+ def literal(x: Boolean): Expr[Boolean]
+
+ def literal(x: Byte): Expr[Byte]
+
+ def literal(x: Short): Expr[Short]
+
+ def literal(x: Int): Expr[Int]
+
+ def literal(x: Long): Expr[Long]
+
+ def literal(x: Float): Expr[Float]
+
+ def literal(x: Double): Expr[Double]
+
+ def literal(x: String): Expr[String]
+
+ def literal(x: Char): Expr[Char]
+}
diff --git a/src/library/scala/reflect/makro/internal/macroImpl.scala b/src/library/scala/reflect/makro/internal/macroImpl.scala
new file mode 100644
index 0000000000..86600ba0a1
--- /dev/null
+++ b/src/library/scala/reflect/makro/internal/macroImpl.scala
@@ -0,0 +1,5 @@
+package scala.reflect.makro
+package internal
+
+/** This type is required by the compiler and <b>should not be used in client code</b>. */
+class macroImpl(val referenceToMacroImpl: Any) extends StaticAnnotation
diff --git a/src/library/scala/reflect/makro/internal/typeTagImpl.scala b/src/library/scala/reflect/makro/internal/typeTagImpl.scala
new file mode 100644
index 0000000000..6c49ef45de
--- /dev/null
+++ b/src/library/scala/reflect/makro/internal/typeTagImpl.scala
@@ -0,0 +1,133 @@
+package scala.reflect.makro
+
+import scala.reflect.api.Universe
+
+/** This package is required by the compiler and <b>should not be used in client code</b>. */
+package object internal {
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeClassTag[T](u: Universe): ClassTag[T] = macro materializeClassTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeClassTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ClassTag[T]] =
+ c.Expr[Nothing](c.materializeClassTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeTypeTag[T](u: Universe): u.TypeTag[T] = macro materializeTypeTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.TypeTag[T]] =
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, requireGroundTypeTag = false))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeGroundTypeTag[T](u: Universe): u.GroundTypeTag[T] = macro materializeGroundTypeTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeGroundTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.GroundTypeTag[T]] =
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, requireGroundTypeTag = true))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ private[scala] implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils
+}
+
+package internal {
+ private[scala] abstract class Utils {
+ val c: Context
+
+ import c.mirror._
+ import definitions._
+
+ val coreTags = Map(
+ ByteClass.asType -> newTermName("Byte"),
+ ShortClass.asType -> newTermName("Short"),
+ CharClass.asType -> newTermName("Char"),
+ IntClass.asType -> newTermName("Int"),
+ LongClass.asType -> newTermName("Long"),
+ FloatClass.asType -> newTermName("Float"),
+ DoubleClass.asType -> newTermName("Double"),
+ BooleanClass.asType -> newTermName("Boolean"),
+ UnitClass.asType -> newTermName("Unit"),
+ AnyClass.asType -> newTermName("Any"),
+ ObjectClass.asType -> newTermName("Object"),
+ AnyValClass.asType -> newTermName("AnyVal"),
+ AnyRefClass.asType -> newTermName("AnyRef"),
+ NothingClass.asType -> newTermName("Nothing"),
+ NullClass.asType -> newTermName("Null"))
+
+ def materializeClassTag(prefix: Tree, tpe: Type): Tree = {
+ val typetagInScope = c.inferImplicitValue(appliedType(typeRef(prefix.tpe, TypeTagClass, Nil), List(tpe)))
+ def typetagIsSynthetic(tree: Tree) = tree.isInstanceOf[Block] || (tree exists (sub => sub.symbol == TypeTagModule || sub.symbol == GroundTypeTagModule))
+ typetagInScope match {
+ case success if !success.isEmpty && !typetagIsSynthetic(success) =>
+ val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe)))
+ Apply(factory, List(Select(typetagInScope, newTermName("tpe"))))
+ case _ =>
+ val result =
+ tpe match {
+ case coreTpe if coreTags contains coreTpe =>
+ Select(Ident(ClassTagModule), coreTags(coreTpe))
+ case _ =>
+ if (tpe.typeSymbol == ArrayClass) {
+ val componentTpe = tpe.typeArguments(0)
+ val classtagInScope = c.inferImplicitValue(appliedType(typeRef(NoPrefix, ClassTagClass, Nil), List(componentTpe)))
+ val componentTag = classtagInScope orElse materializeClassTag(prefix, componentTpe)
+ Select(componentTag, newTermName("wrap"))
+ } else {
+ // [Eugene] what's the intended behavior? there's no spec on ClassManifests
+ // for example, should we ban Array[T] or should we tag them with Array[AnyRef]?
+ // if its the latter, what should be the result of tagging Array[T] where T <: Int?
+ if (tpe.typeSymbol.isAbstractType) fail("tpe is an abstract type")
+ val erasure =
+ if (tpe.typeSymbol.isDerivedValueClass) tpe // [Eugene to Martin] is this correct?
+ else tpe.erasure.normalize // necessary to deal with erasures of HK types
+ val factory = TypeApply(Select(Ident(ClassTagModule), newTermName("apply")), List(TypeTree(tpe)))
+ Apply(factory, List(TypeApply(Ident(newTermName("classOf")), List(TypeTree(erasure)))))
+ }
+ }
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
+ }
+ }
+
+ def materializeTypeTag(prefix: Tree, tpe: Type, requireGroundTypeTag: Boolean): Tree = {
+ val tagModule = if (requireGroundTypeTag) GroundTypeTagModule else TypeTagModule
+ val result =
+ tpe match {
+ case coreTpe if coreTags contains coreTpe =>
+ Select(Select(prefix, tagModule.name), coreTags(coreTpe))
+ case _ =>
+ try c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, requireGroundTypeTag = requireGroundTypeTag)
+ catch {
+ case ex: Throwable =>
+ // [Eugene] cannot pattern match on an abstract type, so had to do this
+ val ex1 = ex
+ if (ex.getClass.toString.endsWith("$ReificationError")) {
+ ex match {
+ case c.ReificationError(pos, msg) =>
+ c.error(pos, msg)
+ EmptyTree
+ }
+ } else if (ex.getClass.toString.endsWith("$UnexpectedReificationError")) {
+ ex match {
+ case c.UnexpectedReificationError(pos, err, cause) =>
+ if (cause != null) throw cause else throw ex
+ }
+ } else {
+ throw ex
+ }
+ }
+ }
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => fail(terr) }
+ }
+
+ private def fail(reason: Any): Nothing = {
+ val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication
+ val tpe = tpeTree.tpe
+ val PolyType(_, MethodType(_, tagTpe)) = fun.tpe
+ val tagModule = tagTpe.typeSymbol.companionSymbol
+ if (c.compilerSettings.contains("-Xlog-implicits"))
+ c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason)
+ c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe))
+ }
+ }
+}
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 1c3e618520..7a8267e689 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -2,21 +2,28 @@ package scala
package object reflect {
+ import ReflectionUtils._
+
// !!! This was a val; we can't throw exceptions that aggressively without breaking
// non-standard environments, e.g. google app engine. I made it a lazy val, but
// I think it would be better yet to throw the exception somewhere else - not during
// initialization, but in response to a doomed attempt to utilize it.
- lazy val mirror: api.Mirror = {
+
+ // todo. default mirror (a static object) might become a source for memory leaks (because it holds a strong reference to a classloader)!
+ lazy val mirror: api.Mirror = mkMirror(defaultReflectionClassLoader)
+
+ def mkMirror(classLoader: ClassLoader): api.Mirror = {
// we use (Java) reflection here so that we can keep reflect.runtime and reflect.internals in a seperate jar
- ReflectionUtils.singletonInstanceOpt("scala.reflect.runtime.Mirror") collect { case x: api.Mirror => x } getOrElse {
- throw new UnsupportedOperationException("Scala reflection not available on this platform")
+ // note that we must instantiate the mirror with current classloader, otherwise we won't be able to cast it to api.Mirror
+ // that's not a problem, though, because mirror can service classes from arbitrary classloaders
+ val instance = invokeFactoryOpt(getClass.getClassLoader, "scala.reflect.runtime.package", "mkMirror", classLoader)
+ instance match {
+ case Some(x: api.Mirror) => x
+ case Some(_) => throw new UnsupportedOperationException("Available scala reflection implementation is incompatible with this interface")
+ case None => throw new UnsupportedOperationException("Scala reflection not available on this platform")
}
}
- type Symbol = mirror.Symbol
- type Type = mirror.Type
- type Tree = mirror.Tree
-
@deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0")
type BeanDescription = scala.beans.BeanDescription
@deprecated("Use `@scala.beans.BeanDisplayName` instead", "2.10.0")
@@ -31,4 +38,26 @@ package object reflect {
type BooleanBeanProperty = scala.beans.BooleanBeanProperty
@deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0")
type ScalaBeanInfo = scala.beans.ScalaBeanInfo
+
+ @deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
+ type ClassManifest[T] = ClassTag[T]
+ @deprecated("OptManifest is no longer supported, and using it may lead to incorrect results, Use `@scala.reflect.TypeTag` instead", "2.10.0")
+ type OptManifest[T] = TypeTag[T]
+ @deprecated("Use `@scala.reflect.GroundTypeTag` instead", "2.10.0")
+ type Manifest[T] = GroundTypeTag[T]
+
+ @deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
+ val ClassManifest = ClassTag
+ @deprecated("Use `@scala.reflect.GroundTypeTag` instead", "2.10.0")
+ lazy val Manifest = GroundTypeTag
+ @deprecated("NoManifest is no longer supported, and using it may lead to incorrect results, Use `@scala.reflect.TypeTag` instead", "2.10.0")
+ object NoManifest extends OptManifest[Nothing](scala.reflect.mirror.definitions.NothingClass.asType) with Serializable
+
+ // ClassTag class is defined separately from the mirror
+ type TypeTag[T] = scala.reflect.mirror.TypeTag[T]
+ type GroundTypeTag[T] = scala.reflect.mirror.GroundTypeTag[T]
+
+ // ClassTag object is defined separately from the mirror
+ lazy val TypeTag = scala.reflect.mirror.TypeTag
+ lazy val GroundTypeTag = scala.reflect.mirror.GroundTypeTag
}
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 8bc63ae3a0..d06eba8f7d 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -31,7 +31,7 @@ object ScalaRunTime {
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
- def isTuple(x: Any) = tupleNames(x.getClass.getName)
+ def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
def isAnyVal(x: Any) = x match {
case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
case _ => false
diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala
index daeaf4c53b..c2269cde45 100644
--- a/src/library/scala/util/Marshal.scala
+++ b/src/library/scala/util/Marshal.scala
@@ -35,7 +35,8 @@ object Marshal {
def load[A](buffer: Array[Byte])(implicit expected: ClassManifest[A]): A = {
val in = new ObjectInputStream(new ByteArrayInputStream(buffer))
val found = in.readObject.asInstanceOf[ClassManifest[_]]
- if (found <:< expected) {
+ // todo. [Eugene] needs review, since ClassManifests no longer capture typeArguments
+ if (found.tpe <:< expected.tpe) {
val o = in.readObject.asInstanceOf[A]
in.close()
o