From c6866a28faf67cd2e455f9a0a829859a73e38819 Mon Sep 17 00:00:00 2001 From: "Paolo G. Giarrusso" Date: Tue, 25 Sep 2012 01:25:20 +0200 Subject: SI-6422: add missing Fractional and Integral alias in scala package --- src/library/scala/package.scala | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/library') diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index a41cdedfa9..fbb98d0582 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -95,7 +95,10 @@ package object scala { val Equiv = scala.math.Equiv type Fractional[T] = scala.math.Fractional[T] + val Fractional = scala.math.Fractional + type Integral[T] = scala.math.Integral[T] + val Integral = scala.math.Integral type Numeric[T] = scala.math.Numeric[T] val Numeric = scala.math.Numeric -- cgit v1.2.3 From 7a6905dc158a7a543ba3f4ddeeffe538580958d3 Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Tue, 9 Oct 2012 15:45:35 -0700 Subject: SI-6440: Revert change to `TraversableLike.filterNot` Commit df9f470f14262b9b1002f022c2620d8c38835805 introduced a change to `TraversableLike.filterNot` which broke Stream implementation that does override `filter` implementation but does not override `filterNot` implementation. This shows clearly that reusing code for strict and non-strict collections is very problematic. Added a test-case covering this problem. Closes SI-6440. Review by @retronym. --- src/library/scala/collection/TraversableLike.scala | 7 +------ test/files/run/t6440.check | 1 + test/files/run/t6440.scala | 7 +++++++ 3 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 test/files/run/t6440.check create mode 100644 test/files/run/t6440.scala (limited to 'src/library') diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index ce0b130b86..7849f1c544 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -271,12 +271,7 @@ trait TraversableLike[+A, +Repr] extends Any * @return a new $coll consisting of all elements of this $coll that do not satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filterNot(p: A => Boolean): Repr = { - val b = newBuilder - for (x <- this) - if (!p(x)) b += x - b.result - } + def filterNot(p: A => Boolean): Repr = filter(!p(_)) def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) diff --git a/test/files/run/t6440.check b/test/files/run/t6440.check new file mode 100644 index 0000000000..b5684daee4 --- /dev/null +++ b/test/files/run/t6440.check @@ -0,0 +1 @@ +Stream((), ?) diff --git a/test/files/run/t6440.scala b/test/files/run/t6440.scala new file mode 100644 index 0000000000..2b690f31e1 --- /dev/null +++ b/test/files/run/t6440.scala @@ -0,0 +1,7 @@ +object Test { + + def main(args: Array[String]): Unit = { + println(Stream.continually(()).filterNot(_ => false).take(2)) + } + +} -- cgit v1.2.3 From 4c7127d9acb1e0bae6f14a6b40019a535d057112 Mon Sep 17 00:00:00 2001 From: Mirco Dotta Date: Wed, 10 Oct 2012 09:29:30 +0200 Subject: Deprecated instrumentation API The instrumentation logic needed by the Scala IDE Worksheet is currently part of the Scala project, but it doesn't need to be. I already have a PR ready for completely removing the instrumentation logic, but I considered it too risky at this point for 2.10.0 release (an oversight can lead to the impossibility of running the worksheet with Scala 2.10.0). For the moment, I believe it's better to deprecate the whole instrumentation API in 2.10.0, and the PR for removing the instrumentation logic will target 2.10.1 or 2.11.0. Besides deprecating the instrumentation API, this commit also raised visibility of `interruptsEnabled` member in `Global`. This change alone is sufficient for moving the instrumentation logic outside of the compiler, and it is needed because the Presentation Compiler thread should never be interrupted while instrumenting a source. This commit is related to SI-6458 --- src/compiler/scala/tools/nsc/interactive/CompilerControl.scala | 2 ++ src/compiler/scala/tools/nsc/interactive/Global.scala | 3 ++- src/compiler/scala/tools/nsc/interactive/REPL.scala | 3 +++ src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala | 1 + src/compiler/scala/tools/nsc/scratchpad/Mixer.scala | 1 + src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala | 1 + src/library/scala/runtime/WorksheetSupport.scala | 1 + 7 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/library') diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index ae38a082ca..9af90eb204 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -221,6 +221,7 @@ trait CompilerControl { self: Global => * everything is brought up to date in a regular type checker run. * @param response The response. */ + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") def askInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) = postWorkItem(new AskInstrumentedItem(source, line, response)) @@ -388,6 +389,7 @@ trait CompilerControl { self: Global => response raise new MissingResponse } + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") case class AskInstrumentedItem(val source: SourceFile, line: Int, response: Response[(String, Array[Char])]) extends WorkItem { def apply() = self.getInstrumented(source, line, response) override def toString = "getInstrumented "+source diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 5514983d98..01889f4f98 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -205,7 +205,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") protected[interactive] var minRunId = 1 - private var interruptsEnabled = true + private[interactive] var interruptsEnabled = true private val NoResponse: Response[_] = new Response[Any] @@ -1041,6 +1041,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } } + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) = try { interruptsEnabled = false diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index afac5828e5..be837b32f3 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -92,6 +92,7 @@ object REPL { val completeResult = new Response[List[comp.Member]] val typedResult = new Response[comp.Tree] val structureResult = new Response[comp.Tree] + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") val instrumentedResult = new Response[(String, Array[Char])] def makePos(file: String, off1: String, off2: String) = { @@ -124,6 +125,7 @@ object REPL { * @param iContents An Array[Char] containing the instrumented source * @return The name of the instrumented source file */ + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") def writeInstrumented(iFullName: String, suffix: String, iContents: Array[Char]): String = { val iSimpleName = iFullName drop ((iFullName lastIndexOf '.') + 1) val iSourceName = iSimpleName + suffix @@ -142,6 +144,7 @@ object REPL { * and outputs in the right column, or None if the presentation compiler * does not respond to askInstrumented. */ + @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") def instrument(arguments: List[String], line: Int): Option[(String, String)] = { val source = toSourceFile(arguments.head) // strip right hand side comment column and any trailing spaces from all lines diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala index 7d332d9f7f..7f0265bf4f 100644 --- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala +++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala @@ -6,6 +6,7 @@ import scala.collection.mutable.ArrayBuffer import scala.reflect.internal.Chars.{isLineBreakChar, isWhitespace} import ast.parser.Tokens._ +@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") trait ScratchPadMaker { self: Global => import definitions._ diff --git a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala index f7ad39bd95..10e9982594 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala @@ -7,6 +7,7 @@ import java.lang.reflect.InvocationTargetException import scala.reflect.runtime.ReflectionUtils._ import scala.collection.mutable.ArrayBuffer +@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") class Mixer { protected val stdSeparator = "//> " diff --git a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala index 5eeab53fca..01dccd7521 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala @@ -5,6 +5,7 @@ import java.io.Writer import scala.reflect.internal.util.SourceFile import scala.reflect.internal.Chars._ +@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") object SourceInserter { def stripRight(cs: Array[Char]): Array[Char] = { val lines = diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala index a003bba034..016a0d04e0 100644 --- a/src/library/scala/runtime/WorksheetSupport.scala +++ b/src/library/scala/runtime/WorksheetSupport.scala @@ -4,6 +4,7 @@ import scala.runtime.ScalaRunTime.stringOf /** A utility object that's needed by the code that executes a worksheet. */ +@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") object WorksheetSupport { /** The offset in the source which should be printed */ -- cgit v1.2.3 From bc25fc53ade2131a2717b3101a01abbbfcbdf646 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Wed, 10 Oct 2012 11:59:54 +0200 Subject: SI-6099 - Scaladoc for scala.concurrent incomplete This is a rebase and resubmission of @phaller's pull https://github.com/scala/scala/pull/1485 With the reviewers' comments additionally addressed --- build.xml | 2 +- src/library/scala/concurrent/Awaitable.scala | 55 +++++++++++++--------- src/library/scala/concurrent/package.scala | 70 ++++++++++++++-------------- 3 files changed, 70 insertions(+), 57 deletions(-) (limited to 'src/library') diff --git a/build.xml b/build.xml index 9109da5276..c9027e0985 100644 --- a/build.xml +++ b/build.xml @@ -2337,7 +2337,7 @@ DOCUMENTATION docfooter="epfl" docsourceurl="${scaladoc.url}€{FILE_PATH}.scala#L1" docUncompilable="${src.dir}/library-aux" - skipPackages="scala.reflect.macros.internal:scala.reflect.internal:scala.reflect.io" + skipPackages="scala.reflect.macros.internal:scala.reflect.internal:scala.reflect.io:scala.concurrent.impl" sourcepath="${src.dir}" classpathref="pack.classpath" addparams="${scalac.args.all}" diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala index 3bd7617bce..c0c688bf42 100644 --- a/src/library/scala/concurrent/Awaitable.scala +++ b/src/library/scala/concurrent/Awaitable.scala @@ -14,36 +14,47 @@ import scala.concurrent.duration.Duration +/** + * An object that may eventually be completed with a result value of type `T` which may be + * awaited using blocking methods. + * + * The [[Await]] object provides methods that allow accessing the result of an `Awaitable` + * by blocking the current thread until the `Awaitable` has been completed or a timeout has + * occurred. + */ trait Awaitable[+T] { + /** - * Await the "resolved" state of this Awaitable. - * This method should not be called directly. - * - * @param atMost - * maximum wait time, which may be negative (no waiting is done), - * [[Duration.Inf]] for unbounded waiting, or a finite positive - * duration - * @return the Awaitable itself - * @throws InterruptedException if the wait call was interrupted - * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready - * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] + * Await the "completed" state of this `Awaitable`. + * + * '''''This method should not be called directly; use [[Await.ready]] instead.''''' + * + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return this `Awaitable` + * @throws InterruptedException if the current thread is interrupted while waiting + * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready + * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]] */ @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) def ready(atMost: Duration)(implicit permit: CanAwait): this.type /** - * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable). - * This method should not be called directly. - * - * @param atMost - * maximum wait time, which may be negative (no waiting is done), - * [[Duration.Inf]] for unbounded waiting, or a finite positive - * duration - * @return the value if the Awaitable was successful within the specific maximum wait time - * @throws InterruptedException if the wait call was interrupted - * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready - * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] + * Await and return the result (of type `T`) of this `Awaitable`. + * + * '''''This method should not be called directly; use [[Await.result]] instead.''''' + * + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the result value if the `Awaitable` is completed within the specific maximum wait time + * @throws InterruptedException if the current thread is interrupted while waiting + * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready + * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]] */ @throws(classOf[Exception]) def result(atMost: Duration)(implicit permit: CanAwait): T diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index e683732e41..c0d46df883 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -23,7 +23,7 @@ package object concurrent { * The result becomes available once the asynchronous computation is completed. * * @tparam T the type of the result - * @param body the asychronous computation + * @param body the asynchronous computation * @param execctx the execution context on which the future is run * @return the `Future` holding the result of the computation */ @@ -37,17 +37,15 @@ package object concurrent { */ def promise[T]()(implicit execctx: ExecutionContext): Promise[T] = Promise[T]() - /** Used to designate a piece of code which potentially blocks, allowing the BlockContext to adjust the runtime's behavior. + /** Used to designate a piece of code which potentially blocks, allowing the current [[BlockContext]] to adjust + * the runtime's behavior. * Properly marking blocking code may improve performance or avoid deadlocks. * - * If you have an `Awaitable` then you should use Await.result instead of `blocking`. + * Blocking on an [[Awaitable]] should be done using [[Await.result]] instead of `blocking`. * * @param body A piece of code which contains potentially blocking or long running calls. - * - * Calling this method may throw the following exceptions: - * - CancellationException - if the computation was cancelled - * - InterruptedException - in the case that a wait within the blockable object was interrupted - * - TimeoutException - in the case that the blockable object timed out + * @throws `CancellationException` if the computation was cancelled + * @throws `InterruptedException` in the case that a wait within the blocking `body` was interrupted */ @throws(classOf[Exception]) def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission) @@ -67,19 +65,21 @@ package concurrent { */ object Await { /** - * Await the "resolved" state of this Awaitable. - * Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`. - * - * @param awaitable - * the `Awaitable` on which `ready` is to be called - * @param atMost - * maximum wait time, which may be negative (no waiting is done), - * [[Duration.Inf]] for unbounded waiting, or a finite positive - * duration - * @return the awaitable itself - * @throws InterruptedException if the wait call was interrupted - * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready - * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] + * Await the "completed" state of an `Awaitable`. + * + * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that + * the underlying [[ExecutionContext]] is prepared to properly manage the blocking. + * + * @param awaitable + * the `Awaitable` to be awaited + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the `awaitable` + * @throws InterruptedException if the current thread is interrupted while waiting + * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready + * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]] */ @throws(classOf[TimeoutException]) @throws(classOf[InterruptedException]) @@ -87,19 +87,21 @@ package concurrent { blocking(awaitable.ready(atMost)(AwaitPermission)) /** - * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable). - * Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`. - * - * @param awaitable - * the `Awaitable` on which `result` is to be called - * @param atMost - * maximum wait time, which may be negative (no waiting is done), - * [[Duration.Inf]] for unbounded waiting, or a finite positive - * duration - * @return the value if the Awaitable was successful within the specific maximum wait time - * @throws InterruptedException if the wait call was interrupted - * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready - * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]] + * Await and return the result (of type `T`) of an `Awaitable`. + * + * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that + * the underlying [[ExecutionContext]] to properly detect blocking and ensure that there are no deadlocks. + * + * @param awaitable + * the `Awaitable` to be awaited + * @param atMost + * maximum wait time, which may be negative (no waiting is done), + * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive + * duration + * @return the result value if `awaitable` is completed within the specific maximum wait time + * @throws InterruptedException if the current thread is interrupted while waiting + * @throws TimeoutException if after waiting for the specified time `awaitable` is still not ready + * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]] */ @throws(classOf[Exception]) def result[T](awaitable: Awaitable[T], atMost: Duration): T = -- cgit v1.2.3 From 68b798e3ec9ae9441d19bd06a040c869c494f159 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Wed, 10 Oct 2012 15:55:43 +0200 Subject: SI-6453 Documentation links for @switch are broken --- src/library/scala/annotation/switch.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala index a867783455..20056bc03c 100644 --- a/src/library/scala/annotation/switch.scala +++ b/src/library/scala/annotation/switch.scala @@ -9,8 +9,7 @@ package scala.annotation /** An annotation to be applied to a match expression. If present, * the compiler will verify that the match has been compiled to a - * [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc14.html tableswitch]] - * or [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc8.html#lookupswitch lookupswitch]] + * [[http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10 tableswitch or lookupswitch]] * and issue an error if it instead compiles into a series of conditional expressions. * Example usage: {{{ -- cgit v1.2.3 From e95a00992599f59f7c74bcc171bb290f859ab848 Mon Sep 17 00:00:00 2001 From: Heather Miller Date: Thu, 11 Oct 2012 20:31:42 +0200 Subject: Adds lots of new documentation for TypeTags, Mirrors, Universes and more Additionally includes improvements, formatting fixes, and link additions and fixes. --- src/library/scala/reflect/ClassTag.scala | 35 ++- src/reflect/scala/reflect/api/Annotations.scala | 13 +- src/reflect/scala/reflect/api/Constants.scala | 76 +++++- src/reflect/scala/reflect/api/Exprs.scala | 3 +- src/reflect/scala/reflect/api/FlagSets.scala | 59 +++-- src/reflect/scala/reflect/api/Importers.scala | 34 +-- src/reflect/scala/reflect/api/JavaMirrors.scala | 22 +- src/reflect/scala/reflect/api/Mirror.scala | 13 +- src/reflect/scala/reflect/api/Mirrors.scala | 201 +++++++++++++++- src/reflect/scala/reflect/api/Names.scala | 4 +- src/reflect/scala/reflect/api/Position.scala | 24 ++ src/reflect/scala/reflect/api/Printers.scala | 78 ++++--- .../scala/reflect/api/StandardDefinitions.scala | 7 +- src/reflect/scala/reflect/api/StandardNames.scala | 3 +- src/reflect/scala/reflect/api/TreeCreator.scala | 2 +- src/reflect/scala/reflect/api/TypeCreator.scala | 6 +- src/reflect/scala/reflect/api/TypeTags.scala | 256 +++++++++++---------- src/reflect/scala/reflect/api/Universe.scala | 131 +++-------- src/reflect/scala/reflect/api/package.scala | 19 +- src/reflect/scala/reflect/runtime/package.scala | 12 +- 20 files changed, 646 insertions(+), 352 deletions(-) (limited to 'src/library') diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 5c2067a548..d699e34ffc 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -5,19 +5,34 @@ import java.lang.{ Class => jClass } import scala.language.{implicitConversions, existentials} import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass } -/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances. +/** + * + * A `ClassTag[T]` stores the erased class of a given type `T`, accessible via the `runtimeClass` + * field. This is particularly useful for instantiating `Array`s whose element types are unknown + * at compile time. + * + * `ClassTag`s are a weaker special case of [[scala.reflect.api.TypeTags#TypeTag]]s, in that they + * wrap only the runtime class of a given type, whereas a `TypeTag` contains all static type + * information. That is, `ClassTag`s are constructed from knowing only the top-level class of a + * type, without necessarily knowing all of its argument types. This runtime information is enough + * for runtime `Array` creation. * - * 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. + * For example: + * {{{ + * scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*) + * mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T] * - * Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi- - * dimensional `Arrays` where the element type is unknown at compile time. + * scala> mkArray(42, 13) + * res0: Array[Int] = Array(42, 13) * - * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]]. + * scala> mkArray("Japan","Brazil","Germany") + * res1: Array[String] = Array(Japan, Brazil, Germany) + * }}} + * + * See [[scala.reflect.api.TypeTags]] for more examples, or the + * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]] + * for more details. * - * @see [[scala.reflect.api.TypeTags]] */ @scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}") trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable { @@ -29,7 +44,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial */ def runtimeClass: jClass[_] - /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */ + /** Produces a `ClassTag` that knows how to instantiate an `Array[Array[T]]` */ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass)) /** Produces a new array with element type `T` and length `len` */ diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala index 1e658228f3..fb353a5520 100644 --- a/src/reflect/scala/reflect/api/Annotations.scala +++ b/src/reflect/scala/reflect/api/Annotations.scala @@ -6,11 +6,16 @@ import scala.collection.immutable.ListMap /** This trait provides annotation support for the reflection API. * * The API distinguishes between two kinds of annotations: - * 1. ''Java annotations'': annotations on definitions produced by the Java compiler, i.e., subtypes of `java.lang.annotation.Annotation` attached to program definitions. When read by Scala reflection, the [[scala.annotation.ClassfileAnnotation]] trait is automatically added as a subclass to every Java annotation. - * 1. ''Scala annotations'': annotations on definitions or types produced by the Scala compiler. * - * When a Scala annotation that inherits from [[scala.annotation.StaticAnnotation]] or [[scala.annotation.ClassfileAnnotation]] is compiled, - * it is stored as special attributes in the corresponding classfile, and not as a Java annotation. Note that subclassing + *
    + *
  • ''Java annotations'': annotations on definitions produced by the Java compiler, i.e., subtypes of [[java.lang.annotation.Annotation]] + * attached to program definitions. When read by Scala reflection, the [[scala.annotation.ClassfileAnnotation]] trait + * is automatically added as a subclass to every Java annotation.
  • + *
  • ''Scala annotations'': annotations on definitions or types produced by the Scala compiler.
  • + *
+ * + * When a Scala annotation that inherits from [[scala.annotation.StaticAnnotation]] or [[scala.annotation.ClassfileAnnotation]] is compiled, + * it is stored as special attributes in the corresponding classfile, and not as a Java annotation. Note that subclassing * just [[scala.annotation.Annotation]] is not enough to have the corresponding metadata persisted for runtime reflection. * * The distinction between Java and Scala annotations is manifested in the contract of [[scala.reflect.api.Annotations#Annotation]], which exposes diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala index 9e0573f0dc..a92fc5cbb3 100644 --- a/src/reflect/scala/reflect/api/Constants.scala +++ b/src/reflect/scala/reflect/api/Constants.scala @@ -7,9 +7,79 @@ package scala.reflect package api /** - * This trait is the [[scala.reflect.api.Universe reflection API]] component that mirrors constant irreducible expressions - * such as `true`, `0` and `classOf[List]`. Constant values appear in the program abstract syntax tree and in annotation parameters - * wrapped in [[Constant `Constant`]] case classes. + * According to the section 6.24 "Constant Expressions" of the Scala language specification, + * certain expressions (dubbed ''constant expressions'') can be evaluated by the Scala compiler at compile-time. + * + * [[scala.reflect.api.Constants#Constant]] instances represent certain kinds of these expressions + * (with values stored in the `value` field and its strongly-typed views named `booleanValue`, `intValue` etc.), namely: + * 1. Literals of primitive value classes (bytes, shorts, ints, longs, floats, doubles, chars, booleans and voids). + * 1. String literals. + * 1. References to classes (typically constructed with [[scala.Predef#classOf]]). + * 1. References to enumeration values. + * + * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node) + * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class). + * + * === Example === + * + * The `value` field deserves some explanation. Primitive and string values are represented as themselves, whereas + * references to classes and enums are a bit roundabout. + * + * Class references are represented as instances of [[scala.reflect.api.Types#Type]] + * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have been compiled). + * To convert such a reference to a runtime class, one should use the `runtimeClass` method of a mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror]] + * (the simplest way to get such a mirror is using [[scala.reflect.runtime.package#currentMirror]]). + * + * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods + * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum, + * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]). + + * {{{ + * enum JavaSimpleEnumeration { FOO, BAR } + * + * import java.lang.annotation.*; + * @Retention(RetentionPolicy.RUNTIME) + * @Target({ElementType.TYPE}) + * public @interface JavaSimpleAnnotation { + * Class classRef(); + * JavaSimpleEnumeration enumRef(); + * } + * + * @JavaSimpleAnnotation( + * classRef = JavaAnnottee.class, + * enumRef = JavaSimpleEnumeration.BAR + * ) + * public class JavaAnnottee {} + * }}} + * {{{ + * import scala.reflect.runtime.universe._ + * import scala.reflect.runtime.{currentMirror => cm} + * + * object Test extends App { + * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs + * def jarg(name: String) = jann(newTermName(name)).asInstanceOf[LiteralArgument].value + * + * val classRef = jarg("classRef").typeValue + * println(showRaw(classRef)) // TypeRef(ThisType(), JavaAnnottee, List()) + * println(cm.runtimeClass(classRef)) // class JavaAnnottee + * + * val enumRef = jarg("enumRef").symbolValue + * println(enumRef) // value BAR + * + * val siblings = enumRef.owner.typeSignature.declarations + * val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic) + * println(enumValues) // Scope{ + * // final val FOO: JavaSimpleEnumeration; + * // final val BAR: JavaSimpleEnumeration + * // } + * + * // doesn't work because of https://issues.scala-lang.org/browse/SI-6459 + * // val enumValue = mirror.reflectField(enumRef.asTerm).get + * val enumClass = cm.runtimeClass(enumRef.owner.asClass) + * val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null) + * println(enumValue) // BAR + * } + * }}} * * @contentDiagram hideNodes "*Api" */ diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 788fc889a8..45bfddb55d 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -8,8 +8,7 @@ package api import scala.reflect.runtime.{universe => ru} -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines strongly-typed tree wrappers and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. +/** A trait that defines strongly-typed tree wrappers and operations on them for use in Scala Reflection. * * `Expr` wraps an abstract syntax tree ([[scala.reflect.api.Trees#Tree]]) and tags it with its type ([[scala.reflect.api.Types#Type]]). * diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 701442b632..a7d1ca05a6 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -3,32 +3,51 @@ package api import scala.language.implicitConversions -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines flag sets and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. +/** + * The trait that defines flag sets and operations on them. * - * Flags are used to provide modifiers for abstract syntax trees that represent definitions - * via the `flags` field of [[scala.reflect.api.Trees#Modifiers]]. Trees that accept modifiers are: - * [[scala.reflect.api.Trees#ClassDef]] (classes and traits), [[scala.reflect.api.Trees#ModuleDef]] (objects), - * [[scala.reflect.api.Trees#ValDef]] (vals, vars, parameters and self-type annotations), - * [[scala.reflect.api.Trees#DefDef]] (methods and constructors) and - * [[scala.reflect.api.Trees#TypeDef]] (type aliases, abstract type members and type parameters). + * `Flag`s are used to provide modifiers for abstract syntax trees that represent definitions + * via the `flags` field of [[scala.reflect.api.Trees#Modifiers]]. Trees that accept modifiers are: * - * For example, to create a class named `C` one would write `ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...)`. - * Here the flag set is empty, representing a vanilla class definition. To make `C` private, one would write - * `ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...)`. Flags can also be combined with the vertical bar operator (`|`). - * For example, a private final class is written as followed: `ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...)`. + * - '''[[scala.reflect.api.Trees#ClassDef]]'''. Classes and traits. + * - '''[[scala.reflect.api.Trees#ModuleDef]]'''. Objects. + * - '''[[scala.reflect.api.Trees#ValDef]]'''. Vals, vars, parameters and self-type annotations. + * - '''[[scala.reflect.api.Trees#DefDef]]'''. Methods and constructors. + * - '''[[scala.reflect.api.Trees#TypeDef]]'''. Type aliases, abstract type members and type parameters. * - * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via the [[scala.reflect.api.FlagSets#Flag]] - * (typically one writes a blanket import for that, e.g. `import scala.reflect.runtime.universe.Flag._`). + * For example, to create a class named `C` one would write something like: + * {{{ + * ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...) + * }}} + * + * Here, the flag set is empty. * - * Definition trees are compiled down to symbols, so flags on modifiers of such trees are transformed into flags on the resulting symbols. - * Unlike trees, symbols don't expose flags, but rather provide `isXXX` test methods (e.g. `isFinal` can be used to test finality). These test methods - * might require an upcast with `asTerm`, `asType` or `asClass` as some flags only make sense for certain flavors of symbols. + * To make `C` private, one would write something like: + * {{{ + * ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...) + * }}} * - * === Known issues === + * Flags can also be combined with the vertical bar operator (`|`). + * For example, a private final class is written something like: + * {{{ + * ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...) + * }}} + * + * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via + * [[scala.reflect.api.FlagSets#Flag]]. (Typically one writes a blanket import for this, e.g. + * `import scala.reflect.runtime.universe.Flag._`). + * + * Definition trees are compiled down to symbols, so flags on modifiers of these trees are transformed into flags + * on the resulting symbols. Unlike trees, symbols don't expose flags, but rather provide `isXXX` test methods + * (e.g. `isFinal` can be used to test finality). These test methods might require an upcast with `asTerm`, + * `asType` or `asClass` as some flags only make sense for certain kinds of symbols. + * + * ''Of Note:'' This part of the Reflection API is being considered as a candidate for redesign. It is + * quite possible that in future releases of the reflection API, flag sets could be replaced with something else. + * + * For more details about `FlagSet`s and other aspects of Scala reflection, see the + * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] * - * This API is considered to be a candidate for redesign. It is quite probable that in future releases of the reflection API - * flag sets will be replaced with something else. */ trait FlagSets { self: Universe => diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index fde8794348..4286b2b45c 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -3,33 +3,23 @@ package api /** This trait provides support for importers, a facility to migrate reflection artifacts between universes. * - * Reflection artifacts, such as symbols and types, are contained in universes. Typically all processing happens - * within a single universe (e.g. a compile-time macro universe or a runtime reflection universe), but sometimes - * there is a need to migrate artifacts from one universe to another. For example, runtime compilation works by - * importing runtime reflection trees into a runtime compiler universe, compiling the importees and exporting the + * Reflection artifacts, such as [[scala.reflect.api.Symbols Symbols]] and [[scala.reflect.api.Types Types]], + * are contained in [[scala.reflect.api.Universes Universe]]s. Typically all processing happens + * within a single `Universe` (e.g. a compile-time macro `Universe` or a runtime reflection `Universe`), but sometimes + * there is a need to migrate artifacts from one `Universe` to another. For example, runtime compilation works by + * importing runtime reflection trees into a runtime compiler universe, compiling the importees and exporting the * result back. * - * Reflection artifacts are firmly grounded in their universes, which is reflected by the fact that types of artifacts - * from different universes are not compatible. By using importers, however, they be imported from one universe - * into another. For example, to import `foo.bar.Baz` from the source universe to the target universe, - * an importer will first check whether the entire owner chain exists in the target universe. + * Reflection artifacts are firmly grounded in their `Universe`s, which is reflected by the fact that types of artifacts + * from different universes are not compatible. By using `Importer`s, however, they be imported from one universe + * into another. For example, to import `foo.bar.Baz` from the source `Universe` to the target `Universe`, + * an importer will first check whether the entire owner chain exists in the target `Universe`. * If it does, then nothing else will be done. Otherwise, the importer will recreate the entire owner chain - * and will import the corresponding type signaturers into the target universe. + * and will import the corresponding type signatures into the target `Universe`. * - * Since importers match symbol tables of the source and the target universes using plain string names, + * Since importers match `Symbol` tables of the source and the target `Universe`s using plain string names, * it is programmer's responsibility to make sure that imports don't distort semantics, e.g., that - * `foo.bar.Baz` in the source universe means the same that `foo.bar.Baz` does in the target universe. - * - * === Known issues === - * - * Importers didn't undergo as much testing as most of the reflection API did, - * so they might be flaky from time to time. Please report issues if you encounter them. - * - * Importers are currently not mirror-aware, they always use `rootMirror` - * of the target universe to resolve symbols. This might cause troubles in cases when the target universe - * need a non-standard way of symbol resolution (e.g. a classloader that's different from the default one). - * We have created [[https://issues.scala-lang.org/browse/SI-6241 https://issues.scala-lang.org/browse/SI-6241]], - * an issue in the issue tracker, to track the implementation of this feature. + * `foo.bar.Baz` in the source `Universe` means the same that `foo.bar.Baz` does in the target `Universe`. * * === Example === * diff --git a/src/reflect/scala/reflect/api/JavaMirrors.scala b/src/reflect/scala/reflect/api/JavaMirrors.scala index 9bc888b884..df099006b5 100644 --- a/src/reflect/scala/reflect/api/JavaMirrors.scala +++ b/src/reflect/scala/reflect/api/JavaMirrors.scala @@ -5,7 +5,12 @@ package api * * This refinement equips mirrors with reflection capabilities for the JVM. `JavaMirror` can * convert Scala reflection artifacts (symbols and types) into Java reflection artifacts (classes) - * and vice versa. It can also perform reflective invocations (getting/settings field values, calling methods, etc). + * and vice versa. It can also perform reflective invocations (getting/setting field values, + * calling methods, etc). + * + * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the + * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]] + * * @groupname JavaMirrors Java Mirrors */ trait JavaMirrors { self: JavaUniverse => @@ -15,7 +20,7 @@ trait JavaMirrors { self: JavaUniverse => */ type RuntimeClass = java.lang.Class[_] - /** In runtime reflection universes, mirrors are JavaMirrors. + /** In runtime reflection universes, mirrors are `JavaMirrors`. * @group JavaMirrors */ override type Mirror >: Null <: JavaMirror @@ -23,10 +28,12 @@ trait JavaMirrors { self: JavaUniverse => /** A refinement of [[scala.reflect.api.Mirror]] for runtime reflection using JVM classloaders. * * With this upgrade, mirrors become capable of converting Scala reflection artifacts (symbols and types) - * into Java reflection artifacts (classes) and vice versa. Consequently refined mirrors - * become capable of performing reflective invocations (getting/settings field values, calling methods, etc). + * into Java reflection artifacts (classes) and vice versa. Consequently, refined mirrors + * become capable of performing reflective invocations (getting/setting field values, calling methods, etc). + * + * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the + * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]] * - * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection. * @group JavaMirrors */ trait JavaMirror extends scala.reflect.api.Mirror[self.type] with RuntimeMirror { @@ -35,7 +42,10 @@ trait JavaMirrors { self: JavaUniverse => } /** Creates a runtime reflection mirror from a JVM classloader. - * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection. + * + * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the + * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]] + * * @group JavaMirrors */ def runtimeMirror(cl: ClassLoader): Mirror diff --git a/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala index 60ba087933..b1290cc02e 100644 --- a/src/reflect/scala/reflect/api/Mirror.scala +++ b/src/reflect/scala/reflect/api/Mirror.scala @@ -4,16 +4,15 @@ package api /** * The base class for all mirrors. * - * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for a description of mirrors - * and infomation on getting started with Scala reflection API. - * - * Note: Unlike most Scala reflection artifact classes, `Mirror` is not defined as an inner class, - * so that it can be referenced from outside. For example, [[scala.reflect.api.TypeCreator]] and [[scala.reflect.api.TreeCreator]] - * reference `Mirror` 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 [[scala.reflect.api.Mirrors]] or [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] + * for a complete overview of `Mirror`s. * * @tparam U the type of the universe this mirror belongs to. */ +// Note: Unlike most Scala reflection artifact classes, `Mirror` is not defined as an inner class, +// so that it can be referenced from outside. For example, [[scala.reflect.api.TypeCreator]] and [[scala.reflect.api.TreeCreator]] +// reference `Mirror` 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. abstract class Mirror[U <: Universe with Singleton] { /** The universe this mirror belongs to. * @group Mirror diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 32cfdf07fb..cc1b9762cb 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -1,10 +1,205 @@ package scala.reflect package api -/** This trait provides support for Mirrors in the reflection API. +/** This trait provides support for Mirrors in the Scala Reflection API. * - * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for a description of mirrors - * and infomation on getting started with Scala reflection API. + * `Mirror`s are a central part of Scala Reflection. All information provided by + * reflection is made accessible through `Mirror`s. Depending on the type of information + * to be obtained, or the reflective action to be taken, different flavors of mirrors + * must be used. "Classloader" mirrors can be used to obtain representations of types + * and members. From a classloader `Mirror`, it's possible to obtain more specialized + * "invoker" `Mirror`s (the most commonly-used mirrors), which implement reflective + * invocations, such as method/constructor calls and field accesses. + * + * The two flavors of mirrors: + * + *
    + *
  • ```“Classloader” mirrors```. These mirrors translate names to symbols + * (via methods `staticClass`/`staticModule`/`staticPackage`).
  • + *
  • ```"Invoker” mirrors```. These mirrors implement reflective invocations + * (via methods `MethodMirror.apply`, `FieldMirror.get`, etc). These "invoker" + * mirrors are the types of mirrors that are most commonly used.
  • + *
+ * + * === Compile-time Mirrors === + * Compile-time `Mirror`s make use of only classloader `Mirror`s to load `Symbol`s + * by name. + * + * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.Context#mirror]]. + * Typical methods which use classloader `Mirror`s include [[scala.reflect.api.Mirror#staticClass]], + * [[scala.reflect.api.Mirror#staticModule]], and [[scala.reflect.api.Mirror#staticPackage]]. For + * example: + * {{{ + * import scala.reflect.macros.Context + * + * case class Location(filename: String, line: Int, column: Int) + * + * object Macros { + * def currentLocation: Location = macro impl + * + * def impl(c: Context): c.Expr[Location] = { + * import c.universe._ + * val pos = c.macroApplication.pos + * val clsLocation = c.mirror.staticModule("Location") // get symbol of "Location" object + * c.Expr(Apply(Ident(clsLocation), List(Literal(Constant(pos.source.path)), Literal(Constant(pos.line)), Literal(Constant(pos.column))))) + * } + * } + * }}} + * + * ''Of Note:'' There are several high-level alternatives that one can use to avoid having to manually + * lookup symbols. For example, `typeOf[Location.type].termSymbol` (or `typeOf[Location].typeSymbol` + * if we needed a `ClassSymbol`), which are type safe since we don’t have to use `String`s to lookup + * the `Symbol`. + * + * === Runtime Mirrors === + * + * Runtime `Mirror`s make use of both classloader and invoker `Mirror`s. + * + * The entry point to `Mirror`s for use at runtime is via `ru.runtimeMirror()`, where + * `ru` is [[scala.reflect.runtime.universe]]. + * + * The result of a [[scala.reflect.api.JavaMirrors#runtimeMirror]] call is a classloader mirror, + * of type [[scala.reflect.api.Mirrors#ReflectiveMirror]], which can load symbols by names as + * discussed above (in the “Compile-time” section). + * + * A classloader mirror can create invoker mirrors, which include: [[scala.reflect.api.Mirrors#InstanceMirror]], + * [[scala.reflect.api.Mirrors#MethodMirror]], [[scala.reflect.api.Mirrors#FieldMirror]], + * [[scala.reflect.api.Mirrors#ClassMirror]] and [[scala.reflect.api.Mirrors#ModuleMirror]]. + * + * Examples of how these two types of `Mirror`s interact are available below. + * + * === Types of Mirrors, Their Use Cases & Examples === + * + * '''[[scala.reflect.api.Mirrors#ReflectiveMirror]]'''. Used for loading `Symbol`s by name, and + * as an entry point into invoker mirrors. Entry point: `val m = ru.runtimeMirror()`. + * Example: + * {{{ + * scala> val ru = scala.reflect.runtime.universe + * ru: scala.reflect.api.JavaUniverse = ... + * + * scala> val m = ru.runtimeMirror(getClass.getClassLoader) + * m: reflect.runtime.universe.Mirror = JavaMirror ... + * }}} + * + * '''[[scala.reflect.api.Mirrors#InstanceMirror]]'''. Used for creating invoker `Mirror`s for methods + * and fields and for inner classes and inner objects (modules). Entry point: `val im = m.reflect()`. + * Example: + * {{{ + * scala> class C { def x = 2 } + * defined class C + * + * scala> val im = m.reflect(new C) + * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@3442299e + * }}} + * + * '''[[scala.reflect.api.Mirrors#MethodMirror]]'''. Used for invoking instance methods (Scala only has + * instance methods-- methods of objects are instance methods of object instances, obtainable + * via `ModuleMirror.instance`). Entry point: `val mm = im.reflectMethod()`. + * Example: + * {{{ + * scala> val methodX = typeOf[C].declaration(newTermName("x")).asMethod + * methodX: reflect.runtime.universe.MethodSymbol = method x + * + * scala> val mm = im.reflectMethod(methodX) + * mm: reflect.runtime.universe.MethodMirror = method mirror for C.x: scala.Int (bound to C@3442299e) + * + * scala> mm() + * res0: Any = 2 + * }}} + * + * '''[[scala.reflect.api.Mirrors#FieldMirror]]'''. Used for getting/setting instance fields + * (Scala only has instance fields-- fields of objects are instance methods of object instances + * obtainable via ModuleMirror.instance). Entry point: + * `val fm = im.reflectMethod()`. + * Example: + * {{{ + * scala> class C { val x = 2; val y = 3 } + * defined class C + * + * scala> val m = ru.runtimeMirror(getClass.getClassLoader) + * m: reflect.runtime.universe.Mirror = JavaMirror ... + * + * scala> val im = m.reflect(new C) + * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@5f0c8ac1 + * + * scala> val fieldX = typeOf[C].declaration(newTermName("x")).asTerm.accessed.asTerm + * fieldX: reflect.runtime.universe.TermSymbol = value x + * scala> val fmX = im.reflectField(fieldX) + * fmX: reflect.runtime.universe.FieldMirror = field mirror for C.x (bound to C@5f0c8ac1) + * + * scala> fmX.get + * res0: Any = 2 + * + * scala> fmX.set(3) + * scala.ScalaReflectionException: cannot set an immutable field x + * ... + * + * scala> val fieldY = typeOf[C].declaration(newTermName("y")).asTerm.accessed.asTerm + * fieldY: reflect.runtime.universe.TermSymbol = variable y + * + * scala> val fmY = im.reflectField(fieldY) + * fmY: reflect.runtime.universe.FieldMirror = field mirror for C.y (bound to C@5f0c8ac1) + * + * scala> fmY.get + * res1: Any = 3 + * + * scala> fmY.set(4) + * + * scala> fmY.get + * res2: Any = 4 + * }}} + * + * '''[[scala.reflect.api.Mirrors#ClassMirror]]'''. Used for creating invoker mirrors for constructors. + * Entry points: for ''static classes'' `val cm1 = m.reflectClass()`, + * for ''inner classes'' `val mm2 = im.reflectClass()`. + * Example: + * {{{ + * scala> case class C(x: Int) + * defined class C + * + * scala> val m = ru.runtimeMirror(getClass.getClassLoader) + * m: reflect.runtime.universe.Mirror = JavaMirror ... + * + * scala> val classC = typeOf[C].typeSymbol.asClass + * + * classC: reflect.runtime.universe.Symbol = class C + * + * scala> val cm = m.reflectClass(classC) + * cm: reflect.runtime.universe.ClassMirror = class mirror for C (bound to null) + * + * scala> val ctorC = typeOf[C].declaration(ru.nme.CONSTRUCTOR).asMethod + * ctorC: reflect.runtime.universe.MethodSymbol = constructor C + * + * scala> val ctorm = cm.reflectConstructor(ctorC) + * ctorm: reflect.runtime.universe.MethodMirror = constructor mirror for C.(x: scala.Int): C (bound to null) + * + * scala> ctorm(2) + * res0: Any = C(2) + * }}} + * + * '''[[scala.reflect.api.Mirrors#ModuleMirror]]'''. Used for getting singleton instances of objects. + * Entry points: for ''static objects (modules)'' `val mm1 = m.reflectModule()`, + * for ''inner objects (modules)'' `val mm2 = im.reflectModule()`. + * Example: + * {{{ + * scala> object C { def x = 2 } + * defined module C + * + * scala> val m = ru.runtimeMirror(getClass.getClassLoader) + * m: reflect.runtime.universe.Mirror = JavaMirror ... + * + * scala> val objectC = typeOf[C.type].termSymbol.asModule + * objectC: reflect.runtime.universe.ModuleSymbol = object C + * + * scala> val mm = m.reflectModule(objectC) + * mm: reflect.runtime.universe.ModuleMirror = module mirror for C (bound to null) + * + * scala> val obj = mm.instance + * obj: Any = C$@1005ec04 + * }}} + * + * For more information about `Mirrors`s, see the + * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]] * * @contentDiagram hideNodes "*Api" */ diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index 332c24e542..02eb79f8ed 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -5,7 +5,7 @@ package api * * Names are simple wrappers for strings. [[scala.reflect.api.Names#Name Name]] has two subtypes [[scala.reflect.api.Names#TermName TermName]] and [[scala.reflect.api.Names#TypeName TypeName]] which * distinguish names of terms (like objects or members) and types. A term and a type of the - * same name can co-exist in an object. + * same name can co-exist in an object. * * === Examples === * @@ -13,7 +13,7 @@ package api * use `typeOf[List[_]].member(newTermName("map"))`. To search for a type member, use * newTypeName instead. * - * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]. + * See the [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for more about Scala Reflection. * * @contentDiagram hideNodes "*Api" */ diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala index fb199bbd69..61d643b449 100644 --- a/src/reflect/scala/reflect/api/Position.scala +++ b/src/reflect/scala/reflect/api/Position.scala @@ -16,6 +16,30 @@ import scala.reflect.macros.Attachments * The compiler adds more information to positions, such a ranges in the source file and defines different types of * positions depending on how a symbol or tree node was generated. The guide fully describes compiler-generated positions. * + * - INV1: A tree with an offset position never contains a child + * with a range position + * - INV2: If the child of a tree with a range position also has a range position, + * then the child's range is contained in the parent's range. + * - INV3: Opaque range positions of children of the same node are non-overlapping + * (this means their overlap is at most a single point). + * + * The following tests are useful on positions: + * `pos.isDefined` true if position is not a NoPosition, + * `pos.isRange` true if position is a range, + * `pos.isOpaqueRange` true if position is an opaque range, + * + * There are also convenience methods, such as + * `pos.startOrPoint`, + * `pos.endOrPoint`, + * `pos.pointOrElse(default)`. + * These are less strict about the kind of position on which they can be applied. + * + * The following conversion methods are often used: + * `pos.focus` converts a range position to an offset position, keeping its point; + * returns all other positions unchanged, + * `pos.makeTransparent` converts an opaque range position into a transparent one. + * returns all other positions unchanged. + * * @groupname Common Commonly used methods */ trait Position extends Attachments { diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index b7157af153..1e8161aeef 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -3,9 +3,12 @@ package api import java.io.{ PrintWriter, StringWriter } -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines prettyprinting functionality. +/** Utilities for nicely printing [[scala.reflect.api.Trees]] and [[scala.reflect.api.Types]]. * - * === Examples (trees) === + * === Printing Trees === + * The method `show` displays the "prettified" representation of reflection artifacts. + * This representation provides one with the desugared Java representation of Scala code. + * For example: * * {{{ * scala> import scala.reflect.runtime.universe._ @@ -14,9 +17,6 @@ import java.io.{ PrintWriter, StringWriter } * scala> def tree = reify{ final class C { def x = 2 } }.tree * tree: reflect.runtime.universe.Tree * - * // show displays prettified representation of reflection artifacts - * // which is typically close to Scala code, but sometimes not quite - * // (e.g. here the constructor is shown in a desugared way) * scala> show(tree) * res0: String = * { @@ -29,21 +29,17 @@ import java.io.{ PrintWriter, StringWriter } * }; * () * } + * }}} + * + * The method `showRaw` displays internal structure of a given reflection object + * as a Scala abstract syntax tree (AST), the representation that the Scala typechecker + * operates on. * - * // showRaw displays internal structure of a given reflection object - * // trees and types (type examples are shown below) are case classes - * // so they are shown in a form that's almost copy/pasteable - * // - * // almost copy/pasteable, but not completely - that's because of symbols - * // there's no good way to get a roundtrip-surviving representation of symbols - * // in general case, therefore only symbol names are shown (e.g. take a look at AnyRef) - * // - * // in such a representation, it's impossible to distinguish Idents/Selects - * // that have underlying symbols vs ones that don't have symbols, because in both cases - * // only names will be printed - * // - * // to overcome this limitation, use `printIds` and `printKinds` - optional parameters - * // of the `showRaw` method (an example is shown below) + * Note, that while this representation appears to generate correct trees that one + * might think would be possible to use in a macro implementation, this is not usually + * the case. Symbols aren't fully represented (only their names are). Thus, this method + * is best-suited for use simply inspecting ASTs given some valid Scala code. + * {{{ * scala> showRaw(tree) * res1: String = Block(List( * ClassDef(Modifiers(FINAL), newTypeName("C"), List(), Template( @@ -57,15 +53,17 @@ import java.io.{ PrintWriter, StringWriter } * DefDef(Modifiers(), newTermName("x"), List(), List(), TypeTree(), * Literal(Constant(2))))))), * Literal(Constant(()))) - * + * }}} + * + * The method `showRaw` can also print [[scala.reflect.api.Types]] next to the artifacts + * being inspected + * {{{ * scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar * import scala.tools.reflect.ToolBox * * scala> import scala.reflect.runtime.{currentMirror => cm} * import scala.reflect.runtime.{currentMirror=>cm} * - * // showRaw can also print types next to the artifacts being inspected - * // provide true for a `printTypes` arguments to achieve this effect * scala> showRaw(cm.mkToolBox().typeCheck(tree), printTypes = true) * res2: String = Block[1](List( * ClassDef[2](Modifiers(FINAL), newTypeName("C"), List(), Template[3]( @@ -89,8 +87,9 @@ import java.io.{ PrintWriter, StringWriter } * [8] ConstantType(Constant(2)) * }}} * - * === Examples (types) === + * === Printing Types === * + * The method `show` * {{{ * scala> import scala.reflect.runtime.universe._ * import scala.reflect.runtime.universe._ @@ -98,10 +97,14 @@ import java.io.{ PrintWriter, StringWriter } * scala> def tpe = typeOf[{ def x: Int; val y: List[Int] }] * tpe: reflect.runtime.universe.Type * - * // show has already been discussed above * scala> show(tpe) * res0: String = scala.AnyRef{def x: Int; val y: scala.List[Int]} + * }}} * + * Like the method `showRaw` for [[scala.reflect.api.Trees]], `showRaw` + * for [[scala.reflect.api.Types]] provides a visualization of the Scala + * AST operated on by the Scala typechecker. + * {{{ * // showRaw has already been discussed above * scala> showRaw(tpe) * res1: String = RefinedType( @@ -109,18 +112,10 @@ import java.io.{ PrintWriter, StringWriter } * Scope( * newTermName("x"), * newTermName("y"))) + * }}} * - * // when `printIds` and/or `printKinds` arguments are provided for showRaw - * // the prettyprinter reveals underlying symbols and their flavors - * // - * // courtesy of `printKinds` we can see four different symbols: a package class `scala`, - * // a type alias `AnyRef`, a method named `x` and a getter named `y`. - * // - * // thanks to `printIds` we can see unique identifiers of symbols - * // so that it becomes possible to distinguish, say, `scala.collection.immutable.List` - * // from `scala.collection.mutable.List` (this also helps in rare cases - * // when the same reflection entity is represented by multiple symbols, but let's - * // not speak of these horrors here) + * `printIds` and/or `printKinds` can additionally be supplied as arguments in a call to + * `showRaw` which additionally shows the unique identifiers of symbols. * scala> showRaw(tpe, printIds = true, printKinds = true) * res2: String = RefinedType( * List(TypeRef(ThisType(scala#2043#PK), newTypeName("AnyRef")#691#TPE, List())), @@ -128,6 +123,10 @@ import java.io.{ PrintWriter, StringWriter } * newTermName("x")#2540#METH, * newTermName("y")#2541#GET)) * }}} + * + * For more details about `Printer`s and other aspects of Scala reflection, see the + * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] + * */ trait Printers { self: Universe => @@ -176,8 +175,9 @@ trait Printers { self: Universe => */ override protected def treeToString(tree: Tree) = show(tree) - /** Renders a prettified representation of a reflection artifact. - * Typically it looks very close to the Scala code it represents. + /** Renders a representation of a reflection artifact + * as desugared Java code. + * * @group Printers */ def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = @@ -188,7 +188,9 @@ trait Printers { self: Universe => */ protected def newTreePrinter(out: PrintWriter): TreePrinter - /** Renders internal structure of a reflection artifact. + /** Renders internal structure of a reflection artifact as the + * visualization of a Scala syntax tree. + * * @group Printers */ def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala index e1eadde3ad..a31a501357 100644 --- a/src/reflect/scala/reflect/api/StandardDefinitions.scala +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -5,10 +5,11 @@ package scala.reflect package api -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines standard symbols and types. +/** All Scala standard symbols and types. * - * These standard reflection artifacts can be referred to using `definitions` (typically imported with - * a blanket import `import definitions._`) and are listed in [[scala.reflect.api.StandardDefinitions#DefinitionsApi]]. + * These standard definitions can accessed to using `definitions`. + * They're typically imported with a blanket import `import definitions`, and are + * listed in [[scala.reflect.api.StandardDefinitions#DefinitionsApi]]. */ trait StandardDefinitions { self: Universe => diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index 203bcdbdc4..fc18c02706 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -10,8 +10,7 @@ package api // Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then sure. // Otherwise you'd better not - reflection API should stay minimalistic. -/** This trait is the [[scala.reflect.api.Universe reflection API]] component that defines standard [[Names names used in reflection and macros]]. - * +/** * Standard names are names that are essential to creating trees or to reflecting Scala artifacts. * For example, `CONSTRUCTOR` (aka `` on JVM) is necessary to create and invoke constructors. * diff --git a/src/reflect/scala/reflect/api/TreeCreator.scala b/src/reflect/scala/reflect/api/TreeCreator.scala index c668fe0b4d..cba90b72e6 100644 --- a/src/reflect/scala/reflect/api/TreeCreator.scala +++ b/src/reflect/scala/reflect/api/TreeCreator.scala @@ -3,7 +3,7 @@ package api /** This is an internal implementation class. * - * @see [[http://docs.scala-lang.org/overviews/reflection/architecture.html]]. + * This class is used internally by Scala Reflection, and is not recommended for use in client code. */ abstract class TreeCreator { def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Tree diff --git a/src/reflect/scala/reflect/api/TypeCreator.scala b/src/reflect/scala/reflect/api/TypeCreator.scala index 16585cd23f..9c386f2939 100644 --- a/src/reflect/scala/reflect/api/TypeCreator.scala +++ b/src/reflect/scala/reflect/api/TypeCreator.scala @@ -1,9 +1,9 @@ package scala.reflect package api -/** This is an internal implementation class. - * - * @see [[http://docs.scala-lang.org/overviews/reflection/architecture.html]]. +/** A mirror-aware factory for types. + * + * This class is used internally by Scala Reflection, and is not recommended for use in client code. */ abstract class TypeCreator { def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Type diff --git a/src/reflect/scala/reflect/api/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala index 9d66a9e236..812d5199fc 100644 --- a/src/reflect/scala/reflect/api/TypeTags.scala +++ b/src/reflect/scala/reflect/api/TypeTags.scala @@ -17,130 +17,143 @@ import scala.language.implicitConversions * [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. */ -/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines type tags and operations on them. - * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern. - * - * 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 and examples === - * - * Type tags are organized in a hierarchy of three classes: - * [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]]. - * - * 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]]] - * :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 - * }}} - * - * - * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]] are path dependent on their universe. - * - * The default universe is [[scala.reflect.runtime.universe]] - * - * Type tags can be migrated to another universe given the corresponding mirror using - * - * {{{ - * tag.in( other_mirror ) - * }}} - * - * See [[scala.reflect.api.TypeTags#WeakTypeTag.in]] - * - * === WeakTypeTag vs TypeTag === - * - * Be careful with WeakTypeTag, because it will reify types even if these types are abstract. - * 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: +/** + * A `TypeTag[T]` encapsulates the runtime type representation of some type `T`. + * Like [[scala.reflect.Manifest]], the prime use case of `TypeTag`s is to give access + * to erased types. However, `TypeTag`s should be considered to be a richer + * replacement of the pre-2.10 notion of a [[scala.reflect.Manifest Manifest]], that + * are, in addition, fully integrated with Scala reflection. * + * There exist three different types of `TypeTags`: + * + *
    + *
  • [[scala.reflect.api.TypeTags#TypeTag]].
    A full type descriptor of a Scala type. + * For example, a `TypeTag[List[String]]` contains all type information, + * in this case, of type `scala.List[String]`.
  • + * + *
  • [[scala.reflect.ClassTag]].
    A partial type descriptor of a Scala type. For + * example, a `ClassTag[List[String]]` contains only the erased class + * type information, in this case, of type `scala.collection.immutable.List`. + * `ClassTag`s provide access only to the runtime class of a type. + * Analogous to [[scala.reflect.ClassManifest]]
  • + * + *
  • [[scala.reflect.api.TypeTags#WeakTypeTag]].
    A type descriptor for abstract + * types (see description below).
  • + *
+ * + * Like [[scala.reflect.Manifest Manifest]]s, `TypeTag`s are always generated by the + * compiler, and can be obtained in three ways: + * + * === #1 Via the methods [[scala.reflect.api.TypeTags#typeTag typeTag]], + * [[scala.reflect#classTag classTag]], or [[scala.reflect.api.TypeTags#weakTypeTag weakTypeTag]] === + * + * For example: * {{{ - * 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) + * import scala.reflect.runtime.universe._ + * val tt = typeTag[Int] + * + * import scala.reflect._ + * val ct = classTag[String] + * }}} + * + * Each of these methods constructs a `TypeTag[T]` or `ClassTag[T]` for the given + * type argument `T`. + * + * === #2 Using an implicit parameter of type `TypeTag[T]`, `ClassTag[T]`, or `WeakTypeTag[T] + * + * For example: + * {{{ + * import scala.reflect.runtime.universe._ + * + * def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = { + * val targs = tag.tpe match { case TypeRef(_, _, args) => args } + * println(s"type of $x has type arguments $targs") * } + * + * scala> paramInfo(42) + * type of 42 has type arguments List() + * + * scala> paramInfo(List(1, 2)) + * type of List(1, 2) has type arguments List(Int) * }}} * - * 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.api.Universe#WeakTypeTag]] here is reasonable, because it is desirable - * to work with all types, even if they are type parameters or abstract type members. + * === #3 Context bound of a type parameter === * - * However if any of the three `WeakTypeTag` context bounds is omitted, the resulting code will be incorrect, - * because the missing `WeakTypeTag` will be transparently generated by the compiler, carrying meaningless information. - * Most likely, this problem will manifest itself elsewhere, making debugging complicated. - * 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. + * ...on methods or classes. The above example can be implemented as follows: * - * === Backward compatibility with Manifests === + * {{{ + * import scala.reflect.runtime.universe._ + * + * def paramInfo[T: TypeTag](x: T): Unit = { + * val targs = typeOf[T] match { case TypeRef(_, _, args) => args } + * println(s"type of $x has type arguments $targs") + * } + * + * scala> paramInfo(42) + * type of 42 has type arguments List() * - * Type tags correspond loosely to manifests. + * scala> paramInfo(List(1, 2)) + * type of List(1, 2) has type arguments List(Int) + * }}} + * + * === `WeakTypeTag`s === + * + *`WeakTypeTag[T]` generalizes `TypeTag[T]`. Unlike a regular `TypeTag`, components of + * its type representation can be references to type parameters or abstract types. + * However, `WeakTypeTag[T]` tries 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[T]`. * - * More precisely: - * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag, - * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.runtime.universe.TypeTag, + * Continuing the example above: + * {{{ + * def weakParamInfo[T](x: T)(implicit tag: WeakTypeTag[T]): Unit = { + * val targs = tag.tpe match { case TypeRef(_, _, args) => args } + * println(s"type of $x has type arguments $targs") + * } * - * In Scala 2.10 class manifests are deprecated, and manifests are planned to be deprecated in one of the - * subsequent point releases. Therefore it's advisable to migrate manifests to tags. + * scala> def foo[T] = weakParamInfo(List[T]()) + * foo: [T]=> Unit * - * In most cases it is enough to replace `ClassManifest` with `ClassTag` and `Manifest` with `TypeTag`. - * There are however a few caveats: + * scala> foo[Int] + * type of List() has type arguments List(T) + * }}} * - * 1) Tags don't support the notion of `OptManifest`. Tags can reify arbitrary types, so they are always available. + * === TypeTags and Manifests === * - * 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 `.tpe.typeSymbol.isPrimitiveValueClass`. + * `TypeTag`s correspond loosely to the pre-2.10 notion of + * [[scala.reflect.Manifest]]s. While [[scala.reflect.ClassTag]] corresponds to + * [[scala.reflect.ClassManifest]] and [[scala.reflect.api.TypeTags#TypeTag]] mostly + * corresponds to [[scala.reflect.Manifest]], other pre-2.10 `Manifest` types do not + * have a direct correspondence with a 2.10 "`Tag`" type. * - * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects. - * Consider assembling corresponding types using the reflection APIs provided by Java (for classes) and Scala (for types). + *
    + *
  • '''[[scala.reflect.OptManifest]] is not supported.'''
    This is because `Tag`s + * can reify arbitrary types, so they are always available.
  • * - * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API. - * Consider using the reflection APIs provided by Java (for classes) and Scala (for types) instead. + *
  • '''There is no equivalent for [[scala.reflect.AnyValManifest]].'''
    Instead, one + * can compare their `Tag` with one of the base `Tag`s (defined in the corresponding + * companion objects) in order to find out whether or not it represents a primitive + * value class. Additionally, it's possible to simply use + * `.tpe.typeSymbol.isPrimitiveValueClass`.
  • * - * === Known issues === + *
  • '''There are no replacement for factory methods defined in the `Manifest` + * companion objects'''.
    Instead, one could generate corresponding types using the + * reflection APIs provided by Java (for classes) and Scala (for types).
  • * - * Type tags are marked as serializable, but this functionality is not yet implemented. - * An issue tracker entry: [[https://issues.scala-lang.org/browse/SI-5919 https://issues.scala-lang.org/browse/SI-5919]] - * has been created to track the implementation of this feature. + *
  • '''Certain manifest operations(i.e., <:<, >:> and typeArguments) are not + * supported.'''
    Instead, one culd use the reflection APIs provided by Java (for + * classes) and Scala (for types).
  • + *
* - * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]], [[scala.reflect.api.Universe#WeakTypeTag]] + * In Scala 2.10, [[scala.reflect.ClassManifest]]s are deprecated, and it is planned + * to deprecate [[scala.reflect.Manifest]] in favor of `TypeTag`s and `ClassTag`s in + * an upcoming point release. Thus, it is advisable to migrate any `Manifest`-based + * APIs to use `Tag`s. + * + * For more information about `TypeTag`s, see the + * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]] + * + * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.TypeTags#TypeTag]], [[scala.reflect.api.TypeTags#WeakTypeTag]] * @group TypeTags Type Tags */ trait TypeTags { self: Universe => @@ -148,14 +161,17 @@ trait TypeTags { self: Universe => import definitions._ /** - * 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.api.Universe#TypeTag]] instead, which statically guarantees this property. + * If an implicit value of type `WeakTypeTag[T]` is required, the compiler will create one, + * and the reflective representation of `T` can be accessed via the `tpe` field. + * Components of `T` can be references to type parameters or abstract types. Note that `WeakTypeTag` + * makes an effort to be as concrete as possible, i.e. if `TypeTag`s 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 perhaps be partially + * abstract, but requires special care to handle this case. However, if `T` is expected to be fully known, use + * [[scala.reflect.api.TypeTags#TypeTag]] instead, which statically guarantees this property. + * + * For more information about `TypeTag`s, see the + * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]] * * @see [[scala.reflect.api.TypeTags]] * @group TypeTags @@ -163,7 +179,7 @@ trait TypeTags { self: Universe => @annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}") trait WeakTypeTag[T] extends Equals with Serializable { /** - * Underlying mirror of this type tag. + * The underlying `Mirror` of this type tag. */ val mirror: Mirror @@ -180,16 +196,16 @@ trait TypeTags { self: Universe => */ def tpe: Type - /** TODO how do I doc this? */ + // TODO how do I doc this? override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]] - /** TODO how do I doc this? */ + // TODO how do I doc this? override def equals(x: Any) = x.isInstanceOf[WeakTypeTag[_]] && this.mirror == x.asInstanceOf[WeakTypeTag[_]].mirror && this.tpe == x.asInstanceOf[WeakTypeTag[_]].tpe - /** TODO how do I doc this? */ + // TODO how do I doc this? override def hashCode = mirror.hashCode * 31 + tpe.hashCode - /** TODO how do I doc this? */ + // TODO how do I doc this? override def toString = "WeakTypeTag[" + tpe + "]" } @@ -249,7 +265,7 @@ trait TypeTags { self: Universe => } /** - * A `TypeTag` is a [[scala.reflect.api.Universe#WeakTypeTag]] with the additional + * A `TypeTag` is a [[scala.reflect.api.TypeTags#WeakTypeTag]] with the additional * static guarantee that all type references are concrete, i.e. it does not contain any references to * unresolved type parameters or abstract types. * diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index d9be73fde9..7d1f5c9df1 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -2,13 +2,18 @@ package scala.reflect package api /** - * The Scala reflection cake. + * `Universe` provides a complete set of reflection operations which make it possible for one + * to reflectively inspect Scala type relations, such as membership or subtyping. * - * See [[scala.reflect.api.package the overview page]] for a description of universes and infomation on getting started with Scala reflection API. - * This page lists the most important layers of the cake, and describes paculiarities of cake APIs. + * [[scala.reflect.api.Universe]] has two specialized sub-universes for different scenarios. + * [[scala.reflect.api.JavaUniverse]] adds operations that link symbols and types to the underlying + * classes and runtime values of a JVM instance-- this can be thought of as the `Universe` that + * should be used for all typical use-cases of Scala reflection. [[scala.reflect.macros.Universe]] + * adds operations which allow macros to access selected compiler data structures and operations-- + * this type of `Universe` should only ever exist within the implementation of a Scala macro. * - * The reflection library is structured according to the 'cake pattern'. The main layer - * resides in package [[scala.reflect.api]] and defines an interface to the following main types: + * `Universe` can be thought of as the entry point to Scala reflection. It mixes-in, and thus provides + * an interface to the following main types: * * - [[scala.reflect.api.Types#Type Types]] represent types * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions @@ -19,58 +24,32 @@ package api * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and * definition trees * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants. + * + * To obtain a `Universe` to use with Scala runtime reflection, simply make sure to use or import + * `scala.reflect.runtime.universe._` + * {{{ + * scala> import scala.reflect.runtime.universe._ + * import scala.reflect.runtime.universe._ + * + * scala> typeOf[List[Int]] + * res0: reflect.runtime.universe.Type = scala.List[Int] + * + * scala> typeOf[Either[String, Int]] + * res1: reflect.runtime.universe.Type = scala.Either[String,Int] + * }}} * - * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class - * [[scala.reflect.api.Universe Universe]]. The main 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.macros]] 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.api.Trees#Tree]]. - * This type is not a class but is abstract and has an upper bound of [[scala.reflect.api.Trees#TreeApi]], - * which is a class defining the minimal base interface for all trees. - * - * For a more interesting tree type, consider [[scala.reflect.api.Trees#If]] representing if-expressions. - * It is defined next to a value `If` of type [[scala.reflect.api.Trees#IfExtractor]]. - * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply` - * for pattern matching. - * + * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.Context#universe]]. For example: * {{{ - * 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) + * def printf(format: String, params: Any*): Unit = macro impl + * def impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = { + * import c.universe._ + * ... + * } * }}} * - * is equivalent to - * - * {{{ - * import scala.reflect.runtime.universe._ - * val iftree = reify{ if( condition ) 1 else 2 }.tree - * }}} + * For more information about `Universe`s, see the [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]] * - * and can be pattern matched as - * - * {{{ - * iftree match { case If(cond,body,other) => ... } - * }}} - * - * Moreover, there is an implicit value [[scala.reflect.api.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 `XApi` 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`. - * @groupprio Universe -1 + * @groupprio Universe -1 * * @contentDiagram hideNodes "*Api" */ @@ -93,9 +72,9 @@ abstract class Universe extends Symbols with Printers with Importers { - /** Produce the abstract syntax tree representing the given Scala expression. + /** Use `refiy` to produce the abstract syntax tree representing a given Scala expression. * - * For example + * For example: * * {{{ * val five = reify{ 5 } // Literal(Constant(5)) @@ -105,49 +84,7 @@ abstract class Universe extends Symbols * * The produced tree is path dependent on the Universe `reify` was called from. * - * Use [[scala.reflect.api.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 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)))) - * }}} - * - * 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", , 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): - * - * {{{ - * val two = mirror.reify(2) // Literal(Constant(2)) - * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("\$plus")), List(two.tree)) - * - * def macroImpl[T](c: Context) = { - * ... - * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion - * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl) - * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation - * val factory = c.reify{ new Queryable[T] } - * ... - * } - * }}} - * - * The transformation looks mostly straightforward, but it has its tricky parts: - * - Reifier retains symbols and types defined outside the reified tree, however - * locally defined entities get erased and replaced with their original trees - * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol` - * - Mutable variables that are accessed from a local function are wrapped in refs + * Use [[scala.reflect.api.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. * @group Universe */ // implementation is hardwired to `scala.reflect.reify.Taggers` diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala index 449b7d5ce1..bd9c72a839 100644 --- a/src/reflect/scala/reflect/api/package.scala +++ b/src/reflect/scala/reflect/api/package.scala @@ -2,13 +2,22 @@ package scala.reflect import scala.reflect.api.{Universe => ApiUniverse} -/** The Scala reflection API (located at scala-reflect.jar). +/** The Scala Reflection API (located in scala-reflect.jar). * - * Using Scala reflection requires understanding of a couple of basic concepts like [[Symbols Symbols]], [[Types Types]], [[Mirror Mirrors]] and [[Universe Universes]]. - * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]. + * In Scala 2.10.0, the Scala Reflection API and its implementation have an "experimental" status. + * This means that the API and the docs are not complete and can be changed in binary- and source-incompatible + * manner in 2.10.1. This also means that the implementation has some known issues. * - * In Scala 2.10.0, reflection API and its implementation have experimental status. This means that the API and the docs are not complete and can be changed - * in binary- and source-incompatible manner in 2.10.1. This also means that the implementation has known issues + * The following types are the backbone of the Scala Reflection API, and serve as a good starting point + * for information about Scala Reflection: + * + * - [[scala.reflect.api.Symbols]] + * - [[scala.reflect.api.Types]] + * - [[scala.reflect.api.Mirrors]] + * - [[scala.reflect.api.Universe]] + * + * For more information about Scala Reflection, see the + * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] * * @groupprio API 9 * @groupprio Extractors 10 diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index b3f9ba5817..b97913daf0 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -5,14 +5,18 @@ package scala.reflect */ package object runtime { - /** The entry point into runtime reflection. - * See [[scala.reflect.api.package the overview page]] for details on how to use it. + /** The entry point into Scala runtime reflection. + * + * To use Scala runtime reflection, simply use or import `scala.reflect.runtime.universe._` + * + * See [[scala.reflect.api.Universe]] or the + * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]] + * for more details. */ lazy val universe: api.JavaUniverse = new runtime.JavaUniverse /** The runtime reflection mirror that corresponds to the current lexical context. - * Is typically equivalent to `universe.runtimeMirror(getClass.getClassLoader)` invoked at the call site. - * See [[scala.reflect.api.package the overview page]] for details on how to use it. + * It's typically equivalent to `universe.runtimeMirror(getClass.getClassLoader)` invoked at the call site. */ // implementation hardwired to the `currentMirror` method below // using the mechanism implemented in `scala.tools.reflect.FastTrack` -- cgit v1.2.3