diff --git a/library/src/scala/Console.scala b/library/src/scala/Console.scala index f229c78beb9a..60c48b803158 100644 --- a/library/src/scala/Console.scala +++ b/library/src/scala/Console.scala @@ -130,8 +130,35 @@ object Console extends AnsiColor { private val inVar = new DynamicVariable[BufferedReader]( new BufferedReader(new InputStreamReader(java.lang.System.in))) + /** Sets the default output stream for the current thread by changing the + * current binding directly, discarding the previously bound stream. Unlike + * `withOut`, this method does not itself restore the previous stream; note, + * however, that if it is called inside a `withOut` body, that enclosing + * scope will restore its own saved stream when it exits. + * + * @param out the new output stream to install as the default for the + * current thread + */ protected def setOutDirect(out: PrintStream): Unit = outVar.value = out + /** Sets the default error stream for the current thread by changing the + * current binding directly, discarding the previously bound stream. Unlike + * `withErr`, this method does not itself restore the previous stream; note, + * however, that if it is called inside a `withErr` body, that enclosing + * scope will restore its own saved stream when it exits. + * + * @param err the new error stream to install as the default for the + * current thread + */ protected def setErrDirect(err: PrintStream): Unit = errVar.value = err + /** Sets the default input reader for the current thread by changing the + * current binding directly, discarding the previously bound reader. Unlike + * `withIn`, this method does not itself restore the previous reader; note, + * however, that if it is called inside a `withIn` body, that enclosing + * scope will restore its own saved reader when it exits. + * + * @param in the new input reader to install as the default for the + * current thread + */ protected def setInDirect(in: BufferedReader): Unit = inVar.value = in /** The default output, can be overridden by `withOut`. diff --git a/library/src/scala/Conversion.scala b/library/src/scala/Conversion.scala index 84aecd201bbc..bf99ce9f8bfb 100644 --- a/library/src/scala/Conversion.scala +++ b/library/src/scala/Conversion.scala @@ -51,5 +51,6 @@ object Conversion: /** Unwraps an `into`. */ extension [T](x: into[T]) + /** Returns `x` viewed at its underlying type `T`, revealing the opaque `into[T]` alias. */ def underlying: T = x end Conversion diff --git a/library/src/scala/DelayedInit.scala b/library/src/scala/DelayedInit.scala index f661c816cb14..f16e30a7c2b7 100644 --- a/library/src/scala/DelayedInit.scala +++ b/library/src/scala/DelayedInit.scala @@ -50,5 +50,13 @@ import scala.language.`2.13` */ @deprecated("DelayedInit semantics can be surprising. Support for `App` will continue. See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0", "2.11.0") trait DelayedInit { + /** Receives the rewritten initialization code of an inheriting class or object. + * + * Implementations decide whether, when, and how often to evaluate `x`, and may + * run other code before or after it. + * + * @param x the initialization code, passed by name so it is not evaluated until + * the implementation forces it + */ def delayedInit(x: => Unit): Unit } diff --git a/library/src/scala/Enumeration.scala b/library/src/scala/Enumeration.scala index 8be912690a7b..0af19b718c68 100644 --- a/library/src/scala/Enumeration.scala +++ b/library/src/scala/Enumeration.scala @@ -84,16 +84,22 @@ import scala.util.matching.Regex * ``` * * @param initial The initial value from which to count the integers that - * identifies values at run-time. + * identify values at run-time. */ @SerialVersionUID(8476000850333817230L) abstract class Enumeration (initial: Int) extends Serializable { thisenum => + /** Creates an enumeration whose values are identified by integers counting from zero. */ def this() = this(0) /* Note that `readResolve` cannot be private, since otherwise the JVM does not invoke it when deserializing subclasses. */ + /** Returns the instance held in this enumeration class's Scala module field, so that + * deserializing an enumeration defined as an `object` yields that singleton rather + * than a copy. The runtime class is assumed to be a module class; deserializing a + * subclass that is not an `object` fails, since no such field exists. + */ protected def readResolve(): AnyRef = thisenum.getClass.getField(MODULE_INSTANCE_NAME).get(null) /** The name of this enumeration. */ @@ -137,8 +143,8 @@ abstract class Enumeration (initial: Int) extends Serializable { private def nextNameOrNull: String | Null = if (nextName != null && nextName.hasNext) nextName.next() else null - /** The highest integer amongst those used to identify values in this - * enumeration. + /** The one higher than the highest integer amongst those used to identify + * values in this enumeration, or `initial` if it has no values yet. */ private var topId = initial @@ -238,14 +244,25 @@ abstract class Enumeration (initial: Int) extends Serializable { /** A marker so we can tell whose values belong to whom come reflective-naming time. */ private[Enumeration] val outerEnum = thisenum + /** Compares this value with `that` by their ids. + * + * @param that the value to compare with + * @return `-1` if this value's id is less than `that`'s, `0` if the ids are equal, `1` otherwise + */ override def compare(that: Value): Int = if (this.id < that.id) -1 else if (this.id == that.id) 0 else 1 + /** Tests whether `other` is a value of the same enumeration instance with the same id. + * + * @param other the object to compare with + * @return `true` if `other` is a `Value` belonging to this same enumeration and has an equal id, `false` otherwise + */ override def equals(other: Any): Boolean = other match { case that: Enumeration#Value => (outerEnum eq that.outerEnum) && (id == that.id) case _ => false } + /** Returns a hash code derived from this value's id. */ override def hashCode(): Int = id.## /** Creates a ValueSet which contains this value and another one. @@ -261,8 +278,25 @@ abstract class Enumeration (initial: Int) extends Serializable { */ @SerialVersionUID(0 - 3501153230598116017L) protected class Val(i: Int, name: String | Null) extends Value with Serializable { + /** Creates a value identified by the integer `i`, taking its name from the + * enumeration's `nextName` iterator if that iterator has a next element. + * + * @param i an integer that identifies this value at run-time; it must be unique amongst all values of the enumeration + */ def this(i: Int) = this(i, nextNameOrNull) + /** Creates a value called `name`, identified by the enumeration's current `nextId`. + * That id must still be unused: constructing values with explicit ids can leave + * `nextId` pointing at an id already taken, in which case this constructor fails + * the duplicate-id assertion. + * + * @param name a human-readable name for this value, or `null` to have the name determined reflectively + */ def this(name: String | Null) = this(nextId, name) + /** Creates a value identified by the enumeration's current `nextId`, taking its + * name from the enumeration's `nextName` iterator if that iterator has a next + * element. As with the other constructors, the id must still be unused, or the + * duplicate-id assertion fails. + */ def this() = this(nextId) assert(!vmap.isDefinedAt(i), "Duplicate id: " + i) @@ -271,12 +305,21 @@ abstract class Enumeration (initial: Int) extends Serializable { nextId = i + 1 if (nextId > topId) topId = nextId if (i < bottomId) bottomId = i + /** Returns the integer that identifies this value at run-time. */ def id: Int = i + /** Returns the name of this value. If no explicit name was given, the name is + * determined reflectively from the fields of the enclosing enumeration, or a + * placeholder string is returned if no such field exists. + */ override def toString(): String = if (name != null) name else try thisenum.nameOf(i) catch { case _: NoSuchElementException => "" } + /** Returns the value of the deserialized enumeration singleton whose id matches + * this value's id, so that deserialized values are identical to the enumeration's + * own values, or this value itself if that enumeration has no value mapping yet. + */ protected def readResolve(): AnyRef = { val enumeration = thisenum.readResolve().asInstanceOf[Enumeration] if (enumeration.vmap == null) this @@ -286,12 +329,27 @@ abstract class Enumeration (initial: Int) extends Serializable { /** An ordering by id for values of this set. */ implicit object ValueOrdering extends Ordering[Value] { + /** Compares two values of this enumeration by their ids. + * + * @param x the first value to compare + * @param y the second value to compare + * @return `-1` if `x`'s id is less than `y`'s, `0` if the ids are equal, `1` otherwise + */ def compare(x: Value, y: Value): Int = x compare y } /** A class for sets of values. * Iterating through this set will yield values in increasing order of their ids. * + * Ids are stored adjusted by the lowest id in use by the enclosing enumeration at + * the time each operation runs, so the behavior described for the methods below + * holds only as long as that lowest id does not change. Creating a value whose id + * is lower than every id created so far shifts the adjustment and thereby + * reinterprets the ids already stored in existing sets, so that a set built before + * the shift can afterwards report membership of, and iterate over, different values + * than it was built from. As stated for the enumeration itself, values should not be + * added after its construction. + * * @param nnIds The set of ids of values (adjusted so that the lowest value does * not fall below zero), organized as a `BitSet`. * @define Coll `collection.immutable.SortedSet` @@ -304,37 +362,110 @@ abstract class Enumeration (initial: Int) extends Serializable { with StrictOptimizedIterableOps[Value, immutable.Set, ValueSet] with Serializable { + /** Returns the ordering of this set, which orders values by increasing id. */ implicit def ordering: Ordering[Value] = ValueOrdering + /** Creates a set restricted to the values of this set that lie in the given range. + * + * @param from the lowest value to retain, or `None` to start at the lowest value of this set + * @param until the lowest value to drop, or `None` to retain values up to the highest value of this set + * @return a new `ValueSet` holding the values of this set within the given range + */ def rangeImpl(from: Option[Value], until: Option[Value]): ValueSet = new ValueSet(nnIds.rangeImpl(from.map(_.id - bottomId), until.map(_.id - bottomId))) + /** Returns the empty value set of this enumeration. */ override def empty: ValueSet = ValueSet.empty + /** Returns the number of values in this set, which is always known. */ override def knownSize: Int = nnIds.size + /** Tests whether this set contains no values. */ override def isEmpty: Boolean = nnIds.isEmpty + /** Tests whether this set contains the given value. + * + * @param v the value to test + * @return `true` if `v` is an element of this set, `false` otherwise + */ def contains(v: Value): Boolean = nnIds contains (v.id - bottomId) + /** Creates a set containing all values of this set and the given value. + * + * @param value the value to include + * @return a new `ValueSet`, holding the same values as this set if `value` is + * already an element of it + */ def incl (value: Value): ValueSet = new ValueSet(nnIds + (value.id - bottomId)) + /** Creates a set containing all values of this set except the given value. + * + * @param value the value to exclude + * @return a new `ValueSet`, holding the same values as this set if `value` is + * not an element of it + */ def excl (value: Value): ValueSet = new ValueSet(nnIds - (value.id - bottomId)) + /** Returns an iterator over the values of this set in increasing order of their ids. */ def iterator: Iterator[Value] = nnIds.iterator map (id => thisenum.apply(bottomId + id)) override def iteratorFrom(start: Value): Iterator[Value] = nnIds iteratorFrom start.id map (id => thisenum.apply(bottomId + id)) + /** Returns the name used for this set in its string representation, of the form `Enum.ValueSet`. */ override def className: String = s"$thisenum.ValueSet" /** Creates a bit mask for the zero-adjusted ids in this set as a * new array of longs */ def toBitMask: Array[Long] = nnIds.toBitMask + /** Creates a value set holding the values of the given collection. + * + * @param coll the values to include + * @return a new `ValueSet` containing the values of `coll` + */ override protected def fromSpecific(coll: IterableOnce[Value]): ValueSet = ValueSet.fromSpecific(coll) + /** Returns a builder for value sets of this enumeration. */ override protected def newSpecificBuilder = ValueSet.newBuilder + /** Creates a value set by applying `f` to every value of this set. + * + * @param f the function to apply to each value + * @return a new `ValueSet` holding the results of applying `f`, with duplicates collapsed + */ def map(f: Value => Value): ValueSet = fromSpecific(new View.Map(this, f)) + /** Creates a value set by applying `f` to every value of this set and concatenating the results. + * + * @param f the function to apply to each value + * @return a new `ValueSet` holding all values produced by `f`, with duplicates collapsed + */ def flatMap(f: Value => IterableOnce[Value]): ValueSet = fromSpecific(new View.FlatMap(this, f)) // necessary for disambiguation: + /** Creates a sorted set by applying `f` to every value of this set. + * + * @tparam B the element type of the resulting set + * @param f the function to apply to each value + * @param ev the ordering by which the resulting set is sorted + * @return a new sorted set holding the results of applying `f`, with duplicates collapsed + */ override def map[B](f: Value => B)(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] = super[SortedSet].map[B](f) + /** Creates a sorted set by applying `f` to every value of this set and concatenating the results. + * + * @tparam B the element type of the resulting set + * @param f the function to apply to each value + * @param ev the ordering by which the resulting set is sorted + * @return a new sorted set holding all elements produced by `f`, with duplicates collapsed + */ override def flatMap[B](f: Value => IterableOnce[B])(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] = super[SortedSet].flatMap[B](f) + /** Creates a sorted set of pairs formed from the values of this set and the elements of `that`. + * + * @tparam B the element type of `that` + * @param that the collection to zip with this set + * @param ev the ordering by which the resulting set of pairs is sorted + * @return a new sorted set of pairs, holding as many pairs as the shorter of this set and `that` + */ override def zip[B](that: IterableOnce[B])(implicit @implicitNotFound(ValueSet.zipOrdMsg) ev: Ordering[(Value, B)]): immutable.SortedSet[(Value, B)] = super[SortedSet].zip[B](that) + /** Creates a sorted set by applying `pf` to every value of this set for which it is defined. + * + * @tparam B the element type of the resulting set + * @param pf the partial function to apply to each value + * @param ev the ordering by which the resulting set is sorted + * @return a new sorted set holding the results of applying `pf`, with duplicates collapsed + */ override def collect[B](pf: PartialFunction[Value, B])(implicit @implicitNotFound(ValueSet.ordMsg) ev: Ordering[B]): immutable.SortedSet[B] = super[SortedSet].collect[B](pf) @@ -362,6 +493,11 @@ abstract class Enumeration (initial: Int) extends Serializable { def clear() = b.clear() def result() = new ValueSet(b.toImmutable) } + /** Creates a value set holding the values of the given collection. + * + * @param it the values to include + * @return a new `ValueSet` containing the values of `it` + */ def fromSpecific(it: IterableOnce[Value]): ValueSet = newBuilder.addAll(it).result() } diff --git a/library/src/scala/MatchError.scala b/library/src/scala/MatchError.scala index fa5e483ab951..cd6b28e653bd 100644 --- a/library/src/scala/MatchError.scala +++ b/library/src/scala/MatchError.scala @@ -40,5 +40,12 @@ final class MatchError(@transient obj: Any) extends RuntimeException { this } + /** Returns a detail message describing the object that failed to match any pattern. + * The message is the object's `toString` representation followed by its class name + * in parentheses, as in `5 (of class java.lang.Integer)`. If the object is `null`, + * the message is just `"null"`; if invoking `toString` on it throws, the message + * omits the representation and is `"an instance of class "` followed by the class + * name. + */ override def getMessage(): String = objString } diff --git a/library/src/scala/NamedTuple.scala b/library/src/scala/NamedTuple.scala index 385c1a062e13..f4fd961f69f6 100644 --- a/library/src/scala/NamedTuple.scala +++ b/library/src/scala/NamedTuple.scala @@ -25,8 +25,27 @@ object NamedTuple: => (@unused eqV: CanEqual[V1, V2]) => CanEqual[NamedTuple[N1, V1], NamedTuple[N2, V2]] = CanEqual.derived + /** Creates a named tuple with the names `N` and the element values of the tuple `x`. + * + * @tparam N the tuple of name types labelling the elements; for named tuples written + * in source code these are literal string types, but the signature only + * requires a tuple + * @tparam V the tuple of element value types + * @param x the tuple holding the element values + * @return the named tuple that pairs the names `N` with the element values of `x` + */ def apply[N <: Tuple, V <: Tuple](x: V): NamedTuple[N, V] = x + /** Decomposes a named tuple into its element values, so that a pattern match on a + * named tuple binds the values without their names. The match always succeeds. + * + * @tparam N the tuple of name types labelling the elements; for named tuples written + * in source code these are literal string types, but the signature only + * requires a tuple + * @tparam V the tuple of element value types + * @param x the named tuple to decompose + * @return `Some` wrapping the underlying tuple of element values of `x` + */ def unapply[N <: Tuple, V <: Tuple](x: NamedTuple[N, V]): Some[V] = Some(x) /** A named tuple expression will desugar to a call to `build`. For instance, @@ -251,6 +270,19 @@ object NamedTupleDecomposition: @publicInBinary private[NamedTupleDecomposition] + /** Creates a map from field names to element values, preserving the order of the fields. + * + * If the two tuples have different sizes, the extra elements of the larger tuple will + * be disregarded. + * + * @tparam N the tuple of field name types; this is not checked, but callers must pass + * only string names, because the result is cast to a map with `String` keys + * @tparam V the tuple of element value types + * @param names the field names, in field order + * @param values the element values, in the same order as `names` + * @return a [[scala.collection.immutable.SeqMap]] that maps each name to the value at + * the same position + */ def createSeqMap[N <: Tuple, V <: Tuple](names: N, values: V): SeqMap[String, Tuple.Union[V]] = SeqMap.newBuilder .addAll(names.productIterator.zip(values.productIterator)) diff --git a/library/src/scala/NotImplementedError.scala b/library/src/scala/NotImplementedError.scala index 8adaa96ed319..6d199fad4ba7 100644 --- a/library/src/scala/NotImplementedError.scala +++ b/library/src/scala/NotImplementedError.scala @@ -21,5 +21,6 @@ import scala.language.`2.13` * @param msg the error message describing which implementation is missing */ final class NotImplementedError(msg: String) extends Error(msg) { + /** Creates a `NotImplementedError` with the default message `"an implementation is missing"`. */ def this() = this("an implementation is missing") } diff --git a/library/src/scala/PartialFunction.scala b/library/src/scala/PartialFunction.scala index 01e04b1da79a..6399273e638e 100644 --- a/library/src/scala/PartialFunction.scala +++ b/library/src/scala/PartialFunction.scala @@ -276,7 +276,19 @@ trait PartialFunction[-A, +B] extends Function1[A, B] { self: PartialFunction[A, */ object PartialFunction { + /** An extractor produced by [[PartialFunction.elementWise]] which matches a sequence + * by applying the underlying partial function to each of its elements. + * + * @tparam A the argument type of the underlying partial function + * @tparam B the result type of the underlying partial function + */ final class ElementWiseExtractor[-A, +B] private[PartialFunction] (private val pf: PartialFunction[A, B]^) extends AnyVal { this: ElementWiseExtractor[A, B]^ => + /** Returns the results of applying the underlying partial function to every element of `seq`. + * + * @param seq the sequence whose elements are matched against the partial function + * @return `Some` containing the sequence of results if the partial function is defined + * at every element of `seq`, `None` otherwise + */ def unapplySeq(seq: Seq[A]): Option[Seq[B]] = { boundary: Some(seq.map: @@ -295,18 +307,63 @@ object PartialFunction { */ private class OrElse[-A, +B] (f1: PartialFunction[A, B]^, f2: PartialFunction[A, B]^) extends scala.runtime.AbstractPartialFunction[A, B] with Serializable { + /** Checks if a value is contained in the domain of either composed partial function. + * + * @param x the value to test + */ def isDefinedAt(x: A) = f1.isDefinedAt(x) || f2.isDefinedAt(x) + /** Applies the primary partial function where it is defined, and the fallback partial + * function elsewhere. + * + * @param x the function argument + * @return the result of applying `f1` to `x`, or the result of applying `f2` to `x` + * where `f1` is not defined + */ override def apply(x: A): B = f1.applyOrElse(x, f2) + /** Applies the primary partial function where it is defined, the fallback partial function + * where only it is defined, and `default` where neither is defined. + * + * @tparam A1 the argument type of the fallback function (a subtype of `A`) + * @tparam B1 the result type of the fallback function (a supertype of `B`) + * @param x the function argument + * @param default the fallback function, applied where neither composed partial function + * is defined + * @return the result of applying to `x` the first of `f1`, `f2` and `default` that is + * defined at `x` + */ override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = { val z = f1.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(z)) z else f2.applyOrElse(x, default) } + /** Composes this composite function with a further fallback partial function, which gets + * applied where neither composed partial function is defined. + * + * @tparam A1 the argument type of the fallback function + * @tparam B1 the result type of the fallback function + * @param that the fallback function + * @return a composite partial function which tries `f1` first, then `f2`, then `that` + */ override def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]^): OrElse[A1, B1]^{this, that} = new OrElse[A1, B1] (f1, f2 orElse that) + /** Composes this composite function with a transformation function that gets applied to + * its results. + * + * The result is again an `orElse` composition, this time of `f1 andThen k` and + * `f2 andThen k`. If `k` is an ordinary function, the domain is unchanged and every + * argument `x` is mapped to `k(this(x))`. If the runtime type of `k` is a + * `PartialFunction`, each of the two transformed components is narrowed to the + * arguments whose result `k` accepts, so an argument at which `f1` is defined but + * `k(f1(x))` is not may still be mapped to `k(f2(x))`. + * + * @tparam C the result type of the transformation function + * @param k the transformation function + * @return a composite partial function which tries `f1 andThen k` first, then + * `f2 andThen k` + */ override def andThen[C](k: B => C): OrElse[A, C]^{this, k} = new OrElse[A, C] (f1 andThen k, f2 andThen k) } @@ -320,10 +377,29 @@ object PartialFunction { * @param k the transformation function applied to results of `pf` */ private class AndThen[-A, B, +C] (pf: PartialFunction[A, B]^, k: B => C) extends PartialFunction[A, C] with Serializable { + /** Checks if a value is contained in the domain of the underlying partial function, which + * is also the domain of this composite function. + * + * @param x the value to test + */ def isDefinedAt(x: A) = pf.isDefinedAt(x) + /** Applies the underlying partial function to the given argument and transforms the result. + * + * @param x the function argument + * @return the result of `k(pf(x))` + */ def apply(x: A): C = k(pf(x)) + /** Applies the underlying partial function to the given argument and transforms the result, + * applying `default` where the underlying partial function is not defined. + * + * @tparam A1 the argument type of the fallback function (a subtype of `A`) + * @tparam C1 the result type of the fallback function (a supertype of `C`) + * @param x the function argument + * @param default the fallback function + * @return `k(pf(x))` where `pf` is defined at `x`, `default(x)` otherwise + */ override def applyOrElse[A1 <: A, C1 >: C](x: A1, default: A1 => C1): C1 = { val z = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(z)) k(z) else default(x) @@ -339,13 +415,36 @@ object PartialFunction { * @param k the transformation partial function applied to results of `pf` */ private class Combined[-A, B, +C] (pf: PartialFunction[A, B]^, k: PartialFunction[B, C]^) extends PartialFunction[A, C] with Serializable { + /** Checks if a value is contained in the domain of this composite function, which requires + * both composed partial functions to be defined. Note that testing applies `pf` and so may + * execute its side effects. + * + * @param x the value to test + * @return `true` if `pf` is defined at `x` and `k` is defined at `pf(x)`, `false` otherwise + */ def isDefinedAt(x: A): Boolean = { val b: B = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(b)) k.isDefinedAt(b) else false } + /** Applies the first partial function to the given argument, then the second partial + * function to that result. + * + * @param x the function argument + * @return the result of `k(pf(x))` + */ def apply(x: A): C = k(pf(x)) + /** Applies both composed partial functions in turn to the given argument, applying `default` + * where either of them is not defined. + * + * @tparam A1 the argument type of the fallback function (a subtype of `A`) + * @tparam C1 the result type of the fallback function (a supertype of `C`) + * @param x the function argument + * @param default the fallback function + * @return `k(pf(x))` where `pf` is defined at `x` and `k` is defined at `pf(x)`, + * `default(x)` otherwise + */ override def applyOrElse[A1 <: A, C1 >: C](x: A1, default: A1 => C1): C1 = { val pfv = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(pfv)) k.applyOrElse(pfv, (_: B) => default(x)) else default(x) @@ -380,6 +479,12 @@ object PartialFunction { private class Lifted[-A, +B] (val pf: PartialFunction[A, B]^) extends scala.runtime.AbstractFunction1[A, Option[B]] with Serializable { + /** Applies the underlying partial function to the given argument, reporting whether it was + * defined there by wrapping the result in an `Option`. + * + * @param x the function argument + * @return `Some(pf(x))` if `pf` is defined at `x`, `None` otherwise + */ def apply(x: A): Option[B] = { val z = pf.applyOrElse(x, checkFallback[B]) if (!fallbackOccurred(z)) Some(z) else None @@ -387,12 +492,34 @@ object PartialFunction { } private class Unlifted[A, B] (f: A => Option[B]) extends scala.runtime.AbstractPartialFunction[A, B] with Serializable { + /** Checks if a value is contained in the function's domain by applying the underlying + * optional function to it. + * + * The underlying function is expected to return a non-null `Option`; if `f(x)` is `null`, + * this method throws a `NullPointerException` instead of returning `false`. + * + * @param x the value to test + * @return `true` if `f(x)` is a `Some`, `false` if it is `None` + */ def isDefinedAt(x: A): Boolean = f(x).isDefined + /** Applies the underlying optional function to the given argument, applying `default` where + * that function yields no result. + * + * The underlying function is expected to return a non-null `Option`; if `f(x)` is `null`, + * this method throws a `NullPointerException` instead of applying `default`. + * + * @tparam A1 the argument type of the fallback function (a subtype of `A`) + * @tparam B1 the result type of the fallback function (a supertype of `B`) + * @param x the function argument + * @param default the fallback function + * @return the value contained in `f(x)`, or `default(x)` if `f(x)` is `None` + */ override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = { f(x).getOrElse(default(x)) } + /** Returns the optional function `f` from which this partial function was created. */ override def lift = f } diff --git a/library/src/scala/Proxy.scala b/library/src/scala/Proxy.scala index b04937e1d550..58937b22b7fb 100644 --- a/library/src/scala/Proxy.scala +++ b/library/src/scala/Proxy.scala @@ -27,15 +27,24 @@ import scala.language.`2.13` */ @deprecated("Explicitly override hashCode, equals and toString instead.", "2.13.0") trait Proxy extends Any { + /** The object to which the `Any` methods of this proxy are forwarded. */ def self: Any + /** Returns the hash code of `self`. */ override def hashCode(): Int = self.hashCode + /** Tests whether `that` is equal to `self`. + * + * @param that the object to compare with `self` + * @return `true` if `that` is a reference to this proxy or to `self`, or if + * `that` equals `self`; `false` otherwise + */ override def equals(that: Any): Boolean = that match { case null => false case _ => val x = that.asInstanceOf[AnyRef] (x eq this.asInstanceOf[AnyRef]) || (x eq self.asInstanceOf[AnyRef]) || (x.equals(self)) } + /** Returns the string representation of `self`. */ override def toString() = "" + self } @@ -45,6 +54,9 @@ object Proxy { */ @deprecated("Explicitly override hashCode, equals and toString instead.", "2.13.0") trait Typed[T] extends Any with Proxy { + /** The object to which the `Any` methods of this proxy are forwarded, + * narrowed to the proxied type `T`. + */ def self: T } } diff --git a/library/src/scala/ScalaReflectionException.scala b/library/src/scala/ScalaReflectionException.scala index aa10c98b2eaa..83f3b03897f4 100644 --- a/library/src/scala/ScalaReflectionException.scala +++ b/library/src/scala/ScalaReflectionException.scala @@ -9,4 +9,8 @@ import scala.language.`2.13` case class ScalaReflectionException(msg: String) extends Exception(msg) object ScalaReflectionException extends scala.runtime.AbstractFunction1[String, ScalaReflectionException]: + /** Returns the name of this companion object, `"ScalaReflectionException"`, rather than + * the `` rendering inherited via [[scala.runtime.AbstractFunction1]] from + * [[scala.Function1]]. + */ override def toString(): String = "ScalaReflectionException" diff --git a/library/src/scala/Selectable.scala b/library/src/scala/Selectable.scala index e46e1163bd01..d3dc3ec34655 100644 --- a/library/src/scala/Selectable.scala +++ b/library/src/scala/Selectable.scala @@ -33,6 +33,17 @@ object Selectable: @deprecated( "import scala.reflect.Selectable.reflectiveSelectable instead of scala.language.reflectiveCalls", since = "3.0") + /** Converts a value into a [[scala.reflect.Selectable]] that performs + * structural selections on it. + * + * Only applies where `scala.language.reflectiveCalls` is imported, so that + * code written against Scala 2 keeps compiling. Prefer importing + * `scala.reflect.Selectable.reflectiveSelectable` instead. + * + * @param x the value on which structural members are selected + * @return a [[scala.reflect.Selectable]] wrapping `x`, whose `selectDynamic` + * and `applyDynamic` dispatch on the runtime type of `x` + */ implicit def reflectiveSelectableFromLangReflectiveCalls(x: Any)( using scala.languageFeature.reflectiveCalls): scala.reflect.Selectable = scala.reflect.Selectable.reflectiveSelectable(x) diff --git a/library/src/scala/Specializable.scala b/library/src/scala/Specializable.scala index 5728d8c4f03d..567a0a5cf225 100644 --- a/library/src/scala/Specializable.scala +++ b/library/src/scala/Specializable.scala @@ -21,9 +21,17 @@ trait Specializable object Specializable { // No type parameter in @specialized annotation. + /** A group of types accepted as the argument of the `@specialized` annotation. */ trait SpecializedGroup // Smuggle a list of types by way of a tuple upon which Group is parameterized. + /** A group whose contents are carried by the type parameter `T`. + * + * @tparam T the contents of the group. The predefined groups in this object, such as [[Primitives]] and + * [[Everything]], encode their member types as a tuple type whose element types are the types + * to specialize for, but `T` is not required to be a tuple type in general. + * @param value a value of type `T`; not retained, since only the type parameter carries the group's contents + */ class Group[T](value: T) extends SpecializedGroup final val Primitives: Group[(Byte, Short, Int, Long, Char, Float, Double, Boolean, Unit)] = null.asInstanceOf[Group[(Byte, Short, Int, Long, Char, Float, Double, Boolean, Unit)]] diff --git a/library/src/scala/StringContext.scala b/library/src/scala/StringContext.scala index 28258c2ff7eb..7f8ef8ccd145 100644 --- a/library/src/scala/StringContext.scala +++ b/library/src/scala/StringContext.scala @@ -61,6 +61,11 @@ case class StringContext(parts: String*) { import StringContext.{checkLengths => scCheckLengths, glob, processEscapes, standardInterpolator => scStandardInterpolator} @deprecated("use same-named method on StringContext companion object", "2.13.0") + /** Checks that the number of given arguments is one less than the number of `parts` + * of this `StringContext`, throwing an `IllegalArgumentException` if it is not. + * + * @param args the interpolated argument values + */ def checkLengths(args: scala.collection.Seq[Any]): Unit = scCheckLengths(args, parts) /** The simple string interpolator. @@ -162,6 +167,17 @@ case class StringContext(parts: String*) { def raw(args: Any*): String = macro ??? // fasttracked to scala.tools.reflect.FastStringInterpolator::interpolateRaw @deprecated("Use the static method StringContext.standardInterpolator instead of the instance method", "2.13.0") + /** Interpolates the given arguments between the `parts` of this `StringContext`, + * transforming each part with `process` first. + * + * The number of `parts` of this `StringContext` must exceed the number of arguments + * by exactly one; otherwise an `IllegalArgumentException` is thrown. + * + * @param process the transformation applied to each literal part, such as escape expansion + * @param args the values to be interpolated between the parts + * @return the processed parts concatenated with the string representations of the + * arguments interleaved between them + */ def standardInterpolator(process: String => String, args: Seq[Any]): String = scStandardInterpolator(process, args, parts) /** The formatted string interpolator. @@ -315,6 +331,16 @@ object StringContext { } index $index in "$str". Use \\\\ for literal \\.""" ) + /** An exception that is thrown if a string contains a backslash (`\`) character + * followed by one or more `u` characters that do not start a valid four hex-digit + * Unicode escape sequence. + * + * @param str the offending string + * @param escapeStart the index in `str` of the first `u` character of the offending escape sequence + * @param index the position in `str` at which the escape sequence was found to be invalid. + * This can be equal to `str.length` if the escape sequence is truncated by the + * end of the string, as in `"\\u1"`. + */ protected[scala] class InvalidUnicodeEscapeException(str: String, val escapeStart: Int, val index: Int) extends IllegalArgumentException( s"""invalid unicode escape at index $index of $str""" ) @@ -357,6 +383,15 @@ object StringContext { * @return The string with all escape sequences expanded. */ @deprecated("use processEscapes", "2.13.0") + /** Returns the given string with all standard Scala escape sequences expanded. + * + * A backslash that does not start a valid escape sequence raises an + * `InvalidEscapeException`, and a backslash followed by one or more `u` + * characters that is not a well-formed four hex-digit Unicode escape raises + * an `InvalidUnicodeEscapeException`. + * + * @param str a string that may contain escape sequences + */ def treatEscapes(str: String): String = processEscapes(str) /** Expands standard Scala escape sequences in a string. @@ -367,12 +402,30 @@ object StringContext { * @param str A string that may contain escape sequences * @return The string with all escape sequences expanded. */ + /** Returns the given string with all standard Scala escape sequences expanded, + * including Unicode escapes of the form `\uxxxx`. + * A backslash that does not start a valid escape sequence raises an + * `InvalidEscapeException`. A backslash followed by one or more `u` characters + * that is not a well-formed four hex-digit Unicode escape, such as `"\u1"`, + * raises an `InvalidUnicodeEscapeException` instead. + * + * @param str a string that may contain escape sequences + */ def processEscapes(str: String): String = str.indexOf('\\') match { case -1 => str case i => replace(str, i) } + /** Returns the given string with its Unicode escape sequences replaced by the + * characters they denote. + * A `\u` sequence is processed as an escape only when preceded by an odd number of + * backslashes; otherwise the backslash is taken to be literal. + * A sequence that is processed as an escape but is not a well-formed four + * hex-digit Unicode escape raises an `InvalidUnicodeEscapeException`. + * + * @param str a string that may contain Unicode escape sequences + */ protected[scala] def processUnicode(str: String): String = str.indexOf("\\u") match { case -1 => str @@ -462,6 +515,19 @@ object StringContext { loop(0, backslash) } + /** Interpolates the given arguments between the given literal parts, transforming + * each part with `process` first. + * + * If the number of `parts` is not exactly `args.length + 1`, an + * `IllegalArgumentException` is thrown. + * + * @param process the transformation applied to each literal part, such as escape expansion + * @param args the values to be interpolated between the parts + * @param parts the literal parts of the interpolated string, which must number exactly + * one more than `args` + * @return the processed parts concatenated with the string representations of the + * arguments interleaved between them + */ def standardInterpolator(process: String => String, args: scala.collection.Seq[Any], parts: Seq[String]): String = { StringContext.checkLengths(args, parts) val pi = parts.iterator @@ -481,6 +547,12 @@ object StringContext { * @param parts the literal parts of the interpolated string * @throws IllegalArgumentException if this is not the case. */ + /** Checks that the number of given arguments is one less than the number of given + * parts, throwing an `IllegalArgumentException` if it is not. + * + * @param args the interpolated argument values + * @param parts the literal parts of the interpolated string + */ def checkLengths(args: scala.collection.Seq[Any], parts: Seq[String]): Unit = if (parts.length != args.length + 1) throw new IllegalArgumentException("wrong number of arguments ("+ args.length diff --git a/library/src/scala/Symbol.scala b/library/src/scala/Symbol.scala index 064c855cee6c..a26309667ca2 100644 --- a/library/src/scala/Symbol.scala +++ b/library/src/scala/Symbol.scala @@ -23,13 +23,36 @@ final class Symbol private (val name: String) extends Serializable { @throws(classOf[java.io.ObjectStreamException]) private def readResolve(): Any = Symbol.apply(name) + /** Returns the hash code of this symbol's name. Throws a `NullPointerException` + * if this symbol was created with a `null` name. + */ override def hashCode() = name.hashCode() + /** Tests whether `other` is this very symbol. Because symbols are interned, + * reference equality coincides with equality of names. + * + * @param other the value to compare with this symbol + */ override def equals(other: Any) = this eq other.asInstanceOf[AnyRef] } object Symbol extends UniquenessCache[String, Symbol] { + /** Returns the unique symbol with the given name, creating and caching it if + * no such symbol exists yet. + * + * @param name the name of the symbol + */ override def apply(name: String): Symbol = super.apply(name) + /** Constructs a fresh symbol with the given name, without consulting the cache. + * + * @param name the name of the symbol to create + * @return a newly allocated `Symbol` for the cache to intern + */ protected def valueFromKey(name: String): Symbol = new Symbol(name) + /** Returns the cache key under which `sym` is interned, namely its name. + * + * @param sym the symbol to take the key from + * @return the symbol's name, always wrapped in `Some` + */ protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name) } @@ -49,9 +72,27 @@ private[scala] abstract class UniquenessCache[K, V] { private val wlock = rwl.writeLock private val map = new WeakHashMap[K, WeakReference[V]] + /** Constructs the value to cache for a key that is not yet present. + * + * @param k the key a value is needed for + * @return a newly constructed value corresponding to `k` + */ protected def valueFromKey(k: K): V + /** Recovers the key from which a cached value was constructed. + * + * @param v the value to take the key from + * @return the key corresponding to `v`, or `None` if it has none + */ protected def keyFromValue(v: V): Option[K] + /** Returns the unique value associated with `name`, constructing and caching it + * if the cache holds no live value for that key. Values are held by weak + * references, so a cached value that has been garbage collected is + * reconstructed on the next lookup. Concurrent access is guarded by a + * read/write lock. + * + * @param name the key to look up + */ def apply(name: K): V = { def cached(): V | Null = { rlock.lock @@ -85,5 +126,11 @@ private[scala] abstract class UniquenessCache[K, V] { case res => res } } + /** Extracts the key from which a cached value was constructed, allowing values + * to be used in pattern matches. + * + * @param other the value to deconstruct + * @return the key corresponding to `other`, or `None` if it has none + */ def unapply(other: V): Option[K] = keyFromValue(other) } diff --git a/library/src/scala/UninitializedFieldError.scala b/library/src/scala/UninitializedFieldError.scala index 10e8c5b2b80f..29389f5de619 100644 --- a/library/src/scala/UninitializedFieldError.scala +++ b/library/src/scala/UninitializedFieldError.scala @@ -23,8 +23,18 @@ import scala.language.`2.13` * @param msg the error message describing which field was accessed before initialization */ final case class UninitializedFieldError(msg: String) extends RuntimeException(msg) { + /** Creates an `UninitializedFieldError` whose message is the string + * representation of `obj`. + * + * @param obj the value describing which field was accessed before initialization; a + * `null` value yields the message `"null"` + */ def this(obj: Any) = this("" + obj) } object UninitializedFieldError extends scala.runtime.AbstractFunction1[String, UninitializedFieldError]: + /** Returns the name of this companion object, `"UninitializedFieldError"`, rather than + * the `` rendering inherited via [[scala.runtime.AbstractFunction1]] from + * [[scala.Function1]]. + */ override def toString(): String = "UninitializedFieldError" diff --git a/library/src/scala/annotation/experimental.scala b/library/src/scala/annotation/experimental.scala index 15cf32315574..72fa6db4efa4 100644 --- a/library/src/scala/annotation/experimental.scala +++ b/library/src/scala/annotation/experimental.scala @@ -10,4 +10,5 @@ import language.experimental.captureChecking * @param message a description explaining the experimental status, or an empty string if no message is needed */ final class experimental(message: String) extends StaticAnnotation: + /** Creates an `experimental` annotation with no explanatory message. */ def this() = this("") diff --git a/library/src/scala/annotation/internal/preview.scala b/library/src/scala/annotation/internal/preview.scala index b28718c920fe..1f6d9aff19f7 100644 --- a/library/src/scala/annotation/internal/preview.scala +++ b/library/src/scala/annotation/internal/preview.scala @@ -11,4 +11,5 @@ import language.experimental.captureChecking * @param message an explanation of the preview status or migration guidance */ private[scala] final class preview(message: String) extends StaticAnnotation: + /** Creates a `preview` annotation with no explanatory message. */ def this() = this("") diff --git a/library/src/scala/annotation/meta/defaultArg.scala b/library/src/scala/annotation/meta/defaultArg.scala index 0d39f65da7fc..33eda752a028 100644 --- a/library/src/scala/annotation/meta/defaultArg.scala +++ b/library/src/scala/annotation/meta/defaultArg.scala @@ -29,5 +29,6 @@ import scala.language.`2.13` * @param arg the default expression for the annotation parameter, stored as a syntax tree in the classfile */ @meta.param class defaultArg(arg: Any) extends StaticAnnotation { + /** Creates a `defaultArg` annotation whose `arg` is `null`. */ def this() = this(null) } diff --git a/library/src/scala/annotation/unused.scala b/library/src/scala/annotation/unused.scala index d1ab6b280acb..05583adafc05 100644 --- a/library/src/scala/annotation/unused.scala +++ b/library/src/scala/annotation/unused.scala @@ -26,5 +26,6 @@ import scala.language.`2.13` */ @meta.getter @meta.setter class unused(message: String) extends StaticAnnotation { + /** Creates an `unused` annotation with no explanatory message. */ def this() = this("") } diff --git a/library/src/scala/caps/package.scala b/library/src/scala/caps/package.scala index 05da4482bfa7..033d466a417d 100644 --- a/library/src/scala/caps/package.scala +++ b/library/src/scala/caps/package.scala @@ -93,6 +93,18 @@ trait Stateful trait Unscoped extends ExclusiveCapability, Classifier @experimental +/** Marker trait for mutable data structures such as ref cells or matrices. + * `Mutable` is itself both [[Stateful]] and [[Unscoped]], so classes extending it + * can consult and change global program state and are not subject to the scoping + * restrictions of captured capabilities. + * + * When [[scala.language.experimental.captureChecking Capture Checking]] is turned on, + * a reference to a type extending `Mutable` gets the implicit capture set `{any.rd}` + * if no capture set is given explicitly. + * + * [[scala.Array]] does not extend this trait, but when separation checking is + * enabled it is treated as a mutable type as well. + */ trait Mutable extends Stateful, Unscoped /** Carrier trait for capture set type parameters. */ @@ -180,6 +192,7 @@ object internal: * @tparam T the type of the mutable variable's value */ trait Var[T] extends Mutable: + /** Returns the current value of the mutable variable. */ def get: T update def set(x: T): Unit diff --git a/library/src/scala/deriving/Mirror.scala b/library/src/scala/deriving/Mirror.scala index 5cb68842ffc9..da5fffd1124e 100644 --- a/library/src/scala/deriving/Mirror.scala +++ b/library/src/scala/deriving/Mirror.scala @@ -36,11 +36,16 @@ object Mirror { def fromProduct(p: scala.Product): MirroredMonoType } + /** The `Mirror` for a singleton type, which has no product elements. */ trait Singleton extends Product { type MirroredMonoType = this.type type MirroredType = this.type type MirroredElemTypes = EmptyTuple type MirroredElemLabels = EmptyTuple + /** Returns the singleton instance itself. + * + * @param p ignored, since a singleton has no elements + */ def fromProduct(p: scala.Product): MirroredMonoType = this } @@ -53,6 +58,10 @@ object Mirror { type MirroredType = value.type type MirroredElemTypes = EmptyTuple type MirroredElemLabels = EmptyTuple + /** Returns the proxied Scala 2 singleton instance. + * + * @param p ignored, since a singleton has no elements + */ def fromProduct(p: scala.Product): MirroredMonoType = value } @@ -66,7 +75,6 @@ object Mirror { * @tparam A the product type whose elements are used as input * @tparam Elems the tuple type representing `A`'s elements, constrained to be a subtype of `T`'s `MirroredElemTypes` * @param a the product instance whose elements are copied into the new `T` - */ def fromProductTyped[A <: scala.Product, Elems <: p.MirroredElemTypes](a: A)(using ProductOf[A] { type MirroredElemTypes = Elems }): T = p.fromProduct(a) diff --git a/library/src/scala/languageFeature.scala b/library/src/scala/languageFeature.scala index 8ce9724ecc17..0871c72ba843 100644 --- a/library/src/scala/languageFeature.scala +++ b/library/src/scala/languageFeature.scala @@ -18,33 +18,40 @@ import scala.annotation.meta object languageFeature { @meta.languageFeature("extension of type scala.Dynamic", enableRequired = true) + /** Serves as the witness type for the [[scala.language.dynamics `dynamics`]] language feature, which permits subclassing [[scala.Dynamic]]. */ sealed trait dynamics object dynamics extends dynamics @meta.languageFeature("postfix operator #", enableRequired = true) + /** Serves as the witness type for the [[scala.language.postfixOps `postfixOps`]] language feature, which permits postfix operator notation `expr op`. */ sealed trait postfixOps object postfixOps extends postfixOps @meta.languageFeature("reflective access of structural type member #", enableRequired = false) + /** Serves as the witness type for the [[scala.language.reflectiveCalls `reflectiveCalls`]] language feature, a legacy Scala 2 feature that is no longer supported in Scala 3. */ sealed trait reflectiveCalls object reflectiveCalls extends reflectiveCalls @meta.languageFeature("implicit conversion #", enableRequired = false) + /** Serves as the witness type for the [[scala.language.implicitConversions `implicitConversions`]] language feature, which permits defining implicit conversion methods. */ sealed trait implicitConversions object implicitConversions extends implicitConversions @deprecated("scala.language.higherKinds no longer needs to be imported explicitly", "2.13.1") @meta.languageFeature("higher-kinded type", enableRequired = false) + /** Serves as the witness type for the deprecated `higherKinds` language feature, a legacy Scala 2 feature that is no longer supported in Scala 3, where higher-kinded types need no language import. */ sealed trait higherKinds @deprecated("scala.language.higherKinds no longer needs to be imported explicitly", "2.13.1") object higherKinds extends higherKinds @meta.languageFeature("#, which cannot be expressed by wildcards,", enableRequired = false) + /** Serves as the witness type for the [[scala.language.existentials `existentials`]] language feature, a legacy Scala 2 feature that is no longer supported in Scala 3. */ sealed trait existentials object existentials extends existentials object experimental { @meta.languageFeature("macro definition", enableRequired = true) + /** Serves as the witness type for the [[scala.language.experimental.macros `experimental.macros`]] language feature, which permits Scala 2-style `def ... = macro ...` definitions. */ sealed trait macros object macros extends macros } diff --git a/library/src/scala/package.scala b/library/src/scala/package.scala index ccf0187cb9ea..784420397494 100644 --- a/library/src/scala/package.scala +++ b/library/src/scala/package.scala @@ -91,8 +91,22 @@ package object scala { // This should be an alias to LazyList.#:: but we need to support Stream, too //val #:: = scala.collection.immutable.LazyList.#:: object #:: { + /** Extracts the head and tail of a non-empty [[scala.collection.immutable.LazyList]], + * supporting the `head #:: tail` pattern wherever patterns are allowed. + * + * @tparam A the element type of the lazy list + * @param s the lazy list to decompose + * @return `Some((head, tail))` if `s` is non-empty, or `None` if it is empty + */ def unapply[A](s: LazyList[A]): Option[(A, LazyList[A])] = if (s.nonEmpty) Some((s.head, s.tail)) else None + /** Extracts the head and tail of a non-empty [[scala.collection.immutable.Stream]], + * supporting the `head #:: tail` pattern wherever patterns are allowed. + * + * @tparam A the element type of the stream + * @param s the stream to decompose + * @return `Some((head, tail))` if `s` is non-empty, or `None` if it is empty + */ @deprecated("Prefer LazyList instead", since = "2.13.0") def unapply[A](s: Stream[A]): Option[(A, Stream[A])] = if (s.nonEmpty) Some((s.head, s.tail)) else None diff --git a/library/src/scala/reflect/ClassManifestDeprecatedApis.scala b/library/src/scala/reflect/ClassManifestDeprecatedApis.scala index 893e3e957a7f..f923bd3168c0 100644 --- a/library/src/scala/reflect/ClassManifestDeprecatedApis.scala +++ b/library/src/scala/reflect/ClassManifestDeprecatedApis.scala @@ -20,11 +20,17 @@ import java.lang.{Class => jClass} import scala.annotation.{nowarn, tailrec} @deprecated("use scala.reflect.ClassTag instead", "2.10.0") +/** Provides the deprecated members of the `ClassManifest` API. [[scala.reflect.ClassTag]] extends + * this trait for source compatibility with `ClassManifest`, which is an alias for `ClassTag`. + * + * @tparam T the type described by the manifest + */ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { self: ClassManifest[T] => // Still in use in target test.junit.comp. @deprecated("use runtimeClass instead", "2.10.0") + /** Returns the runtime class of the type described by this manifest. */ def erasure: jClass[?] = runtimeClass private def subtype(sub: jClass[?], sup: jClass[?]): Boolean = { @@ -90,51 +96,94 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { def >:>(that: ClassManifest[?]): Boolean = that <:< this + /** Returns `true` if `other` is a `ClassManifest`, and so is a candidate for equality with this manifest. + * + * @param other the value to test for comparability with this manifest + */ override def canEqual(other: Any) = other match { case _: ClassManifest[?] => true case _ => false } + /** Returns the `Class` object for arrays whose element class is `tp`. + * + * @tparam A the element type of the array class + * @param tp the runtime `Class` of the array's element type + * @return the `Class` representing `Array[A]`. The cast to that type is unchecked, so `tp` is + * assumed to be the erasure of `A`. + */ protected def arrayClass[A](tp: jClass[?]): jClass[Array[A]] = java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[jClass[Array[A]]] + /** Returns a manifest for the array type `Array[T]`. */ @deprecated("use wrap instead", "2.10.0") def arrayManifest: ClassManifest[Array[T]] = ClassManifest.classType[Array[T]](arrayClass[T](runtimeClass), this) + /** Returns a new two-dimensional array of `T` whose outer dimension has length `len`. + * + * @param len the length of the outer array + * @return a new `Array[Array[T]]` of length `len`, whose elements are all `null` + */ @deprecated("use wrap.newArray instead", "2.10.0") def newArray2(len: Int): Array[Array[T]] = java.lang.reflect.Array.newInstance(arrayClass[T](runtimeClass), len) .asInstanceOf[Array[Array[T]]] @deprecated("use wrap.wrap.newArray instead", "2.10.0") + /** Returns a new three-dimensional array of `T` whose outermost dimension has length `len`. + * + * @param len the length of the outermost array + * @return a new `Array[Array[Array[T]]]` of length `len`, whose elements are all `null` + */ def newArray3(len: Int): Array[Array[Array[T]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](runtimeClass)), len) .asInstanceOf[Array[Array[Array[T]]]] @deprecated("use wrap.wrap.wrap.newArray instead", "2.10.0") + /** Returns a new four-dimensional array of `T` whose outermost dimension has length `len`. + * + * @param len the length of the outermost array + * @return a new `Array[Array[Array[Array[T]]]]` of length `len`, whose elements are all `null` + */ def newArray4(len: Int): Array[Array[Array[Array[T]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass))), len) .asInstanceOf[Array[Array[Array[Array[T]]]]] @deprecated("use wrap.wrap.wrap.wrap.newArray instead", "2.10.0") + /** Returns a new five-dimensional array of `T` whose outermost dimension has length `len`. + * + * @param len the length of the outermost array + * @return a new `Array[Array[Array[Array[Array[T]]]]]` of length `len`, whose elements are all `null` + */ def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] = java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](runtimeClass)))), len) .asInstanceOf[Array[Array[Array[Array[Array[T]]]]]] + /** Returns a new mutable sequence of length `len` backed by a freshly created array of `T`. + * + * @param len the length of the underlying array + * @return a new [[scala.collection.mutable.ArraySeq]] wrapping an `Array[T]` of length `len` + */ @deprecated("create WrappedArray directly instead", "2.10.0") def newWrappedArray(len: Int): ArraySeq[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new ArraySeq.ofRef[T & AnyRef](newArray(len).asInstanceOf[Array[T & AnyRef]]).asInstanceOf[ArraySeq[T]] + /** Returns a new builder for arrays with element type `T`. */ @deprecated("use ArrayBuilder.make(this) instead", "2.10.0") def newArrayBuilder(): ArrayBuilder[T] = // it's safe to assume T <: AnyRef here because the method is overridden for all value type manifests new ArrayBuilder.ofRef[T & AnyRef]()(using this.asInstanceOf[ClassManifest[T & AnyRef]]).asInstanceOf[ArrayBuilder[T]] + /** Returns the manifests for the type arguments of the type described by this manifest, or `Nil` if there are none. */ @deprecated("use scala.reflect.runtime.universe.TypeTag to capture type structure instead", "2.10.0") def typeArguments: List[OptManifest[?]] = List() + /** Returns the bracketed type arguments of this manifest. If there are no type arguments but the + * runtime class is an array, returns its bracketed component type instead. Otherwise returns the + * empty string. + */ protected def argString = if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]") else if (runtimeClass.isArray) "["+ClassManifest.fromClass(runtimeClass.getComponentType)+"]" @@ -170,6 +219,13 @@ object ClassManifestFactory { val Nothing = ManifestFactory.Nothing val Null = ManifestFactory.Null + /** Returns the `ClassManifest` for the type whose erasure is `clazz`. + * + * @tparam T the type described by `clazz` + * @param clazz the runtime `Class` object to build a manifest for + * @return one of the predefined value-type manifests if `clazz` is a primitive class, with + * `Void.TYPE` mapping to `Unit`, otherwise a class-type manifest for `clazz` + */ def fromClass[T](clazz: jClass[T]): ClassManifest[T] = clazz match { case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]] case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]] @@ -183,6 +239,15 @@ object ClassManifestFactory { case _ => classType[T & AnyRef](clazz).asInstanceOf[ClassManifest[T]] } + /** Returns the manifest for the singleton type `value.type`. + * + * @tparam T the singleton type the resulting manifest is requested to describe; the signature does + * not relate it to the type of `value`, so callers supply it or let it default to `AnyRef` + * @param value the runtime object whose singleton type is represented; must be non-null, since + * the resulting manifest calls `value.getClass` and `value.toString` + * @return a `Manifest` that lazily obtains its `runtimeClass` from `value.getClass`, throwing a + * `NullPointerException` on first access if `value` is `null` + */ def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest.singleType(value) /** ClassManifest for the class type `clazz`, where `clazz` is @@ -220,6 +285,13 @@ object ClassManifestFactory { def classType[T](prefix: OptManifest[?], clazz: jClass[?], args: OptManifest[?]*): ClassManifest[T] = new ClassTypeManifest[T](Some(prefix), clazz, args.toList) + /** Returns the `ClassManifest` for the array type `Array[T]`, given the manifest `arg` + * for the element type `T`. + * + * @tparam T the element type of the array type described by the result + * @param arg the manifest for the element type, or `NoManifest` if it is unknown + * @return the array manifest derived from `arg`, or the `Object` manifest if `arg` is `NoManifest` + */ def arrayType[T](arg: OptManifest[?]): ClassManifest[Array[T]] = (arg: @unchecked) match { case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]] case m: ClassManifest[?] => m.asInstanceOf[ClassManifest[T]].arrayManifest @@ -227,8 +299,10 @@ object ClassManifestFactory { @SerialVersionUID(1L) private class AbstractTypeClassManifest[T](prefix: OptManifest[?], name: String, clazz: jClass[?], args: OptManifest[?]*) extends ClassManifest[T] { + /** Returns the runtime class that was supplied as the erasure of the abstract type. */ override def runtimeClass = clazz override val typeArguments = args.toList + /** Returns the abstract type rendered as `prefix#name`, followed by its type arguments. */ override def toString() = prefix.toString+"#"+name+argString } @@ -270,6 +344,10 @@ private class ClassTypeManifest[T]( val runtimeClass: jClass[?], override val typeArguments: List[OptManifest[?]]) extends ClassManifest[T] { + /** Returns the represented type rendered as three parts: the prefix followed by `#`, if there is a + * prefix; then `Array` if the runtime class is an array class, otherwise the runtime class name; + * then the type arguments. + */ override def toString() = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + (if (runtimeClass.isArray) "Array" else runtimeClass.getName) + diff --git a/library/src/scala/reflect/ClassTag.scala b/library/src/scala/reflect/ClassTag.scala index 497a1f9e5265..e6763ff99af7 100644 --- a/library/src/scala/reflect/ClassTag.scala +++ b/library/src/scala/reflect/ClassTag.scala @@ -78,9 +78,24 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial else None // case class accessories + /** Returns `true` if `x` is a `ClassTag`, making it eligible for comparison with this one. + * + * @param x the value to test for comparability with this class tag + */ override def canEqual(x: Any) = x.isInstanceOf[ClassTag[?]] + /** Returns `true` if `x` is a `ClassTag` whose `runtimeClass` is the same as this class tag's. + * + * Note that the type arguments of the two tags play no part in the comparison, since only + * the erased class is stored. + * + * @param x the value to compare with this class tag + */ override def equals(x: Any) = x.isInstanceOf[ClassTag[?]] && this.runtimeClass == x.asInstanceOf[ClassTag[?]].runtimeClass + /** Returns a hash code derived from `runtimeClass`, consistent with `equals`. */ override def hashCode() = runtimeClass.## + /** Returns the name of `runtimeClass`, rendering array classes as `Array[...]` instead of in + * the form returned by `Class.getName`, such as `[Ljava.lang.String;`. + */ override def toString() = { def prettyprint(clazz: jClass[?]): String = if (clazz.isArray) s"Array[${prettyprint(clazz.getComponentType)}]" else @@ -115,9 +130,20 @@ object ClassTag { private val cacheDisabled = java.lang.Boolean.getBoolean("scala.reflect.classtag.cache.disable") private object cache extends ClassValueCompat[jWeakReference[ClassTag[?]]] { + /** Computes the cache entry for `runtimeClass`, holding its `ClassTag` only weakly so that a + * cached entry does not by itself keep the tag alive. + * + * @param runtimeClass the class for which a `ClassTag` is being cached + * @return a weak reference to the `ClassTag` for `runtimeClass` + */ override def computeValue(runtimeClass: jClass[?]): jWeakReference[ClassTag[?]] = new jWeakReference(computeTag(runtimeClass)) + /** Returns the `ClassTag` for `runtimeClass`, reusing the predefined tags for the primitive + * types and for `Object`, `Nothing` and `Null`, and creating a generic tag for any other class. + * + * @param runtimeClass the erased class the tag should describe + */ def computeTag(runtimeClass: jClass[?]): ClassTag[?] = runtimeClass match { case x if x.isPrimitive => primitiveClassTag(runtimeClass) @@ -143,11 +169,24 @@ object ClassTag { @SerialVersionUID(1L) private class GenericClassTag[T](val runtimeClass: jClass[?]) extends ClassTag[T] { + /** Returns a new array of length `len` whose element type is `runtimeClass`. + * + * @param len the length of the new array + */ override def newArray(len: Int): Array[T] = { java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] } } + /** Returns a `ClassTag[T]` whose `runtimeClass` is `runtimeClass1`, taken from a cache of tags + * keyed by class unless caching was disabled by setting the system property + * `scala.reflect.classtag.cache.disable` to `true` before this object was initialized, in which + * case a tag is computed on each call. + * + * @tparam T the type the resulting tag stands for; it is assumed, but not checked, to erase + * to `runtimeClass1` + * @param runtimeClass1 the erased class the resulting tag describes + */ def apply[T](runtimeClass1: jClass[?]): ClassTag[T] = { if (cacheDisabled) { cache.computeTag(runtimeClass1).asInstanceOf[ClassTag[T]] @@ -162,5 +201,14 @@ object ClassTag { } } + /** Extracts the erased class stored in a `ClassTag`, so that class tags can be taken apart in + * pattern matches. + * + * A `null` tag is not accepted: the extraction throws `NullPointerException` in that case. + * + * @tparam T the type the tag stands for + * @param ctag the class tag to take apart + * @return `Some` of the tag's `runtimeClass`; for a non-null `ctag` the match always succeeds + */ def unapply[T](ctag: ClassTag[T]): Option[Class[?]] = Some(ctag.runtimeClass) } diff --git a/library/src/scala/reflect/Manifest.scala b/library/src/scala/reflect/Manifest.scala index 6700da6b5930..20c95c26ecb0 100644 --- a/library/src/scala/reflect/Manifest.scala +++ b/library/src/scala/reflect/Manifest.scala @@ -49,11 +49,17 @@ import scala.collection.mutable.{ArrayBuilder, ArraySeq} // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("use scala.reflect.ClassTag (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0") trait Manifest[T] extends ClassManifest[T] with Equals { + /** Returns the manifests for the type arguments of the represented type, or `Nil` if there are none. */ override def typeArguments: List[Manifest[?]] = Nil + /** Returns a manifest for the array type `Array[T]`. */ override def arrayManifest: Manifest[Array[T]] = Manifest.classType[Array[T]](arrayClass[T](runtimeClass), this) + /** Returns `true` if `that` is a `Manifest`, and so is a candidate for equality with this manifest. + * + * @param that the value to test for comparability with this manifest + */ override def canEqual(that: Any): Boolean = that match { case _: Manifest[?] => true case _ => false @@ -67,6 +73,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals { case m: Manifest[?] => (m canEqual this) && (this.runtimeClass == m.runtimeClass) && (this <:< m) && (m <:< this) case _ => false } + /** Returns a hash code derived from `runtimeClass`, so that manifests with the same erasure hash alike. */ override def hashCode() = this.runtimeClass.## } @@ -82,6 +89,9 @@ object Manifest { * defined above. */ + /** Returns the manifests for the nine value types, in the order `Byte`, `Short`, `Char`, `Int`, + * `Long`, `Float`, `Double`, `Boolean`, `Unit`. + */ def valueManifests: List[AnyValManifest[?]] = ManifestFactory.valueManifests @@ -145,6 +155,13 @@ object Manifest { def classType[T](prefix: Manifest[?], clazz: Predef.Class[?], args: Manifest[?]*): Manifest[T] = ManifestFactory.classType[T](prefix, clazz, args*) + /** Returns the manifest for the array type `Array[T]`, given the manifest `arg` for the element type `T`. + * + * @tparam T the element type of the array type described by the result + * @param arg the manifest for the element type + * @return the `arrayManifest` obtained by casting `arg` to `Manifest[T]`; the cast is unchecked, + * so `arg` is assumed to describe `T` + */ def arrayType[T](arg: Manifest[?]): Manifest[Array[T]] = ManifestFactory.arrayType[T](arg) @@ -180,6 +197,16 @@ object Manifest { } +/** A `Manifest` for one of the value types, such as `Int` or `Boolean`. + * + * Instances of this class are compared by reference identity, and the represented type conforms + * only to itself, `Any` and `AnyVal`. The canonical manifest for each value type is the single + * instance supplied by `Manifest`, such as `Manifest.Int`. + * + * @tparam T the value type described by this manifest + * @param toString the name of the value type, such as `"Int"`, used as the string representation + * of this manifest + */ // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("use type tags and manually check the corresponding class or type instead", "2.10.0") @nowarn("""cat=deprecation&origin=scala\.reflect\.ClassManifest(DeprecatedApis.*)?""") @@ -187,11 +214,21 @@ object Manifest { abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals { override def <:<(that: ClassManifest[?]): Boolean = (that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal) + /** Returns `true` if `other` is an `AnyValManifest`, and so is a candidate for equality with this manifest. + * + * @param other the value to test for comparability with this manifest + */ override def canEqual(other: Any) = other match { case _: AnyValManifest[?] => true case _ => false } + /** Returns `true` only if `that` is this very manifest, since equality for value type manifests is + * reference identity. + * + * @param that the value to compare with this manifest + */ override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + /** Returns the identity hash code of this manifest, consistent with its reference-identity `equals`. */ override def hashCode = System.identityHashCode(this) } @@ -204,15 +241,30 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend */ @nowarn("""cat=deprecation&origin=scala\.reflect\.ClassManifest(DeprecatedApis.*)?""") object ManifestFactory { + /** Returns the manifests for the nine value types, in the order `Byte`, `Short`, `Char`, `Int`, + * `Long`, `Float`, `Double`, `Boolean`, `Unit`. + */ def valueManifests: List[AnyValManifest[?]] = List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit) @SerialVersionUID(1L) final private[reflect] class ByteManifest extends AnyValManifest[scala.Byte]("Byte") { + /** Returns the `Class` for the primitive type `byte`. */ def runtimeClass: Class[java.lang.Byte] = java.lang.Byte.TYPE @inline override def newArray(len: Int): Array[Byte] = new Array[Byte](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Byte]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofByte` wrapping an `Array[Byte]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Byte] = new ArraySeq.ofByte(new Array[Byte](len)) + /** Returns a new builder for arrays with element type `Byte`. */ override def newArrayBuilder(): ArrayBuilder[Byte] = new ArrayBuilder.ofByte() + /** Matches `x` only if it is a `Byte`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Byte` + * @return `Some(x)` if `x` is a `Byte`, `None` otherwise + */ override def unapply(x: Any): Option[Byte] = { x match { case d: Byte => Some(d) @@ -225,10 +277,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class ShortManifest extends AnyValManifest[scala.Short]("Short") { + /** Returns the `Class` for the primitive type `short`. */ def runtimeClass: Class[java.lang.Short] = java.lang.Short.TYPE @inline override def newArray(len: Int): Array[Short] = new Array[Short](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Short]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofShort` wrapping an `Array[Short]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Short] = new ArraySeq.ofShort(new Array[Short](len)) + /** Returns a new builder for arrays with element type `Short`. */ override def newArrayBuilder(): ArrayBuilder[Short] = new ArrayBuilder.ofShort() + /** Matches `x` only if it is a `Short`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Short` + * @return `Some(x)` if `x` is a `Short`, `None` otherwise + */ override def unapply(x: Any): Option[Short] = { x match { case d: Short => Some(d) @@ -241,10 +305,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class CharManifest extends AnyValManifest[scala.Char]("Char") { + /** Returns the `Class` for the primitive type `char`. */ def runtimeClass: Class[java.lang.Character] = java.lang.Character.TYPE @inline override def newArray(len: Int): Array[Char] = new Array[Char](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Char]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofChar` wrapping an `Array[Char]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Char] = new ArraySeq.ofChar(new Array[Char](len)) + /** Returns a new builder for arrays with element type `Char`. */ override def newArrayBuilder(): ArrayBuilder[Char] = new ArrayBuilder.ofChar() + /** Matches `x` only if it is a `Char`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Char` + * @return `Some(x)` if `x` is a `Char`, `None` otherwise + */ override def unapply(x: Any): Option[Char] = { x match { case d: Char => Some(d) @@ -257,10 +333,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class IntManifest extends AnyValManifest[scala.Int]("Int") { + /** Returns the `Class` for the primitive type `int`. */ def runtimeClass: Class[java.lang.Integer] = java.lang.Integer.TYPE @inline override def newArray(len: Int): Array[Int] = new Array[Int](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Int]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofInt` wrapping an `Array[Int]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Int] = new ArraySeq.ofInt(new Array[Int](len)) + /** Returns a new builder for arrays with element type `Int`. */ override def newArrayBuilder(): ArrayBuilder[Int] = new ArrayBuilder.ofInt() + /** Matches `x` only if it is an `Int`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being an `Int` + * @return `Some(x)` if `x` is an `Int`, `None` otherwise + */ override def unapply(x: Any): Option[Int] = { x match { case d: Int => Some(d) @@ -273,10 +361,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class LongManifest extends AnyValManifest[scala.Long]("Long") { + /** Returns the `Class` for the primitive type `long`. */ def runtimeClass: Class[java.lang.Long] = java.lang.Long.TYPE @inline override def newArray(len: Int): Array[Long] = new Array[Long](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Long]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofLong` wrapping an `Array[Long]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Long] = new ArraySeq.ofLong(new Array[Long](len)) + /** Returns a new builder for arrays with element type `Long`. */ override def newArrayBuilder(): ArrayBuilder[Long] = new ArrayBuilder.ofLong() + /** Matches `x` only if it is a `Long`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Long` + * @return `Some(x)` if `x` is a `Long`, `None` otherwise + */ override def unapply(x: Any): Option[Long] = { x match { case d: Long => Some(d) @@ -289,10 +389,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class FloatManifest extends AnyValManifest[scala.Float]("Float") { + /** Returns the `Class` for the primitive type `float`. */ def runtimeClass: Class[java.lang.Float] = java.lang.Float.TYPE @inline override def newArray(len: Int): Array[Float] = new Array[Float](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Float]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofFloat` wrapping an `Array[Float]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Float] = new ArraySeq.ofFloat(new Array[Float](len)) + /** Returns a new builder for arrays with element type `Float`. */ override def newArrayBuilder(): ArrayBuilder[Float] = new ArrayBuilder.ofFloat() + /** Matches `x` only if it is a `Float`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Float` + * @return `Some(x)` if `x` is a `Float`, `None` otherwise + */ override def unapply(x: Any): Option[Float] = { x match { case d: Float => Some(d) @@ -305,11 +417,23 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class DoubleManifest extends AnyValManifest[scala.Double]("Double") { + /** Returns the `Class` for the primitive type `double`. */ def runtimeClass: Class[java.lang.Double] = java.lang.Double.TYPE @inline override def newArray(len: Int): Array[Double] = new Array[Double](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Double]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofDouble` wrapping an `Array[Double]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Double] = new ArraySeq.ofDouble(new Array[Double](len)) + /** Returns a new builder for arrays with element type `Double`. */ override def newArrayBuilder(): ArrayBuilder[Double] = new ArrayBuilder.ofDouble() + /** Matches `x` only if it is a `Double`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Double` + * @return `Some(x)` if `x` is a `Double`, `None` otherwise + */ override def unapply(x: Any): Option[Double] = { x match { case d: Double => Some(d) @@ -322,10 +446,22 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class BooleanManifest extends AnyValManifest[scala.Boolean]("Boolean") { + /** Returns the `Class` for the primitive type `boolean`. */ def runtimeClass: Class[java.lang.Boolean] = java.lang.Boolean.TYPE @inline override def newArray(len: Int): Array[Boolean] = new Array[Boolean](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Boolean]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofBoolean` wrapping an `Array[Boolean]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Boolean] = new ArraySeq.ofBoolean(new Array[Boolean](len)) + /** Returns a new builder for arrays with element type `Boolean`. */ override def newArrayBuilder(): ArrayBuilder[Boolean] = new ArrayBuilder.ofBoolean() + /** Matches `x` only if it is a `Boolean`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Boolean` + * @return `Some(x)` if `x` is a `Boolean`, `None` otherwise + */ override def unapply(x: Any): Option[Boolean] = { x match { case d: Boolean => Some(d) @@ -338,13 +474,34 @@ object ManifestFactory { @SerialVersionUID(1L) final private[reflect] class UnitManifest extends AnyValManifest[scala.Unit]("Unit") { + /** Returns the `Class` for the primitive type `void`. */ def runtimeClass: Class[java.lang.Void] = java.lang.Void.TYPE @inline override def newArray(len: Int): Array[Unit] = new Array[Unit](len) + /** Returns a new mutable sequence of length `len` backed by a freshly created `Array[Unit]`. + * + * @param len the length of the underlying array + * @return a new `ArraySeq.ofUnit` wrapping an `Array[Unit]` of length `len` + */ override def newWrappedArray(len: Int): ArraySeq[Unit] = new ArraySeq.ofUnit(new Array[Unit](len)) + /** Returns a new builder for arrays with element type `Unit`. */ override def newArrayBuilder(): ArrayBuilder[Unit] = new ArrayBuilder.ofUnit() + /** Returns the `Class` object for arrays whose element class is `tp`, answering + * `Array[scala.runtime.BoxedUnit]` when `tp` is the `Unit` runtime class, since that is how + * arrays of `Unit` are represented at runtime. + * + * @tparam T the element type of the array class + * @param tp the runtime `Class` of the array's element type + * @return the `Class` representing `Array[T]`. The cast to that type is unchecked, so `tp` is + * assumed to be the erasure of `T`. + */ override protected def arrayClass[T](tp: Class[?]): Class[Array[T]] = if (tp eq runtimeClass) classOf[Array[scala.runtime.BoxedUnit]].asInstanceOf[Class[Array[T]]] else super.arrayClass(tp) + /** Matches `x` only if it is a `Unit`, so that this manifest can serve as an extractor. + * + * @param x the value to test for being a `Unit` + * @return `Some(x)` if `x` is a `Unit`, `None` otherwise + */ override def unapply(x: Any): Option[Unit] = { x match { case d: Unit => Some(d) @@ -361,6 +518,10 @@ object ManifestFactory { @SerialVersionUID(1L) final private class AnyManifest extends PhantomManifest[scala.Any](ObjectTYPE, "Any") { + /** Returns a new `Array[Any]` of length `len`. + * + * @param len the length of the new array + */ override def newArray(len: Int) = new Array[scala.Any](len) override def <:<(that: ClassManifest[?]): Boolean = (that eq this) private def readResolve(): Any = Manifest.Any @@ -369,6 +530,10 @@ object ManifestFactory { @SerialVersionUID(1L) final private class ObjectManifest extends PhantomManifest[java.lang.Object](ObjectTYPE, "Object") { + /** Returns a new `Array[java.lang.Object]` of length `len`. + * + * @param len the length of the new array + */ override def newArray(len: Int) = new Array[java.lang.Object](len) override def <:<(that: ClassManifest[?]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.Object @@ -379,6 +544,10 @@ object ManifestFactory { @SerialVersionUID(1L) final private class AnyValPhantomManifest extends PhantomManifest[scala.AnyVal](ObjectTYPE, "AnyVal") { + /** Returns a new `Array[AnyVal]` of length `len`. + * + * @param len the length of the new array + */ override def newArray(len: Int) = new Array[scala.AnyVal](len) override def <:<(that: ClassManifest[?]): Boolean = (that eq this) || (that eq Any) private def readResolve(): Any = Manifest.AnyVal @@ -387,6 +556,10 @@ object ManifestFactory { @SerialVersionUID(1L) final private class NullManifest extends PhantomManifest[scala.Null](NullTYPE, "Null") { + /** Returns a new `Array[Null]` of length `len`, all of whose elements are `null`. + * + * @param len the length of the new array + */ override def newArray(len: Int) = new Array[scala.Null](len) override def <:<(that: ClassManifest[?]): Boolean = (that ne null) && (that ne Nothing) && !(that <:< AnyVal) @@ -396,6 +569,11 @@ object ManifestFactory { @SerialVersionUID(1L) final private class NothingManifest extends PhantomManifest[scala.Nothing](NothingTYPE, "Nothing") { + /** Returns a new `Array[Nothing]` of length `len`, all of whose elements are `null` since no + * value of type `Nothing` exists. + * + * @param len the length of the new array + */ override def newArray(len: Int) = new Array[scala.Nothing](len) override def <:<(that: ClassManifest[?]): Boolean = (that ne null) private def readResolve(): Any = Manifest.Nothing @@ -454,7 +632,13 @@ object ManifestFactory { @SerialVersionUID(1L) private abstract class PhantomManifest[T](_runtimeClass: Predef.Class[?], override val toString: String) extends ClassTypeManifest[T](None, _runtimeClass, Nil) { + /** Returns `true` only if `that` is this very manifest, since each phantom type is described by + * a single instance. + * + * @param that the value to compare with this manifest + */ override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef] + /** Returns the identity hash code of this manifest, consistent with its reference-identity `equals`. */ override def hashCode = System.identityHashCode(this) } @@ -465,19 +649,36 @@ object ManifestFactory { private class ClassTypeManifest[T](prefix: Option[Manifest[?]], val runtimeClass: Predef.Class[?], override val typeArguments: List[Manifest[?]]) extends Manifest[T] { + /** Returns the represented type rendered as three parts: the prefix followed by `#`, if there is + * a prefix; then `Array` if the runtime class is an array class, otherwise the runtime class + * name; then `argString`: the type arguments if there are any, otherwise the bracketed component + * type of the runtime class if it is an array class, and otherwise nothing. + */ override def toString() = (if (prefix.isEmpty) "" else prefix.get.toString+"#") + (if (runtimeClass.isArray) "Array" else runtimeClass.getName) + argString } + /** Returns the manifest for the array type `Array[T]`, given the manifest `arg` for the element type `T`. + * + * @tparam T the element type of the array type described by the result + * @param arg the manifest for the element type + * @return the `arrayManifest` obtained by casting `arg` to `Manifest[T]`; the cast is unchecked, + * so `arg` is assumed to describe `T` + */ def arrayType[T](arg: Manifest[?]): Manifest[Array[T]] = arg.asInstanceOf[Manifest[T]].arrayManifest @SerialVersionUID(1L) private class AbstractTypeManifest[T](prefix: Manifest[?], name: String, upperBound: Predef.Class[?], args: scala.collection.Seq[Manifest[?]]) extends Manifest[T] { + /** Returns the runtime class of the abstract type's upper bound, which serves as its erasure. */ def runtimeClass = upperBound override val typeArguments = args.toList + /** Returns the abstract type rendered as `prefix#name`, followed by `argString`: the type arguments + * if there are any, otherwise the bracketed component type of the upper bound if the upper bound + * is an array class, and otherwise nothing. + */ override def toString() = prefix.toString+"#"+name+argString } @@ -496,7 +697,11 @@ object ManifestFactory { @SerialVersionUID(1L) private class WildcardManifest[T](lowerBound: Manifest[?], upperBound: Manifest[?]) extends Manifest[T] { + /** Returns the runtime class of the wildcard's upper bound, which serves as its erasure. */ def runtimeClass = upperBound.runtimeClass + /** Returns the wildcard rendered as `_`, followed by ` >: ` and the lower bound and by ` <: ` + * and the upper bound, each bound omitted when it is the `Nothing` manifest. + */ override def toString() = "_" + (if (lowerBound eq Nothing) "" else " >: "+lowerBound) + @@ -516,7 +721,9 @@ object ManifestFactory { private class IntersectionTypeManifest[T](parents: Array[Manifest[?]]) extends Manifest[T] { // We use an `Array` instead of a `Seq` for `parents` to avoid cyclic dependencies during deserialization // which can cause serialization proxies to leak and cause a ClassCastException. + /** Returns the runtime class of the first type in the intersection, which serves as its erasure. */ def runtimeClass = parents(0).runtimeClass + /** Returns the types in the intersection rendered as `parents_0 with ... with parents_n`. */ override def toString() = parents.mkString(" with ") } diff --git a/library/src/scala/reflect/NoManifest.scala b/library/src/scala/reflect/NoManifest.scala index 278449585760..0208468136b0 100644 --- a/library/src/scala/reflect/NoManifest.scala +++ b/library/src/scala/reflect/NoManifest.scala @@ -20,5 +20,6 @@ import scala.language.`2.13` // TODO undeprecated until Scala reflection becomes non-experimental // @deprecated("This notion doesn't have a corresponding concept in 2.10, because scala.reflect.runtime.universe.TypeTag can capture arbitrary types. Use type tags instead of manifests, and there will be no need in opt manifests.", "2.10.0") object NoManifest extends OptManifest[Nothing] with Serializable { + /** Returns ``, indicating that no type information is available. */ override def toString() = "" } diff --git a/library/src/scala/reflect/package.scala b/library/src/scala/reflect/package.scala index 5db8021b2470..7f6d8f0ae21e 100644 --- a/library/src/scala/reflect/package.scala +++ b/library/src/scala/reflect/package.scala @@ -50,6 +50,11 @@ package object reflect { @deprecated("use scala.reflect.ClassTag instead", "2.10.0") val ClassManifest = ClassManifestFactory + /** Returns the `ClassTag` available in implicit scope for type `T`. + * + * @tparam T the type whose erased class the summoned tag describes + * @param ctag the implicitly resolved `ClassTag[T]`, returned unchanged + */ def classTag[T](implicit ctag: ClassTag[T]) = ctag /** Makes a java reflection object accessible, if it is not already diff --git a/library/src/scala/specialized.scala b/library/src/scala/specialized.scala index d02ddcf06191..b20a41326c93 100644 --- a/library/src/scala/specialized.scala +++ b/library/src/scala/specialized.scala @@ -33,6 +33,12 @@ import Specializable._ // class tspecialized[T](group: Group[T]) extends scala.annotation.StaticAnnotation { final class specialized(group: SpecializedGroup) extends scala.annotation.StaticAnnotation { + /** Creates an annotation that specializes for an explicitly listed set of types. + * + * @param types the companion values of the types to specialize for, as written in + * `@specialized(Int, Double, Boolean)` + */ def this(types: Specializable*) = this(new Group(types.toList)) + /** Creates an annotation that specializes for [[Specializable.Primitives]], the group of all primitive types. */ def this() = this(Primitives) } diff --git a/library/src/scala/throws.scala b/library/src/scala/throws.scala index dc8a692ec677..73690d4023b2 100644 --- a/library/src/scala/throws.scala +++ b/library/src/scala/throws.scala @@ -28,5 +28,12 @@ import scala.language.`2.13` * @param cause a description of the condition under which the exception is thrown */ final class throws[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation { + /** Creates an annotation with an empty `cause` description. This supports the + * legacy `@throws(classOf[T])` form, in which the exception is given as a class + * value instead of a type argument. + * + * @param clazz the class value identifying the exception that the annotated + * method may throw + */ def this(clazz: Class[T]) = this("") } diff --git a/library/src/scala/transient.scala b/library/src/scala/transient.scala index 3ca34fba9f69..77ccd39bb7b2 100644 --- a/library/src/scala/transient.scala +++ b/library/src/scala/transient.scala @@ -16,4 +16,5 @@ import scala.language.`2.13` import scala.annotation.meta._ @field +/** Marks a field as transient, so that it is not included in the serialized form of its enclosing instance. */ final class transient extends scala.annotation.StaticAnnotation diff --git a/library/src/scala/typeConstraints.scala b/library/src/scala/typeConstraints.scala index 5308271d8ac5..96f6f72b26b9 100644 --- a/library/src/scala/typeConstraints.scala +++ b/library/src/scala/typeConstraints.scala @@ -116,6 +116,14 @@ sealed abstract class <:<[-From, +To] extends (From => To) with Serializable { substituteCo[Id](f) } + /** Composes this coercion with the function `r`, widening `r`'s result from `From` to `To`. + * + * Since the coercion is the identity function, the composition behaves exactly like `r`. + * + * @tparam C the argument type of `r` + * @param r a function producing a `From` + * @return `r`, $sameDiff + */ override def compose[C](r: C => From): C => To = { type G[+T] = C => T substituteCo[G](r) @@ -129,6 +137,14 @@ sealed abstract class <:<[-From, +To] extends (From => To) with Serializable { type G[+T] = C <:< T substituteCo[G](r) } + /** Composes this coercion with the function `r`, narrowing `r`'s argument from `To` to `From`. + * + * Since the coercion is the identity function, the composition behaves exactly like `r`. + * + * @tparam C the result type of `r` + * @param r a function accepting a `To` + * @return `r`, $sameDiff + */ override def andThen[C](r: To => C): From => C = { type G[-T] = T => C substituteContra[G](r) @@ -229,12 +245,43 @@ object <:< { // Most of the notes on <:< above apply to =:= as well @implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.") sealed abstract class =:=[From, To] extends (From <:< To) with Serializable { + /** Substitutes `From` for `To` and `To` for `From` in the type `F[To, From]`, where `F` is $contraCo. + * Essentially swaps `To` and `From` in `ftf`'s type. + * + * Equivalent in power to each of [[substituteCo]] and [[substituteContra]]. + * + * $isProof + * + * @tparam F $contraCo + * @param ftf a value whose type mentions `To` in the first argument position and `From` in the second + * @return `ftf`, but with a (potentially) different type + */ override def substituteBoth[F[_, _]](ftf: F[To, From]): F[From, To] + /** Substitutes the `From` in the type `F[From]`, where `F` is $coCon, for `To`. + * + * Equivalent in power to each of [[substituteBoth]] and [[substituteContra]]. + * + * $isProof + * + * @tparam F $coCon + * @param ff a value of type `F[From]` + * @return `ff`, but with a (potentially) different type + */ override def substituteCo[F[_]](ff: F[From]): F[To] = { type G[_, T] = F[T] substituteBoth[G](ff) } // = substituteContra[({type G[T] = F[T] => F[To]})#G](identity)(ff) + /** Substitutes the `To` in the type `F[To]`, where `F` is $contraCon, for `From`. + * + * Equivalent in power to each of [[substituteBoth]] and [[substituteCo]]. + * + * $isProof + * + * @tparam F $contraCon + * @param ft a value of type `F[To]` + * @return `ft`, but with a (potentially) different type + */ override def substituteContra[F[_]](ft: F[To]): F[From] = { type G[T, _] = F[T] substituteBoth[G](ft) @@ -271,6 +318,11 @@ sealed abstract class =:=[From, To] extends (From <:< To) with Serializable { substituteContra[G](r) } + /** Lifts this evidence over the type constructor `F`. + * + * @tparam F $coCon to lift the evidence over + * @return evidence that `F[From]` and `F[To]` are equal + */ override def liftCo[F[_]]: F[From] =:= F[To] = { type G[T] = F[T] =:= F[To] substituteContra[G](implicitly[G[To]]) diff --git a/library/src/scala/volatile.scala b/library/src/scala/volatile.scala index 75b615ee6c7d..475d1ce6d66a 100644 --- a/library/src/scala/volatile.scala +++ b/library/src/scala/volatile.scala @@ -16,4 +16,5 @@ import scala.language.`2.13` import scala.annotation.meta._ @field +/** Marks a mutable field as volatile, giving reads and writes of the field the JVM's volatile memory-visibility and ordering guarantees. */ final class volatile extends scala.annotation.StaticAnnotation