summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Vogt <christopher.vogt@epfl.ch>2012-09-18 07:58:26 +0200
committerChristopher Vogt <christopher.vogt@epfl.ch>2012-09-18 14:55:47 +0200
commitbbd2e43b1ddd244f8f67c951b9009444efa19391 (patch)
tree482a3fabfdb488626e6133cfbb7b633af7069603
parent61480eb14a07c78a6746d2a6dc1e302d5baa112f (diff)
downloadscala-bbd2e43b1ddd244f8f67c951b9009444efa19391.tar.gz
scala-bbd2e43b1ddd244f8f67c951b9009444efa19391.tar.bz2
scala-bbd2e43b1ddd244f8f67c951b9009444efa19391.zip
improved reflection documentation
-rw-r--r--src/library/scala/reflect/ClassTag.scala23
-rw-r--r--src/library/scala/reflect/base/Annotations.scala63
-rw-r--r--src/library/scala/reflect/base/Attachments.scala17
-rw-r--r--src/library/scala/reflect/base/Base.scala3
-rw-r--r--src/library/scala/reflect/base/BuildUtils.scala3
-rw-r--r--src/library/scala/reflect/base/Constants.scala16
-rw-r--r--src/library/scala/reflect/base/Exprs.scala46
-rw-r--r--src/library/scala/reflect/base/FlagSets.scala2
-rw-r--r--src/library/scala/reflect/base/MirrorOf.scala23
-rw-r--r--src/library/scala/reflect/base/Mirrors.scala15
-rw-r--r--src/library/scala/reflect/base/Names.scala36
-rw-r--r--src/library/scala/reflect/base/Positions.scala11
-rw-r--r--src/library/scala/reflect/base/Scopes.scala17
-rw-r--r--src/library/scala/reflect/base/StandardDefinitions.scala50
-rw-r--r--src/library/scala/reflect/base/StandardNames.scala4
-rw-r--r--src/library/scala/reflect/base/Symbols.scala21
-rw-r--r--src/library/scala/reflect/base/TagInterop.scala16
-rw-r--r--src/library/scala/reflect/base/Trees.scala120
-rw-r--r--src/library/scala/reflect/base/TypeTags.scala174
-rw-r--r--src/library/scala/reflect/base/Types.scala29
-rw-r--r--src/library/scala/reflect/base/Universe.scala37
-rw-r--r--src/library/scala/reflect/package.scala46
22 files changed, 591 insertions, 181 deletions
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 8a595473cc..0bafa7c505 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -5,17 +5,17 @@ import java.lang.{ Class => jClass }
import scala.language.{implicitConversions, existentials}
import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
-/** A `ClassTag[T]` wraps a runtime class, which can be accessed via the `runtimeClass` method.
+/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances.
*
- * 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.
+ * If an implicit value of type ClassTag[T] is requested, the compiler will create one.
+ * The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed
+ * via the `runtimeClass` field. References to type parameters or abstract types are
+ * replaced by the concrete types if ClassTags are available for them.
+ *
+ * Besides accessing the erasure, a ClassTag knows how instantiate single- and multi-
+ * dimensional `Arrays` where the element type is unknown at compile time.
*
- * If an implicit value of type u.ClassTag[T] is required, the compiler will make one up on demand.
- * The implicitly created value contains in its `runtimeClass` field the runtime class that is the result of erasing type T.
- * In that value, any occurrences of type parameters or abstract types U which come themselves with a ClassTag
- * are represented by the type referenced by that tag.
- * If the type T contains unresolved references to type parameters or abstract types, a static error results.
+ * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]].
*
* @see [[scala.reflect.base.TypeTags]]
*/
@@ -76,7 +76,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
if (conforms) Some(x.asInstanceOf[T]) else None
}
- /** case class accessories */
+ // case class accessories
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass
override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass)
@@ -88,6 +88,9 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
}
}
+/**
+ * Class tags corresponding to primitive types and constructor/extractor for ClassTags.
+ */
object ClassTag {
private val ObjectTYPE = classOf[java.lang.Object]
private val NothingTYPE = classOf[scala.runtime.Nothing$]
diff --git a/src/library/scala/reflect/base/Annotations.scala b/src/library/scala/reflect/base/Annotations.scala
index e3453b1cdf..c6ef7b721c 100644
--- a/src/library/scala/reflect/base/Annotations.scala
+++ b/src/library/scala/reflect/base/Annotations.scala
@@ -3,42 +3,103 @@ package base
import scala.collection.immutable.ListMap
+/**
+ * Defines the type hierarchy for annotations.
+ */
trait Annotations { self: Universe =>
+ /** Typed information about an annotation. It can be attached to either a symbol or an annotated type.
+ *
+ * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.Annotation]] or [[scala.annotation.StaticAnnotation]]
+ * but not [[scala.annotation.ClassfileAnnotation]] or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]].
+ * Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser.
+ */
type Annotation >: Null <: AnyRef
+
+ /** A tag that preserves the identity of the `Annotation` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ */
implicit val AnnotationTag: ClassTag[Annotation]
- val Annotation: AnnotationExtractor
+ /** The constructor/deconstructor for `Annotation` instances. */
+ val Annotation: AnnotationExtractor
+
+ /** An extractor class to create and pattern match with syntax `Annotation(atp, args, javaArgs)`.
+ * Here, `atp` is the annotation type, `args` the arguments, and `javaArgs` the annotation's key-value
+ * pairs.
+ *
+ * Annotations are written to the classfile as Java annotations if `atp` conforms to
+ * `ClassfileAnnotation`. Annotations are pickled, i.e., written to scala symtab attribute in the classfile,
+ * if `atp` inherits from `StaticAnnotation` but not `ClassfileAnnotation`.
+ *
+ * For Scala annotations, arguments are stored in `args` and `javaArgs` is empty. Arguments in
+ * `args` are represented as typed trees. Note that these trees are not transformed by any phases
+ * following the type-checker. For Java annotations, `args` is empty and arguments are stored in
+ * `javaArgs`.
+ */
abstract class AnnotationExtractor {
def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation
def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])]
}
+ /** A Java annotation argument */
type JavaArgument >: Null <: AnyRef
implicit val JavaArgumentTag: ClassTag[JavaArgument]
+ /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`*/
type LiteralArgument >: Null <: AnyRef with JavaArgument
+
+ /** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ */
implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
+
+ /** The constructor/deconstructor for `LiteralArgument` instances. */
val LiteralArgument: LiteralArgumentExtractor
+ /** An extractor class to create and pattern match with syntax `LiteralArgument(value)`
+ * where `value` is the constant argument.
+ */
abstract class LiteralArgumentExtractor {
def apply(value: Constant): LiteralArgument
def unapply(arg: LiteralArgument): Option[Constant]
}
+ /** An array argument to a Java annotation as in `@Target(value={TYPE,FIELD,METHOD,PARAMETER})`
+ */
type ArrayArgument >: Null <: AnyRef with JavaArgument
+
+ /** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ */
implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
+
+ /** The constructor/deconstructor for `ArrayArgument` instances. */
val ArrayArgument: ArrayArgumentExtractor
+ /** An extractor class to create and pattern match with syntax `ArrayArgument(args)`
+ * where `args` is the argument array.
+ */
abstract class ArrayArgumentExtractor {
def apply(args: Array[JavaArgument]): ArrayArgument
def unapply(arg: ArrayArgument): Option[Array[JavaArgument]]
}
+ /** A nested argument to a Java annotation as `@Nested` in `@Outer(@Nested)`.
+ */
type NestedArgument >: Null <: AnyRef with JavaArgument
+
+ /** A tag that preserves the identity of the `NestedArgument` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ */
implicit val NestedArgumentTag: ClassTag[NestedArgument]
+
+ /** The constructor/deconstructor for `NestedArgument` instances. */
val NestedArgument: NestedArgumentExtractor
+ /** An extractor class to create and pattern match with syntax `NestedArgument(annotation)`
+ * where `annotation` is the nested annotation.
+ */
abstract class NestedArgumentExtractor {
def apply(annotation: Annotation): NestedArgument
def unapply(arg: NestedArgument): Option[Annotation]
diff --git a/src/library/scala/reflect/base/Attachments.scala b/src/library/scala/reflect/base/Attachments.scala
index 889ac0ac14..0082066fdb 100644
--- a/src/library/scala/reflect/base/Attachments.scala
+++ b/src/library/scala/reflect/base/Attachments.scala
@@ -1,35 +1,38 @@
package scala.reflect
package base
-/** Attachments is a generalisation of Position.
- * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads.
+/** Attachments 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
+ * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree`
* imposing an unnecessary memory tax because of something that will not be used in most cases.
*/
abstract class Attachments { self =>
+ /** The position type of this attachment */
type Pos >: Null
- /** Gets the underlying position */
+ /** The underlying position */
def pos: Pos
- /** Creates a copy of this attachment with its position updated */
+ /** Creates a copy of this attachment with the position replaced by `newPos` */
def withPos(newPos: Pos): Attachments { type Pos = self.Pos }
- /** Gets the underlying payload */
+ /** The underlying payload. */
def all: Set[Any] = Set.empty
private def matchesTag[T: ClassTag](datum: Any) =
classTag[T].runtimeClass == datum.getClass
+ /** An underlying payload of the given class type `T`. */
def get[T: ClassTag]: Option[T] =
(all filter matchesTag[T]).headOption.asInstanceOf[Option[T]]
- /** Creates a copy of this attachment with its payload updated */
+ /** Creates a copy of this attachment with a new payload added */
def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } =
new NonemptyAttachments(this.pos, remove[T].all + attachment)
+ /** Creates a copy of this attachment with all payloads of the given class type `T` removed. */
def remove[T: ClassTag]: Attachments { type Pos = self.Pos } = {
val newAll = all filterNot matchesTag[T]
if (newAll.isEmpty) pos.asInstanceOf[Attachments { type Pos = self.Pos }]
diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala
index 29bf2df656..6ecfd384ab 100644
--- a/src/library/scala/reflect/base/Base.scala
+++ b/src/library/scala/reflect/base/Base.scala
@@ -7,6 +7,9 @@ import scala.ref.WeakReference
import scala.collection.mutable
import scala.collection.immutable.ListMap
+/**
+ * This is an internal implementation class.
+ */
class Base extends Universe { self =>
private var nextId = 0
diff --git a/src/library/scala/reflect/base/BuildUtils.scala b/src/library/scala/reflect/base/BuildUtils.scala
index e4710316e2..5982329aef 100644
--- a/src/library/scala/reflect/base/BuildUtils.scala
+++ b/src/library/scala/reflect/base/BuildUtils.scala
@@ -1,6 +1,9 @@
package scala.reflect
package base
+/**
+ * This is an internal implementation class.
+ */
trait BuildUtils { self: Universe =>
val build: BuildBase
diff --git a/src/library/scala/reflect/base/Constants.scala b/src/library/scala/reflect/base/Constants.scala
index ba12b02e92..240434362d 100644
--- a/src/library/scala/reflect/base/Constants.scala
+++ b/src/library/scala/reflect/base/Constants.scala
@@ -6,13 +6,29 @@
package scala.reflect
package base
+/**
+ * Defines the type hierachy for compile-time constants.
+ *
+ * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ */
trait Constants {
self: Universe =>
+ /** The type of compile-time constants.
+ */
type Constant >: Null <: AnyRef
+
+ /** A tag that preserves the identity of the `Constant` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ */
implicit val ConstantTag: ClassTag[Constant]
+
+ /** The constructor/deconstructor for `Constant` instances. */
val Constant: ConstantExtractor
+ /** An extractor class to create and pattern match with syntax `Constant(value)`
+ * where `value` is the Scala value of the constant.
+ */
abstract class ConstantExtractor {
def apply(value: Any): Constant
def unapply(arg: Constant): Option[Any]
diff --git a/src/library/scala/reflect/base/Exprs.scala b/src/library/scala/reflect/base/Exprs.scala
index 45598c03e2..0fd383e8b2 100644
--- a/src/library/scala/reflect/base/Exprs.scala
+++ b/src/library/scala/reflect/base/Exprs.scala
@@ -8,16 +8,54 @@ package base
trait Exprs { self: Universe =>
- /** An expression tree tagged with its type */
+ /** Expr wraps an expression tree and tags it with its type. */
trait Expr[+T] extends Equals with Serializable {
val mirror: Mirror
+ /**
+ * Migrates the expression into another universe given its corresponding mirror.
+ */
def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # Expr[T]
+ /**
+ * The Scala syntax tree representing the wrapped expression.
+ */
def tree: Tree
+
+ /**
+ * Representation of the type of the wrapped expression tree as found via type tags.
+ */
def staticType: Type
+ /**
+ * Representation of the type of the wrapped expression tree as found in the tree.
+ */
def actualType: Type
+ /**
+ * A dummy method to mark expression splicing in reification.
+ * It should only be used within a `reify` call, which eliminates the `splice` call and embeds
+ * the wrapped tree into the reified surrounding expression.
+ * If used alone `splice` throws an exception when called at runtime.
+ *
+ * If you want to use an Expr in reification of some Scala code, you need to splice it in.
+ * For an expr of type `Expr[T]`, where `T` has a method `foo`, the following code
+ * {{{
+ * reify{ expr.splice.foo }
+ * }}}
+ * uses splice to turn an expr of type Expr[T] into a value of type T in the context of `reify`.
+ *
+ * It is equivalent to
+ * {{{
+ * Select( expr.tree, newTermName("foo") )
+ * }}}
+ *
+ * The following example code however does not compile
+ * {{{
+ * reify{ expr.foo }
+ * }}}
+ * because expr of type Expr[T] does not have a method foo.
+ */
def splice: T
+ // TODO: document this
val value: T
/** case class accessories */
@@ -27,6 +65,12 @@ trait Exprs { self: Universe =>
override def toString = "Expr["+staticType+"]("+tree+")"
}
+ /**
+ * Constructor/Extractor for Expr.
+ *
+ * Can be useful, when having a tree and wanting to splice it in reify call,
+ * in which case the tree first needs to be wrapped in an expr.
+ */
object Expr {
def apply[T: WeakTypeTag](mirror: MirrorOf[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec)
def unapply[T](expr: Expr[T]): Option[Tree] = Some(expr.tree)
diff --git a/src/library/scala/reflect/base/FlagSets.scala b/src/library/scala/reflect/base/FlagSets.scala
index 96cdbe894c..0ce7613eb3 100644
--- a/src/library/scala/reflect/base/FlagSets.scala
+++ b/src/library/scala/reflect/base/FlagSets.scala
@@ -3,7 +3,7 @@ package base
trait FlagSets { self: Universe =>
- /** An abstract type representing sets of flags that apply to definition trees and symbols */
+ /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols */
type FlagSet
/** A tag that preserves the identity of the `FlagSet` abstract type from erasure.
diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/library/scala/reflect/base/MirrorOf.scala
index 1e9619d062..6115a622bc 100644
--- a/src/library/scala/reflect/base/MirrorOf.scala
+++ b/src/library/scala/reflect/base/MirrorOf.scala
@@ -1,14 +1,33 @@
package scala.reflect
package base
+/**
+ * The base interface for all mirrors.
+ *
+ * @tparam U the type of the universe this mirror belongs to.
+ *
+ * This is defined outside the reflection universe cake pattern implementation
+ * so that it can be referenced from outside. For example TypeCreator and TreeCreator
+ * reference MirrorOf and also need to be defined outside the cake as they are
+ * used by type tags, which can be migrated between different universes and consequently
+ * cannot be bound to a fixed one.
+ *
+ * @see [[Mirrors]]
+ */
abstract class MirrorOf[U <: base.Universe with Singleton] {
- /** .. */
+ /** The universe this mirror belongs to. */
val universe: U
- /** .. */
+ /** The class symbol of the `_root_` package */
def RootClass: U#ClassSymbol
+
+ /** The module symbol of the `_root_` package */
def RootPackage: U#ModuleSymbol
+
+ /** The class symbol of the default (unnamed) package */
def EmptyPackageClass: U#ClassSymbol
+
+ /** The module symbol of the default (unnamed) package */
def EmptyPackage: U#ModuleSymbol
/** The symbol corresponding to the globally accessible class with the
diff --git a/src/library/scala/reflect/base/Mirrors.scala b/src/library/scala/reflect/base/Mirrors.scala
index 50866ef000..8cb6811dca 100644
--- a/src/library/scala/reflect/base/Mirrors.scala
+++ b/src/library/scala/reflect/base/Mirrors.scala
@@ -1,12 +1,23 @@
package scala.reflect
package base
+/**
+ * Defines a type hierarchy for mirrors.
+ *
+ * Every universe has one or more mirrors. A mirror defines a hierarchy of symbols starting with the root package `_root_`
+ * and provides methods to locate and define classes and singleton objects in that hierarchy.
+ *
+ * On the JVM, there is a one to one correspondance between class loaders and mirrors.
+ */
trait Mirrors {
self: Universe =>
- /** .. */
+ /** The base type of all mirrors of this universe */
type Mirror >: Null <: MirrorOf[self.type]
- /** .. */
+ /** The roor mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`,
+ * `Nothing`, `Null`, and all classes loaded from scala-library. The root package of this mirror contains the root
+ * packages of all other mirrors of this universe as members.
+ */
val rootMirror: Mirror
}
diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala
index ad99f54fb3..8afdb8f69b 100644
--- a/src/library/scala/reflect/base/Names.scala
+++ b/src/library/scala/reflect/base/Names.scala
@@ -4,20 +4,26 @@ package base
import scala.language.implicitConversions
/** A trait that manages names.
- * A name is a string in one of two name universes: terms and types.
- * The same string can be a name in both universes.
- * Two names are equal if they represent the same string and they are
- * members of the same universe.
- *
- * Names are interned. That is, for two names `name11 and `name2`,
- * `name1 == name2` implies `name1 eq name2`.
+ *
+ * @see TermName
+ * @see TypeName
*/
trait Names {
- /** Intentionally no implicit from String => Name. */
+ // Intentionally no implicit from String => Name.
implicit def stringToTermName(s: String): TermName = newTermName(s)
implicit def stringToTypeName(s: String): TypeName = newTypeName(s)
- /** The abstract type of names */
+ /**
+ * The abstract type of names
+ *
+ * A Name wraps a string as the name for either a type ([[TypeName]]) of a term ([[TermName]]).
+ * Two names are equal, if the wrapped string are equal and they are either both `TypeName` or both `TermName`.
+ * The same string can co-exist as a `TypeName` and a `TermName`, but they would not be equal.
+ * Names are interned. That is, for two names `name11 and `name2`,
+ * `name1 == name2` implies `name1 eq name2`.
+ *
+ * One of the reasons for the existence of names rather than plain strings is being more explicit about what is a name and if it represents a type or a term.
+ */
type Name >: Null <: NameBase
implicit val NameTag: ClassTag[Name]
@@ -31,16 +37,16 @@ trait Names {
/** The base API that all names support */
abstract class NameBase {
- /** Is this name a term name? */
+ /** Checks weather the name is a a term name */
def isTermName: Boolean
- /** Is this name a type name? */
+ /** Checks weather the name is a a type name */
def isTypeName: Boolean
- /** Returns a term name that represents the same string as this name */
+ /** Returns a term name that wraps the same string as `this` */
def toTermName: TermName
- /** Returns a type name that represents the same string as this name */
+ /** Returns a type name that wraps the same string as `this` */
def toTypeName: TypeName
}
@@ -52,7 +58,11 @@ trait Names {
*/
def newTypeName(s: String): TypeName
+ /** Wraps the empty string
+ */
def EmptyTermName: TermName = newTermName("")
+ /** Wraps the empty string
+ */
def EmptyTypeName: TypeName = EmptyTermName.toTypeName
}
diff --git a/src/library/scala/reflect/base/Positions.scala b/src/library/scala/reflect/base/Positions.scala
index 76a7382e9e..70412a2f4b 100644
--- a/src/library/scala/reflect/base/Positions.scala
+++ b/src/library/scala/reflect/base/Positions.scala
@@ -1,17 +1,22 @@
package scala.reflect
package base
+/**
+ * Defines the type hierachy for positions.
+ *
+ * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ */
trait Positions {
self: Universe =>
- /** .. */
+ /** The base type for all positions of tree nodes in source files. */
type Position >: Null <: Attachments { type Pos = Position }
- /** A tag that preserves the identity of the `FlagSet` abstract type from erasure.
+ /** A tag that preserves the identity of the `Position` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
*/
implicit val PositionTag: ClassTag[Position]
- /** .. */
+ /** A special "missing" position. */
val NoPosition: Position
}
diff --git a/src/library/scala/reflect/base/Scopes.scala b/src/library/scala/reflect/base/Scopes.scala
index a388fdc392..a8c498b814 100644
--- a/src/library/scala/reflect/base/Scopes.scala
+++ b/src/library/scala/reflect/base/Scopes.scala
@@ -1,8 +1,16 @@
package scala.reflect
package base
+/**
+ * Defines the type hierachy for scopes.
+ *
+ * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ */
trait Scopes { self: Universe =>
+ /** The base type of all scopes. A scope object generally maps names to symbols available in the current lexical scope.
+ * Scopes can be nested. This base type, however, only exposes a minimal interface, representing a scope as an iterable of symbols.
+ */
type Scope >: Null <: ScopeBase
/** The base API that all scopes support */
@@ -13,12 +21,13 @@ trait Scopes { self: Universe =>
*/
implicit val ScopeTag: ClassTag[Scope]
+ /** The base type of member scopes, as in class definitions, for example. */
type MemberScope >: Null <: Scope with MemberScopeBase
/** The base API that all member scopes support */
trait MemberScopeBase extends ScopeBase {
/** Sorts the symbols included in this scope so that:
- * 1) Symbols appear the linearization order of their owners.
+ * 1) Symbols appear in the linearization order of their owners.
* 2) Symbols with the same owner appear in reverse order of their declarations.
* 3) Synthetic members (e.g. getters/setters for vals/vars) might appear in arbitrary order.
*/
@@ -30,12 +39,12 @@ trait Scopes { self: Universe =>
*/
implicit val MemberScopeTag: ClassTag[MemberScope]
- /** Create a new scope */
+ /** Create a new scope. */
def newScope: Scope
- /** Create a new scope nested in another one with which it shares its elements */
+ /** 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 */
+ /** Create a new scope with the given initial elements. */
def newScopeWith(elems: Symbol*): Scope
} \ No newline at end of file
diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala
index 8f1c96ea3f..6d85ae9d2a 100644
--- a/src/library/scala/reflect/base/StandardDefinitions.scala
+++ b/src/library/scala/reflect/base/StandardDefinitions.scala
@@ -6,14 +6,21 @@
package scala.reflect
package base
+/**
+ * Defines standard symbols and types.
+ */
trait StandardDefinitions {
self: Universe =>
+ /** A value containing all standard defnitions. */
val definitions: DefinitionsBase
+ /** Defines standard symbols (and types via its base class). */
trait DefinitionsBase extends StandardTypes {
- // packages
+ /** The class symbol of package `scala`. */
def ScalaPackageClass: ClassSymbol
+
+ /** The module symbol of package `scala`. */
def ScalaPackage: ModuleSymbol
// top types
@@ -37,36 +44,67 @@ trait StandardDefinitions {
def DoubleClass : ClassSymbol
def BooleanClass: ClassSymbol
- // some special classes
+ /** The class symbol of class `String`. */
def StringClass : ClassSymbol
+
+ /** The class symbol of class `Class`. */
def ClassClass : ClassSymbol
+
+ /** The class symbol of class `Array`. */
def ArrayClass : ClassSymbol
+
+ /** The class symbol of class `List`. */
def ListClass : ClassSymbol
- // the Predef object
+ /** The module symbol of `scala.Predef`. */
def PredefModule: ModuleSymbol
}
+ /** Defines standard types. */
trait StandardTypes {
- // the scala value classes
+ /** The `Type` of type `Unit`. */
val UnitTpe: Type
+
+ /** The `Type` of primitive type `Byte`. */
val ByteTpe: Type
+
+ /** The `Type` of primitive type `Short`. */
val ShortTpe: Type
+
+ /** The `Type` of primitive type `Char`. */
val CharTpe: Type
+
+ /** The `Type` of primitive type `Int`. */
val IntTpe: Type
+
+ /** The `Type` of primitive type `Long`. */
val LongTpe: Type
+
+ /** The `Type` of primitive type `Float`. */
val FloatTpe: Type
+
+ /** The `Type` of primitive type `Double`. */
val DoubleTpe: Type
+
+ /** The `Type` of primitive type `Boolean`. */
val BooleanTpe: Type
- // top types
+ /** The `Type` of type `Any`. */
val AnyTpe: Type
+
+ /** The `Type` of type `AnyVal`. */
val AnyValTpe: Type
+
+ /** The `Type` of type `AnyRef`. */
val AnyRefTpe: Type
+
+ /** The `Type` of type `Object`. */
val ObjectTpe: Type
- // bottom types
+ /** The `Type` of type `Nothing`. */
val NothingTpe: Type
+
+ /** The `Type` of type `Null`. */
val NullTpe: Type
}
}
diff --git a/src/library/scala/reflect/base/StandardNames.scala b/src/library/scala/reflect/base/StandardNames.scala
index 3e569cd523..0b4ec3728a 100644
--- a/src/library/scala/reflect/base/StandardNames.scala
+++ b/src/library/scala/reflect/base/StandardNames.scala
@@ -11,6 +11,10 @@ package base
// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then it goes to api.StandardNames.
// Otherwise it goes nowhere - reflection API should stay minimalistic.
+// TODO: document better
+/**
+ * Names necessary to create Scala trees.
+ */
trait StandardNames {
self: Universe =>
diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala
index 3830264425..efdd4cb19e 100644
--- a/src/library/scala/reflect/base/Symbols.scala
+++ b/src/library/scala/reflect/base/Symbols.scala
@@ -1,9 +1,14 @@
package scala.reflect
package base
+/**
+ * Defines the type hierachy for symbols
+ *
+ * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ */
trait Symbols { self: Universe =>
- /** The abstract type of symbols representing declarations */
+ /** The type of symbols representing declarations */
type Symbol >: Null <: SymbolBase
/** A tag that preserves the identity of the `Symbol` abstract type from erasure.
@@ -11,7 +16,7 @@ trait Symbols { self: Universe =>
*/
implicit val SymbolTag: ClassTag[Symbol]
- /** The abstract type of type symbols representing type, class, and trait declarations,
+ /** The type of type symbols representing type, class, and trait declarations,
* as well as type parameters
*/
type TypeSymbol >: Null <: Symbol with TypeSymbolBase
@@ -21,7 +26,7 @@ trait Symbols { self: Universe =>
*/
implicit val TypeSymbolTag: ClassTag[TypeSymbol]
- /** The abstract type of term symbols representing val, var, def, and object declarations as
+ /** The type of term symbols representing val, var, def, and object declarations as
* well as packages and value parameters.
*/
type TermSymbol >: Null <: Symbol with TermSymbolBase
@@ -31,7 +36,7 @@ trait Symbols { self: Universe =>
*/
implicit val TermSymbolTag: ClassTag[TermSymbol]
- /** The abstract type of method symbols representing def declarations */
+ /** The type of method symbols representing def declarations */
type MethodSymbol >: Null <: TermSymbol with MethodSymbolBase
/** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure.
@@ -39,7 +44,7 @@ trait Symbols { self: Universe =>
*/
implicit val MethodSymbolTag: ClassTag[MethodSymbol]
- /** The abstract type of module symbols representing object declarations */
+ /** The type of module symbols representing object declarations */
type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolBase
/** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure.
@@ -47,7 +52,7 @@ trait Symbols { self: Universe =>
*/
implicit val ModuleSymbolTag: ClassTag[ModuleSymbol]
- /** The abstract type of class symbols representing class and trait definitions */
+ /** The type of class symbols representing class and trait definitions */
type ClassSymbol >: Null <: TypeSymbol with ClassSymbolBase
/** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure.
@@ -55,7 +60,7 @@ trait Symbols { self: Universe =>
*/
implicit val ClassSymbolTag: ClassTag[ClassSymbol]
- /** The abstract type of free terms introduced by reification */
+ /** The type of free terms introduced by reification */
type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolBase
/** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure.
@@ -63,7 +68,7 @@ trait Symbols { self: Universe =>
*/
implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol]
- /** The abstract type of free types introduced by reification */
+ /** The type of free types introduced by reification */
type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolBase
/** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure.
diff --git a/src/library/scala/reflect/base/TagInterop.scala b/src/library/scala/reflect/base/TagInterop.scala
index ec054106eb..e989631abf 100644
--- a/src/library/scala/reflect/base/TagInterop.scala
+++ b/src/library/scala/reflect/base/TagInterop.scala
@@ -4,12 +4,26 @@ package base
import scala.runtime.ScalaRunTime._
trait TagInterop { self: Universe =>
- // todo. `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work
+ // TODO `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work
// if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala
+ /**
+ * Convert a typetag to a pre `Scala-2.10` manifest.
+ * For example
+ * {{{
+ * typeTagToManifest( scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]] )
+ * }}}
+ */
def typeTagToManifest[T: ClassTag](mirror: Any, tag: base.Universe # TypeTag[T]): Manifest[T] =
throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.")
+ /**
+ * Convert a pre `Scala-2.10` manifest to a typetag.
+ * For example
+ * {{{
+ * manifestToTypeTag( scala.reflect.runtime.currentMirror, implicitly[Manifest[String]] )
+ * }}}
+ */
def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): base.Universe # TypeTag[T] =
throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.")
}
diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala
index 78174f354c..666870cb10 100644
--- a/src/library/scala/reflect/base/Trees.scala
+++ b/src/library/scala/reflect/base/Trees.scala
@@ -9,9 +9,11 @@ trait Trees { self: Universe =>
/** The base API that all trees support */
abstract class TreeBase extends Product { this: Tree =>
+ // TODO
/** ... */
def isDef: Boolean
+ // TODO
/** ... */
def isEmpty: Boolean
@@ -52,7 +54,7 @@ trait Trees { self: Universe =>
* Transformer found around the compiler.
*
* Copying Trees should be done with care depending on whether
- * it need be done lazily or strictly (see LazyTreeCopier and
+ * it needs be done lazily or strictly (see LazyTreeCopier and
* StrictTreeCopier) and on whether the contents of the mutable
* fields should be copied. The tree copiers will copy the mutable
* attributes to the new tree; calling Tree#duplicate will copy
@@ -67,8 +69,8 @@ trait Trees { self: Universe =>
*
* SymTrees include important nodes Ident and Select, which are
* used as both terms and types; they are distinguishable based on
- * whether the Name is a TermName or TypeName. The correct way for
- * to test for a type or a term (on any Tree) are the isTerm/isType
+ * whether the Name is a TermName or TypeName. The correct way
+ * to test any Tree for a type or a term are the `isTerm`/`isType`
* methods on Tree.
*
* "Others" are mostly syntactic or short-lived constructs. Examples
@@ -86,7 +88,7 @@ trait Trees { self: Universe =>
/** The empty tree */
val EmptyTree: Tree
- /** A tree for a term. Not all terms are TermTrees; use isTerm
+ /** A tree for a term. Not all trees are TermTrees; use isTerm
* to reliably identify terms.
*/
type TermTree >: Null <: AnyRef with Tree
@@ -96,7 +98,7 @@ trait Trees { self: Universe =>
*/
implicit val TermTreeTag: ClassTag[TermTree]
- /** A tree for a type. Not all types are TypTrees; use isType
+ /** A tree for a type. Not all trees are TypTrees; use isType
* to reliably identify types.
*/
type TypTree >: Null <: AnyRef with Tree
@@ -213,7 +215,7 @@ trait Trees { self: Universe =>
/** An object definition, e.g. `object Foo`. Internally, objects are
* quite frequently called modules to reduce ambiguity.
- * Eliminated by refcheck.
+ * Eliminated by compiler phase refcheck.
*/
type ModuleDef >: Null <: ImplDef
@@ -248,13 +250,14 @@ trait Trees { self: Universe =>
*/
implicit val ValOrDefDefTag: ClassTag[ValOrDefDef]
+ // FIXME: document how ValDef in self-types can be recognized. (Only private modifier is set there.)
/** Broadly speaking, a value definition. All these are encoded as ValDefs:
*
* - immutable values, e.g. "val x"
* - mutable values, e.g. "var x" - the MUTABLE flag set in mods
* - lazy values, e.g. "lazy val x" - the LAZY flag set in mods
- * - method parameters, see vparamss in DefDef - the PARAM flag is set in mods
- * - explicit self-types, e.g. class A { self: Bar => } - !!! not sure what is set.
+ * - method parameters, see vparamss in [[scala.reflect.base.Trees#DefDef]] - the PARAM flag is set in mods
+ * - explicit self-types, e.g. class A { self: Bar => }
*/
type ValDef >: Null <: ValOrDefDef
@@ -267,7 +270,7 @@ trait Trees { self: Universe =>
val ValDef: ValDefExtractor
/** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`.
- * This AST node corresponds to the following Scala code:
+ * This AST node corresponds to any of the following Scala code:
*
* mods `val` name: tpt = rhs
*
@@ -275,7 +278,7 @@ trait Trees { self: Universe =>
*
* mods name: tpt = rhs // in signatures of function and method definitions
*
- * self: Bar => // self-types (!!! not sure what is set)
+ * self: Bar => // self-types
*
* If the type of a value is not specified explicitly (i.e. is meant to be inferred),
* this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!).
@@ -369,9 +372,12 @@ trait Trees { self: Universe =>
* This AST node does not have direct correspondence to Scala code.
* It is used for tailcalls and like.
* For example, while/do are desugared to label defs as follows:
- *
+ * {{{
* while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ())
+ * }}}
+ * {{{
* do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ())
+ * }}}
*/
abstract class LabelDefExtractor {
def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef
@@ -427,7 +433,7 @@ trait Trees { self: Universe =>
*
* import expr.{selectors}
*
- * Selectors are a list of pairs of names (from, to). // [Eugene++] obviously, they no longer are. please, document!
+ * Selectors are a list of ImportSelectors, which conceptually are pairs of names (from, to).
* The last (and maybe only name) may be a nme.WILDCARD. For instance:
*
* import qual.{x, y => z, _}
@@ -498,16 +504,16 @@ trait Trees { self: Universe =>
*
* { stats; expr }
*
- * If the block is empty, the `expr` is set to `Literal(Constant(()))`. // [Eugene++] check this
+ * If the block is empty, the `expr` is set to `Literal(Constant(()))`.
*/
abstract class BlockExtractor {
def apply(stats: List[Tree], expr: Tree): Block
def unapply(block: Block): Option[(List[Tree], Tree)]
}
- /** Case clause in a pattern match, eliminated during explicitouter
+ /** Case clause in a pattern match.
* (except for occurrences in switch statements).
- * Eliminated by patmat/explicitouter.
+ * Eliminated by compiler phases patmat/explicitouter.
*/
type CaseDef >: Null <: AnyRef with Tree
@@ -524,17 +530,16 @@ trait Trees { self: Universe =>
*
* `case` pat `if` guard => body
*
- * If the guard is not present, the `guard` is set to `EmptyTree`. // [Eugene++] check this
- * If the body is not specified, the `body` is set to `EmptyTree`. // [Eugene++] check this
+ * If the guard is not present, the `guard` is set to `EmptyTree`.
+ * If the body is not specified, the `body` is set to `Literal(Constant())`
*/
abstract class CaseDefExtractor {
def apply(pat: Tree, guard: Tree, body: Tree): CaseDef
def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)]
}
- /** Alternatives of patterns, eliminated by explicitouter, except for
- * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)))
- * Eliminated by patmat/explicitouter.
+ /** Alternatives of patterns, eliminated by compiler phases patmat/explicitouter, except for
+ * occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...)))
*/
type Alternative >: Null <: TermTree
@@ -557,7 +562,7 @@ trait Trees { self: Universe =>
}
/** Repetition of pattern.
- * Eliminated by patmat/explicitouter.
+ * Eliminated by compiler phase patmat/explicitouter.
*/
type Star >: Null <: TermTree
@@ -579,8 +584,8 @@ trait Trees { self: Universe =>
def unapply(star: Star): Option[Tree]
}
- /** Bind of a variable to a rhs pattern, eliminated by explicitouter
- * Eliminated by patmat/explicitouter.
+ /** Bind a variable to a rhs pattern.
+ * Eliminated by compiler phase patmat/explicitouter.
*
* @param name
* @param body
@@ -605,8 +610,11 @@ trait Trees { self: Universe =>
def unapply(bind: Bind): Option[(Name, Tree)]
}
- /** Used to represent `unapply` methods in pattern matching.
- * Introduced by typer, eliminated by patmat/explicitouter.
+ // TODO: evaluate if UnApply can be removed or at least moved out of reflection.
+ /**
+ * Used to represent `unapply` methods in pattern matching.
+ *
+ * Introduced by typer, eliminated by patmat/explicitouter.
*
* For example:
* {{{
@@ -649,9 +657,9 @@ trait Trees { self: Universe =>
def unapply(unApply: UnApply): Option[(Tree, List[Tree])]
}
- /** Array of expressions, needs to be translated in backend.
- * This AST node is used to pass arguments to vararg arguments.
- * Introduced by uncurry.
+ /** An array of expressions. This AST node needs to be translated in backend.
+ * It is used to pass arguments to vararg arguments.
+ * Introduced by compiler phase uncurry.
*/
type ArrayValue >: Null <: TermTree
@@ -669,7 +677,7 @@ trait Trees { self: Universe =>
*
* printf("%s%d", foo, 42)
*
- * Is translated to after uncurry to:
+ * Is translated to after compiler phase uncurry to:
*
* Apply(
* Ident("printf"),
@@ -681,7 +689,7 @@ trait Trees { self: Universe =>
def unapply(arrayValue: ArrayValue): Option[(Tree, List[Tree])]
}
- /** Anonymous function, eliminated by lambdalift */
+ /** Anonymous function, eliminated by compiler phase lambdalift */
type Function >: Null <: TermTree with SymTree
/** A tag that preserves the identity of the `Function` abstract type from erasure.
@@ -694,10 +702,10 @@ trait Trees { self: Universe =>
/** An extractor class to create and pattern match with syntax `Function(vparams, body)`.
* This AST node corresponds to the following Scala code:
- *
+ *
* vparams => body
*
- * The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME
+ * The symbol of a Function is a synthetic TermSymbol having its name set to nme.ANON_FUN_NAME.
* It is the owner of the function's parameters.
*/
abstract class FunctionExtractor {
@@ -727,7 +735,7 @@ trait Trees { self: Universe =>
}
/** Either an assignment or a named argument. Only appears in argument lists,
- * eliminated by typecheck (doTypedApply), resurrected by reifier.
+ * eliminated by compiler phase typecheck (doTypedApply), resurrected by reifier.
*/
type AssignOrNamedArg >: Null <: TermTree
@@ -742,9 +750,13 @@ trait Trees { self: Universe =>
/** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`.
* This AST node corresponds to the following Scala code:
*
+ * {{{
+ * m.f(lhs = rhs)
+ * }}}
+ * {{{
* @annotation(lhs = rhs)
+ * }}}
*
- * m.f(lhs = rhs)
*/
abstract class AssignOrNamedArgExtractor {
def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg
@@ -767,17 +779,17 @@ trait Trees { self: Universe =>
*
* `if` (cond) thenp `else` elsep
*
- * If the alternative is not present, the `elsep` is set to `EmptyTree`. // [Eugene++] check this
+ * If the alternative is not present, the `elsep` is set to `Literal(Constant(()))`.
*/
abstract class IfExtractor {
def apply(cond: Tree, thenp: Tree, elsep: Tree): If
def unapply(if_ : If): Option[(Tree, Tree, Tree)]
}
- /** - Pattern matching expression (before explicitouter)
- * - Switch statements (after explicitouter)
+ /** - Pattern matching expression (before compiler phase explicitouter)
+ * - Switch statements (after compiler phase explicitouter)
*
- * After explicitouter, cases will satisfy the following constraints:
+ * After compiler phase explicitouter, cases will satisfy the following constraints:
*
* - all guards are `EmptyTree`,
* - all patterns will be either `Literal(Constant(x:Int))`
@@ -800,7 +812,7 @@ trait Trees { self: Universe =>
*
* selector `match` { cases }
*
- * // [Eugene++] say something about `val (foo, bar) = baz` and likes.
+ * `Match` is also used in pattern matching assignments like `val (foo, bar) = baz`.
*/
abstract class MatchExtractor {
def apply(selector: Tree, cases: List[CaseDef]): Match
@@ -823,7 +835,7 @@ trait Trees { self: Universe =>
*
* `return` expr
*
- * The symbol of a Return node is the enclosing method
+ * The symbol of a Return node is the enclosing method.
*/
abstract class ReturnExtractor {
def apply(expr: Tree): Return
@@ -846,7 +858,7 @@ trait Trees { self: Universe =>
*
* `try` block `catch` { catches } `finally` finalizer
*
- * If the finalizer is not present, the `finalizer` is set to `EmptyTree`. // [Eugene++] check this
+ * If the finalizer is not present, the `finalizer` is set to `EmptyTree`.
*/
abstract class TryExtractor {
def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try
@@ -875,9 +887,6 @@ trait Trees { self: Universe =>
}
/** Object instantiation
- * One should always use factory method below to build a user level new.
- *
- * @param tpt a class type
*/
type New >: Null <: TermTree
@@ -886,7 +895,8 @@ trait Trees { self: Universe =>
*/
implicit val NewTag: ClassTag[New]
- /** The constructor/deconstructor for `New` instances. */
+ /** The constructor/deconstructor for `New` instances.
+ */
val New: NewExtractor
/** An extractor class to create and pattern match with syntax `New(tpt)`.
@@ -899,11 +909,16 @@ trait Trees { self: Universe =>
* (`new` tpt).<init>[targs](args)
*/
abstract class NewExtractor {
+ /** A user level `new`.
+ * One should always use this factory method to build a user level `new`.
+ *
+ * @param tpt a class type
+ */
def apply(tpt: Tree): New
def unapply(new_ : New): Option[Tree]
}
- /** Type annotation, eliminated by cleanup */
+ /** Type annotation, eliminated by compiler phase cleanup */
type Typed >: Null <: TermTree
/** A tag that preserves the identity of the `Typed` abstract type from erasure.
@@ -924,11 +939,7 @@ trait Trees { self: Universe =>
def unapply(typed: Typed): Option[(Tree, Tree)]
}
- /** Common base class for Apply and TypeApply. This could in principle
- * be a SymTree, but whether or not a Tree is a SymTree isn't used
- * to settle any interesting questions, and it would add a useless
- * field to all the instances (useless, since GenericApply forwards to
- * the underlying fun.)
+ /** Common base class for Apply and TypeApply.
*/
type GenericApply >: Null <: TermTree
@@ -937,11 +948,11 @@ trait Trees { self: Universe =>
*/
implicit val GenericApplyTag: ClassTag[GenericApply]
- /** Explicit type application.
- * @PP: All signs point toward it being a requirement that args.nonEmpty,
+ /* @PP: All signs point toward it being a requirement that args.nonEmpty,
* but I can't find that explicitly stated anywhere. Unless your last name
* is odersky, you should probably treat it as true.
*/
+ /** Explicit type application. */
type TypeApply >: Null <: GenericApply
/** A tag that preserves the identity of the `TypeApply` abstract type from erasure.
@@ -991,7 +1002,8 @@ trait Trees { self: Universe =>
def unapply(apply: Apply): Option[(Tree, List[Tree])]
}
- /** Super reference, qual = corresponding this reference
+ // TODO: what is it used for exactly? extend docs!
+ /** Super reference, where `qual` is the corresponding `this` reference.
* A super reference C.super[M] is represented as Super(This(C), M).
*/
type Super >: Null <: TermTree
diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala
index 55708c5274..eeda6cb143 100644
--- a/src/library/scala/reflect/base/TypeTags.scala
+++ b/src/library/scala/reflect/base/TypeTags.scala
@@ -10,45 +10,80 @@ package base
import java.lang.{ Class => jClass }
import scala.language.implicitConversions
+/*
+ * TODO
+ * add @see to docs about universes
+ * [Eugene++] also mention sensitivity to prefixes, i.e. that rb.TypeTag is different from ru.TypeTag
+ * [Chris++] tag.in(some mirror) or expr.in(some mirror) (does not work for tag and exprs in macros)
+ * Backwards compat item1: [Eugene++] it might be useful, though, to guard against abstractness of the incoming type.
+ */
/**
- * 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.
+ * A type tag encapsulates a representation of type T.
+ *
+ * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are much better integrated with reflection.
*
- * === Overview ===
+ * === Overview and examples ===
*
* Type tags are organized in a hierarchy of three classes:
* [[scala.reflect.ClassTag]], [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.Universe#WeakTypeTag]].
+ *
+ * @see scala.reflect.ClassTag
+ * @see scala.reflect.base.Universe#TypeTag
+ * @see scala.reflect.base.Universe#WeakTypeTag
*
- * A [[scala.reflect.ClassTag]] carries a runtime class that corresponds to the source type T.
- * As of such, it possesses the knowledge about how to build single- and multi-dimensional arrays of elements of that type.
- * It guarantees that the source type T did not to contain any references to type parameters or abstract types.
- * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]].
- *
- * A [[scala.reflect.base.Universe#WeakTypeTag]] value wraps a full Scala type in its tpe field.
- * A [[scala.reflect.base.Universe#TypeTag]] value is an [[scala.reflect.base.Universe#WeakTypeTag]]
- * that is guaranteed not to contain any references to type parameters or abstract types.
- *
- * [Eugene++] also mention sensitivity to prefixes, i.e. that rb.TypeTag is different from ru.TypeTag
- * [Eugene++] migratability between mirrors and universes is also worth mentioning
- *
- * === Splicing ===
+ * Examples:
+ * {{{
+ * scala> class Person
+ * scala> class Container[T]
+ * scala> import scala.reflect.ClassTag
+ * scala> import scala.reflect.runtime.universe.TypeTag
+ * scala> import scala.reflect.runtime.universe.WeakTypeTag
+ * scala> def firstTypeArg( tag: WeakTypeTag[_] ) = (tag.tpe match {case TypeRef(_,_,typeArgs) => typeArgs})(0)
+ * }}}
+ * TypeTag contains concrete type arguments:
+ * {{{
+ * scala> firstTypeArg( implicitly[TypeTag[Container[Person]]] )
+ * res0: reflect.runtime.universe.Type = Person
+ * }}}
+ * TypeTag guarantees concrete type arguments (fails for references to unbound type arguments):
+ * {{{
+ * scala> def foo1[T] = implicitly[TypeTag[Container[T]]]
+ * <console>:11: error: No TypeTag available for Container[T]
+ * def foo1[T] = implicitly[TypeTag[Container[T]]]
+ * }}}
+ * WeakTypeTag allows references to unbound type arguments:
+ * {{{
+ * scala> def foo2[T] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
+ * foo2: [T]=> reflect.runtime.universe.Type
+ * scala> foo2[Person]
+ * res1: reflect.runtime.universe.Type = T
+ * }}}
+ * TypeTag allows unbound type arguments for which type tags are available:
+ * {{{
+ * scala> def foo3[T:TypeTag] = firstTypeArg( implicitly[TypeTag[Container[T]]] )
+ * foo3: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
+ * scala> foo3[Person]
+ * res1: reflect.runtime.universe.Type = Person
+ * }}}
+ * WeakTypeTag contains concrete type arguments if available via existing tags:
+ * {{{
+ * scala> def foo4[T:WeakTypeTag] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
+ * foo4: [T](implicit evidence$1: reflect.runtime.universe.WeakTypeTag[T])reflect.runtime.universe.Type
+ * scala> foo4[Person]
+ * res1: reflect.runtime.universe.Type = Person
+ * }}}
*
- * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged
- * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result.
- * An example that illustrates the TypeTag embedding, consider the following function:
*
- * import reflect.mirror._
- * def f[T: TypeTag, U] = {
- * type L = T => U
- * implicitly[WeakTypeTag[L]]
- * }
+ * [[scala.reflect.base.Universe#TypeTag]] and [[scala.reflect.base.Universe#WeakTypeTag]] are path dependent on their universe.
*
- * Then a call of f[String, Int] will yield a result of the form
+ * The default universe is [[scala.reflect.runtime.universe]]
+ *
+ * Type tags can be migrated to another universe given the corresponding mirror using
*
- * WeakTypeTag(<[ 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.
+ * {{{
+ * tag.in( other_mirror )
+ * }}}
+ *
*
* === WeakTypeTag vs TypeTag ===
*
@@ -56,14 +91,16 @@ import scala.language.implicitConversions
* This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime
* by getting cryptic errors far away from their source. For example, consider the following snippet:
*
+ * {{{
* def bind[T: WeakTypeTag](name: String, value: T): IR.Result = bind((name, value))
* def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
* object NamedParam {
* implicit def namedValue[T: WeakTypeTag](name: String, x: T): NamedParam = apply(name, x)
* def apply[T: WeakTypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
* }
- *
- * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type
+ * }}}
+ *
+ * This fragment of the Scala REPL implementation defines a `bind` function that carries a named value along with its type
* into the heart of the REPL. Using a [[scala.reflect.base.Universe#WeakTypeTag]] here is reasonable, because it is desirable
* to work with all types, even if they are type parameters or abstract type members.
*
@@ -73,7 +110,7 @@ import scala.language.implicitConversions
* If `WeakTypeTag` context bounds were replaced with `TypeTag`, then such errors would be reported statically.
* But in that case we wouldn't be able to use `bind` in arbitrary contexts.
*
- * === Backward compatibility ===
+ * === Backward compatibility with Manifests ===
*
* Type tags correspond loosely to manifests.
*
@@ -81,50 +118,69 @@ import scala.language.implicitConversions
* 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.runtime.universe.TypeTag,
*
- * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags,
- * because manifests might be removed in the next major release.
+ * In Scala 2.10, manifests are deprecated, so it's advisable to migrate them to tags,
+ * because manifests will probably be removed in the next major release.
*
- * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with TypeTags,
- * however there are a few caveats:
+ * In most cases it will be enough to replace ClassManifest with ClassTag and Manifest with TypeTag.
+ * There are however a few caveats:
*
* 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available.
- * // [Eugene++] it might be useful, though, to guard against abstractness of the incoming type.
*
* 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the base tags
* (defined in the corresponding companion objects) to find out whether it represents a primitive value class.
* You can also use `<tag>.tpe.typeSymbol.isPrimitiveValueClass` for that purpose (requires scala-reflect.jar).
*
* 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects.
- * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types).
+ * Consider assembling corresponding types using the reflection APIs provided by Java (for classes) and Scala (for types).
*
* 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API.
- * Consider using reflection API provided by Java (for classes) and Scala (for types) instead.
+ * Consider using the reflection APIs provided by Java (for classes) and Scala (for types) instead.
*/
trait TypeTags { self: Universe =>
import definitions._
/**
- * If an implicit value of type u.WeakTypeTag[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.
+ * If an implicit value of type WeakTypeTag[T] is required, the compiler will create one.
+ * A reflective representation of T can be accessed via the tpe field.
+ * Components of T can be references to type parameters or abstract types. WeakTypeTag makes an effort to
+ * be as concrete as possible, i.e. if type tags are available for the referenced type arguments or abstract types,
+ * they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will contain a reference
+ * to an abstract type. This behavior can be useful, when one expects T to be possibly partially abstract, but
+ * requires special care to handle this case. If however T is expected to be fully known, use
+ * [[scala.reflect.base.Universe#TypeTag]] instead, which statically guarantees this property.
*
* @see [[scala.reflect.base.TypeTags]]
*/
@annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}")
trait WeakTypeTag[T] extends Equals with Serializable {
+ /**
+ * Mirror corresponding to the universe of this WeakTypeTag.
+ */
val mirror: Mirror
+ /**
+ * Migrates type tag to another universe.
+ *
+ * Type tags are path dependent on their universe. This methods allows migration
+ * given the mirror corresponding to the target universe.
+ */
def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # WeakTypeTag[T]
+
+ /**
+ * Reflective representation of type T.
+ */
def tpe: Type
- /** case class accessories */
+ // case class accessories
override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]]
override def equals(x: Any) = x.isInstanceOf[WeakTypeTag[_]] && this.mirror == x.asInstanceOf[WeakTypeTag[_]].mirror && this.tpe == x.asInstanceOf[WeakTypeTag[_]].tpe
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
override def toString = "WeakTypeTag[" + tpe + "]"
}
+ /**
+ * Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags.
+ */
object WeakTypeTag {
val Byte : WeakTypeTag[scala.Byte] = TypeTag.Byte
val Short : WeakTypeTag[scala.Short] = TypeTag.Short
@@ -142,6 +198,7 @@ trait TypeTags { self: Universe =>
val Nothing : WeakTypeTag[scala.Nothing] = TypeTag.Nothing
val Null : WeakTypeTag[scala.Null] = TypeTag.Null
+
def apply[T](mirror1: MirrorOf[self.type], tpec1: TypeCreator): WeakTypeTag[T] =
tpec1(mirror1) match {
case ByteTpe => WeakTypeTag.Byte.asInstanceOf[WeakTypeTag[T]]
@@ -175,16 +232,20 @@ trait TypeTags { self: Universe =>
}
/**
- * If an implicit value of type u.TypeTag[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.
+ * A `TypeTag` is a [[scala.reflect.base.Universe#WeakTypeTag]] with the additional
+ * static guarantee that all type references are concrete, i.e. it does <b>not</b> contain any references to
+ * unresolved type parameters or abstract types.
*
* @see [[scala.reflect.base.TypeTags]]
*/
@annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
trait TypeTag[T] extends WeakTypeTag[T] with Equals with Serializable {
+ /**
+ * @inheritdoc
+ */
override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T]
- /** case class accessories */
+ // case class accessories
override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]]
override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.mirror == x.asInstanceOf[TypeTag[_]].mirror && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
@@ -239,7 +300,7 @@ trait TypeTags { self: Universe =>
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
}
- private class PredefTypeCreator[T](copyIn: Universe => Universe # TypeTag[T]) extends TypeCreator {
+ private class PredefTypeCreator[T](copyIn: Universe => Universe#TypeTag[T]) extends TypeCreator {
def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type = {
copyIn(m.universe).asInstanceOf[U # TypeTag[T]].tpe
}
@@ -250,12 +311,24 @@ trait TypeTags { self: Universe =>
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
}
- // incantations
- def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]]`
+ */
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]]`
+ */
def typeTag[T](implicit ttag: TypeTag[T]) = ttag
// big thanks to Viktor Klang for this brilliant idea!
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ */
def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]].tpe`
+ */
def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe
}
@@ -276,3 +349,4 @@ private[scala] class SerializedTypeTag(var tpec: TypeCreator, var concrete: Bool
else WeakTypeTag(rootMirror, tpec)
}
}
+ \ No newline at end of file
diff --git a/src/library/scala/reflect/base/Types.scala b/src/library/scala/reflect/base/Types.scala
index 839c49805a..b2ee3bc4d3 100644
--- a/src/library/scala/reflect/base/Types.scala
+++ b/src/library/scala/reflect/base/Types.scala
@@ -1,6 +1,14 @@
package scala.reflect
package base
+/**
+ * Defines the type hierachy for types.
+ *
+ * Note: Because of implementation details, some type factories have return type `Type`
+ * instead of a more precise type.
+ *
+ * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ */
trait Types { self: Universe =>
/** The type of Scala types, and also Scala type signatures.
@@ -26,14 +34,14 @@ trait Types { self: Universe =>
*/
val NoPrefix: Type
- /** The type of Scala singleton types, i.e. types that are inhabited
+ /** The type of Scala singleton types, i.e., types that are inhabited
* by only one nun-null value. These include types of the forms
* {{{
* C.this.type
* C.super.type
* x.type
* }}}
- * as well as constant types.
+ * as well as [[ConstantType constant types]].
*/
type SingletonType >: Null <: Type
@@ -42,8 +50,8 @@ trait Types { self: Universe =>
*/
implicit val SingletonTypeTag: ClassTag[SingletonType]
- /** The `ThisType` type describes types of the form on the left with the
- * correspnding ThisType representations to the right.
+ /** A singleton type that describes types of the form on the left with the
+ * corresponding `ThisType` representation to the right:
* {{{
* C.this.type ThisType(C)
* }}}
@@ -62,7 +70,10 @@ trait Types { self: Universe =>
* where `sym` is the class prefix of the this type.
*/
abstract class ThisTypeExtractor {
- def apply(sym: Symbol): Type // not ThisTypebecause of implementation details
+ /**
+ * Creates a ThisType from the given class symbol.
+ */
+ def apply(sym: Symbol): Type
def unapply(tpe: ThisType): Option[Symbol]
}
@@ -120,7 +131,7 @@ trait Types { self: Universe =>
}
/** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant.
- * The REPL expresses constant types like Int(11). Here are some constants with their types.
+ * The REPL expresses constant types like `Int(11)`. Here are some constants with their types:
* {{{
* 1 ConstantType(Constant(1))
* "abc" ConstantType(Constant("abc"))
@@ -401,7 +412,7 @@ trait Types { self: Universe =>
val WildcardType: Type
/** BoundedWildcardTypes, used only during type inference, are created in
- * two places that I can find:
+ * two places:
*
* 1. If the expected type of an expression is an existential type,
* its hidden symbols are replaced with bounded wildcards.
@@ -417,8 +428,12 @@ trait Types { self: Universe =>
*/
implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
+ /** The constructor/deconstructor for `BoundedWildcardType` instances. */
val BoundedWildcardType: BoundedWildcardTypeExtractor
+ /** An extractor class to create and pattern match with syntax `BoundedWildcardTypeExtractor(bounds)`
+ * with `bounds` denoting the type bounds.
+ */
abstract class BoundedWildcardTypeExtractor {
def apply(bounds: TypeBounds): BoundedWildcardType
def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala
index 36b85ca714..be1b60933a 100644
--- a/src/library/scala/reflect/base/Universe.scala
+++ b/src/library/scala/reflect/base/Universe.scala
@@ -18,24 +18,39 @@ abstract class Universe extends Symbols
with BuildUtils
with Mirrors
{
- /** 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.
+ /** Produce the abstract syntax tree representing the given Scala expression.
+ *
+ * For example
+ *
+ * {{{
+ * val five = reify{ 5 } // Literal(Constant(5))
+ * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) )
+ * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("$plus")), List( Literal(Constant(4)) ) )
+ * }}}
+ *
+ * The produced tree is path dependent on the Universe `refiy` was called from.
+ *
+ * Use [[splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced.
+ *
+ * == Further info and implementation details ==
+ *
+ * `refiy` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree.
*
- * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression:
+ * For instance in `reify{ x + 1 }` the macro `reify` receives the abstract syntax tree of `x + 1` as its argument, which is
*
* {{{
* Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
* }}}
*
- * The reifier transforms it to the following expression:
+ * and returns a tree, which produces the tree above, when compiled and executed. So in other terms, the refiy call expands to something like
*
* {{{
- * <[
* val $u: u.type = u // where u is a reference to the Universe that calls the reify
* $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1))))))
- * ]>
* }}}
- *
+ *
+ * ------
+ *
* Reification performs expression splicing (when processing Expr.splice)
* and type splicing (for every type T that has a TypeTag[T] implicit in scope):
*
@@ -54,11 +69,11 @@ abstract class Universe extends Symbols
* }}}
*
* The transformation looks mostly straightforward, but it has its tricky parts:
- * * Reifier retains symbols and types defined outside the reified tree, however
+ * - 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,
+ * - 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
*/
// implementation is hardwired to `scala.reflect.reify.Taggers`
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index d97f2ec633..e78ec7599a 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -1,5 +1,51 @@
package scala
+/**
+ * The base package of Scala's reflection library.
+ *
+ * The refection library is structured according to the 'cake pattern'. The base layer
+ * resides in package [[scala.reflect.base]] and defines an interface to the following main types:
+ *
+ * - [[scala.reflect.base.Types#Type Types]] represent types
+ * - [[scala.reflect.base.Symbol#Symbol Symbols]] represent definitions
+ * - [[scala.reflect.base.Trees#Tree Trees]] represent abstract syntax trees
+ * - [[scala.reflect.base.Names#Name Names]] represent term and type names
+ * - [[scala.reflect.base.AnnotationInfos#AnnotationInfo AnnotationInfos]] represent annotations
+ * - [[scala.reflect.base.Position#Positions Positions]] represent source positions of tree nodes
+ * - [[scala.reflect.base.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
+ * definition trees
+ * - [[scala.reflect.base.Constansts#Constant Constants]] represent compile-time constants.
+ *
+ * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class
+ * [[scala.reflect.base.Universe Universe]]. The base universe defines a minimal interface to the above types.
+ * Universes that provide additional functionality such as deeper introspection or runtime code generation,
+ * are defined in packages [[scala.reflect.api]] and [[scala.tools.reflect]].
+ *
+ * The cake pattern employed here requires to write certain Scala idioms with more indirections that usual.
+ * What follows is a description of these indirections, which will help to navigate the Scaladocs easily.
+ *
+ * For instance, consider the base type of all abstract syntax trees: [[scala.reflect.base.Trees#Tree]].
+ * This type is not a class but is abstract and has an upper bound of [[scala.reflect.base.Trees#TreeBase]],
+ * which is a class defining the minimal base interface for all trees.
+ *
+ * For a more interesting tree type, consider [[scala.reflect.base.Trees#If]] representing if-expressions.
+ * It does not come with a class `IfBase`, since it does not add anything to the interface of its upper
+ * bound `TermTree`. However, it is defined next to a value `If` of type [[scala.reflect.base.Trees#IfExtractor]].
+ * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply`
+ * for pattern matching. Moreover, there is an implicit value [[scala.reflect.base.Trees#IfTag]] of type
+ * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `If`:
+ * {{{
+ * tree match { case ifTree: If => ... }
+ * }}}
+ * Without the given implicit value, this pattern match would raise an "unchecked" warning at compile time
+ * since `If` is an abstract type that gets erased at runtime. See [[scala.reflect.ClassTag]] for details.
+ *
+ * To summarize: each tree type `X` (and similarly for other types such as `Type` or `Symbol`) is represented
+ * by an abstract type `X`, optionally together with a class `XBase` that defines `X`'s' interface.
+ * `X`'s companion object, if it exists, is represented by a value `X` that is of type `XExtractor`.
+ * Moreover, for each type `X`, there is a value `XTag` of type `ClassTag[X]` that allows to pattern match
+ * on `X`.
+ */
package object reflect {
lazy val basis: base.Universe = new base.Base