diff options
24 files changed, 681 insertions, 186 deletions
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 8a595473cc..1a574836c0 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 type members are + * replaced by the concrete types if ClassTags are available for them. + * + * Besides accessing the erasure, a ClassTag knows how to 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..107443f09b 100644 --- a/src/library/scala/reflect/base/Annotations.scala +++ b/src/library/scala/reflect/base/Annotations.scala @@ -3,42 +3,102 @@ 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.StaticAnnotation]] + * 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, scalaArgs, javaArgs)`. + * Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value + * pairs. + * + * Annotations are pickled, i.e. written to scala symtab attribute in the classfile. + * Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`. + * + * For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in + * `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases + * following the type-checker. For Java annotations, `scalaArgs` 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 annotation 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..479ab9a857 100644 --- a/src/library/scala/reflect/base/Attachments.scala +++ b/src/library/scala/reflect/base/Attachments.scala @@ -1,35 +1,42 @@ 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 generalization of Position. Typically it stores a Position of a tree, but this can be extended to + * encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written + * with `update[T]` and `remove[T]`. * - * 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 with the guarantee that no two elements have the same type. */ 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 the payload slot of T added/updated with the provided value. + * + * Replaces an existing payload of the same type, if exists. + */ 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 the payload 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..bd15c65711 100644 --- a/src/library/scala/reflect/base/Exprs.scala +++ b/src/library/scala/reflect/base/Exprs.scala @@ -8,16 +8,71 @@ 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 mirror, jumping into a different universe if necessary. + * + * This means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). + */ 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] itself does not have a method foo. + */ def splice: T + /** + * A dummy value to denote cross-stage path-dependent type dependencies. + * + * For example for the following macro definition: + * {{{ + * class X { type T } + * object Macros { def foo(x: X): x.T = macro Impls.foo_impl } + * }}} + * + * The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x): + * {{{ + * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } + * }}} + */ val value: T /** case class accessories */ @@ -27,6 +82,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..4e54a2fae7 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 module 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..e38a3d1cdd 100644 --- a/src/library/scala/reflect/base/Mirrors.scala +++ b/src/library/scala/reflect/base/Mirrors.scala @@ -1,12 +1,22 @@ 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 root 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, which are shared across all mirrors within the enclosing universe. + */ val rootMirror: Mirror } diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala index ad99f54fb3..b02038a920 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 wether the name is a a term name */ def isTermName: Boolean - /** Is this name a type name? */ + /** Checks wether 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. Can be used as the null object for term name. + */ def EmptyTermName: TermName = newTermName("") + /** Wraps the empty string. Can be used as the null object for term name. + */ 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..4df8501b3d 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 class 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..4a1eef014c 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. @@ -81,10 +86,10 @@ trait Symbols { self: Universe => * that directly contains the current symbol's definition. * The `NoSymbol` symbol does not have an owner, and calling this method * on one causes an internal error. - * The owner of the Scala root class [[scala.reflect.api.mirror.RootClass]] - * and the Scala root object [[scala.reflect.api.mirror.RootPackage]] is `NoSymbol`. + * The owner of the Scala root class [[scala.reflect.base.MirrorOf.RootClass]] + * and the Scala root object [[scala.reflect.base.MirrorOf.RootPackage]] is `NoSymbol`. * Every other symbol has a chain of owners that ends in - * [[scala.reflect.api.mirror.RootClass]]. + * [[scala.reflect.base.MirrorOf.RootClass]]. */ def owner: Symbol 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/TreeCreator.scala b/src/library/scala/reflect/base/TreeCreator.scala index c9c8de2307..5de0094f1f 100644 --- a/src/library/scala/reflect/base/TreeCreator.scala +++ b/src/library/scala/reflect/base/TreeCreator.scala @@ -1,6 +1,26 @@ package scala.reflect package base +/** A mirror-aware factory for trees. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a tree one needs to know a universe that the tree is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TreeCreator` implements this notion by providing a standalone tree factory. + * + * This is immediately useful for reification. When the compiler reifies an expression, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's reifying an expression into (specified by the target of the `reify` call), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the reifee). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TreeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ abstract class TreeCreator { def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Tree } diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala index 78174f354c..428b493478 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 representing terms 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 representing types 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 @@ -253,8 +255,8 @@ trait Trees { self: Universe => * - 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 +269,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 +277,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 +371,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 +432,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 +503,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 (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher) */ type CaseDef >: Null <: AnyRef with Tree @@ -524,17 +529,19 @@ 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 Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher), + * except for + * occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...))) */ type Alternative >: Null <: TermTree @@ -557,7 +564,8 @@ trait Trees { self: Universe => } /** Repetition of pattern. - * Eliminated by patmat/explicitouter. + * + * Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). */ type Star >: Null <: TermTree @@ -579,8 +587,9 @@ 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 phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). * * @param name * @param body @@ -605,8 +614,8 @@ 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. + /** + * Used to represent `unapply` methods in pattern matching. * * For example: * {{{ @@ -629,6 +638,8 @@ trait Trees { self: Universe => * EmptyTree, * Ident(newTermName("x"))))) * }}} + * + * Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher). */ type UnApply >: Null <: TermTree @@ -649,9 +660,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 +680,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 +692,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 +705,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. * It is the owner of the function's parameters. */ abstract class FunctionExtractor { @@ -727,7 +738,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 +753,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 +782,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 before 2.10 / patmat from 2.10) + * - Switch statements (after compiler phase explicitouter before 2.10 / patmat from 2.10) * - * After explicitouter, cases will satisfy the following constraints: + * After compiler phase explicitouter before 2.10 / patmat from 2.10, cases will satisfy the following constraints: * * - all guards are `EmptyTree`, * - all patterns will be either `Literal(Constant(x:Int))` @@ -800,7 +815,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 +838,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 +861,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 +890,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 +898,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 +912,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 +942,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 +951,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,8 +1005,8 @@ trait Trees { self: Universe => def unapply(apply: Apply): Option[(Tree, List[Tree])] } - /** Super reference, qual = corresponding this reference - * A super reference C.super[M] is represented as Super(This(C), M). + /** 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/TypeCreator.scala b/src/library/scala/reflect/base/TypeCreator.scala index 8a14e53dd3..0260fe1410 100644 --- a/src/library/scala/reflect/base/TypeCreator.scala +++ b/src/library/scala/reflect/base/TypeCreator.scala @@ -1,6 +1,26 @@ package scala.reflect package base +/** A mirror-aware factory for types. + * + * In the reflection API, artifacts are specific to universes and + * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors. + * + * Therefore to build a type one needs to know a universe that the type is going to be bound to + * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int` + * points to a core class `Int` from scala-library.jar). + * + * `TypeCreator` implements this notion by providing a standalone type factory. + * + * This is immediately useful for type tags. When the compiler creates a type tag, + * the end result needs to make sense in any mirror. That's because the compiler knows + * the universe it's creating a type tag for (since `TypeTag` is path-dependent on a universe), + * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM + * it doesn't know what classloader use to resolve symbolic names in the type tag). + * + * Due to a typechecker restriction (no eta-expansion for dependent method types), + * `TypeCreator` can't have a functional type, so it's implemented as class with an apply method. + */ abstract class TypeCreator { def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type } diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index 55708c5274..db9fa95553 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -10,45 +10,79 @@ 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 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]], [[scala.reflect.base.Universe#TypeTag]], [[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 ) + * }}} + * + * See [[scala.reflect.base.TypeTags#WeakTypeTag.in]] * * === WeakTypeTag vs TypeTag === * @@ -56,14 +90,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 +109,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 +117,72 @@ 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. + * + * Migration means that all symbolic references to classes/objects/packages in the expression + * will be re-resolved within the new mirror (typically using that mirror's classloader). + */ 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 +200,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 +234,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,23 +302,36 @@ 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 } } - private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { + private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe#TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { override lazy val tpe: Type = _tpe private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } - // incantations + /** + * Shortcut for `implicitly[WeakTypeTag[T]]` + */ def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag + + /** + * 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 +352,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..0b5d5ed685 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 `reify` was called from. + * + * Use [[scala.reflect.base.Exprs#Expr.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 == + * + * `reify` 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,12 +69,10 @@ 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, - * special measures are taken to ensure that all members accessed in the reifee remain visible + * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol` + * - Mutable variables that are accessed from a local function are wrapped in refs */ // implementation is hardwired to `scala.reflect.reify.Taggers` // using the mechanism implemented in `scala.tools.reflect.FastTrack` diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index d97f2ec633..046491ae10 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -1,5 +1,74 @@ package scala +/** + * The base package of Scala's reflection library. + * + * The reflection 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.Symbols#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.Annotations#Annotation Annotations]] represent annotations + * - [[scala.reflect.base.Positions#Position 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.Constants#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. + * + * {{{ + * import scala.reflect.runtime.universe._ + * val cond = reify{ condition }.tree // <- just some tree representing a condition + * val body = Literal(Constant(1)) + * val other = Literal(Constant(2)) + * val iftree = If(cond,body,other) + * }}} + * + * is equivalent to + * + * {{{ + * import scala.reflect.runtime.universe._ + * val iftree = reify{ if( condition ) 1 else 2 }.tree + * }}} + * + * and can be pattern matched as + * + * {{{ + * iftree match { case If(cond,body,other) => ... } + * }}} + * + * 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`: + * {{{ + * iftree match { case _: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 |