Skip to content

Commit 1ff6ff3

Browse files
committed
Add Scaladoc for undocumented scala.runtime APIs
Documents declarations that had no doc comment at all across scala.runtime: the boxed and unboxed value-class runtime support, the array and tuple helpers, and the 87 files of scala.runtime.java8 that back Java function interop. Comment-only: no declaration, body, import, annotation or blank line is touched.
1 parent 279209e commit 1ff6ff3

116 files changed

Lines changed: 3799 additions & 7 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

library/src/scala/runtime/ArrayCharSequence.scala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,55 @@ import scala.language.`2.13`
1717

1818
// Still need this one since the implicit class ArrayCharSequence only converts
1919
// a single argument.
20+
/** A `CharSequence` view of a slice of an `Array[Char]`.
21+
*
22+
* The sequence consists of the characters of `xs` from index `start` until
23+
* `end`. Characters are read from the array on demand, so later writes to
24+
* the array are visible through this sequence. The bounds are not validated
25+
* on construction: `end <= start` yields an empty sequence, and out-of-range
26+
* bounds only surface when characters are accessed.
27+
*
28+
* @param xs the underlying character array
29+
* @param start the index in `xs` of the first character of the sequence
30+
* @param end the index in `xs` one past the last character of the sequence
31+
*/
2032
final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends CharSequence {
2133
// yikes
2234
// java.lang.VerifyError: (class: scala/runtime/ArrayCharSequence, method: <init> signature: ([C)V)
2335
// Constructor must call super() or this()
2436
//
2537
// def this(xs: Array[Char]) = this(xs, 0, xs.length)
2638

39+
/** Returns the number of characters in this sequence: `end - start`, or `0` if `end <= start`. */
2740
def length: Int = math.max(0, end - start)
41+
/** Returns the character at the given index of this sequence, that is, the
42+
* character at index `start + index` of the underlying array.
43+
*
44+
* @param index the index of the character to return, from `0` to `length - 1`
45+
* @throws ArrayIndexOutOfBoundsException if `index` is negative or not less
46+
* than `length`, or if the slice this sequence was constructed with
47+
* falls outside the array, since those bounds are not validated (the
48+
* exception message reports the bounds of the underlying array, not
49+
* of this sequence)
50+
*/
2851
def charAt(index: Int): Char = {
2952
if (0 <= index && index < length)
3053
xs(start + index)
3154
else throw new ArrayIndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${xs.length - 1})")
3255
}
56+
/** Returns a new `ArrayCharSequence` over the characters of this sequence
57+
* from index `start0` until `end0`.
58+
*
59+
* The result is a view over the same underlying array; no characters are
60+
* copied.
61+
*
62+
* @param start0 the index in this sequence of the first character of the subsequence
63+
* @param end0 the index in this sequence one past the last character of the subsequence
64+
* @return the subsequence view; empty if `end0 <= start0` (no exception is
65+
* thrown for an inverted range, unlike the `CharSequence` contract)
66+
* @throws ArrayIndexOutOfBoundsException if `start0` is negative or `end0`
67+
* is greater than `length`
68+
*/
3369
def subSequence(start0: Int, end0: Int): CharSequence = {
3470
if (start0 < 0) throw new ArrayIndexOutOfBoundsException(s"$start0 is out of bounds (min 0, max ${length -1})")
3571
else if (end0 > length) throw new ArrayIndexOutOfBoundsException(s"$end0 is out of bounds (min 0, max ${xs.length -1})")
@@ -40,6 +76,15 @@ final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends
4076
new ArrayCharSequence(xs, start1, start1 + newlen)
4177
}
4278
}
79+
/** Returns the characters of this sequence as a `String`.
80+
*
81+
* The bounds are clamped to the underlying array before copying: a
82+
* negative `start` is treated as `0` and the end is capped at the array's
83+
* length, so a sequence constructed with out-of-range bounds yields
84+
* characters rather than throwing. The count is taken from the declared
85+
* bounds, so a negative `start` shifts the window: `start = -2, end = 5`
86+
* copies seven characters from index `0`, not the five in range.
87+
*/
4388
override def toString() = {
4489
val start = math.max(this.start, 0)
4590
val end = math.min(xs.length, start + length)

library/src/scala/runtime/EnumValue.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,27 @@ package scala.runtime
33
import language.experimental.captureChecking
44

55
transparent trait EnumValue extends Product, Serializable:
6+
/** Returns `true` if `that` is the same object as this one, by reference.
7+
*
8+
* Each simple enum case is a singleton, so it can only compare equal to
9+
* itself.
10+
*
11+
* @param that the value to compare with this enum value
12+
*/
613
override def canEqual(that: Any) = this eq that.asInstanceOf[AnyRef]
14+
/** Returns `0`: a simple enum case has no case fields. */
715
override def productArity: Int = 0
16+
/** Always throws: a simple enum case has no elements.
17+
*
18+
* @param n the index of the requested element; no index is valid
19+
* @throws IndexOutOfBoundsException always, with `n` as its message
20+
*/
821
override def productElement(n: Int): Any =
922
throw IndexOutOfBoundsException(n.toString)
23+
/** Always throws: a simple enum case has no elements.
24+
*
25+
* @param n the index of the requested element name; no index is valid
26+
* @throws IndexOutOfBoundsException always, with `n` as its message
27+
*/
1028
override def productElementName(n: Int): String =
1129
throw IndexOutOfBoundsException(n.toString)

library/src/scala/runtime/FunctionXXL.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ trait FunctionXXL {
1212
*/
1313
def apply(xs: IArray[Object]): Object
1414

15+
/** Returns the string `"<functionXXL>"`, mirroring the `"<functionN>"` rendering of the `Function0` to `Function22` traits. */
1516
override def toString() = "<functionXXL>"
1617
}

library/src/scala/runtime/LambdaDeserialize.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ import scala.collection.immutable
2121

2222
import scala.language.`2.13`
2323

24+
/** The per-class state behind the synthetic `$deserializeLambda$` method of
25+
* a class hosting lambdas: the class's lookup, a map from implementation
26+
* method name-and-descriptor keys to their method handles, and a cache of
27+
* deserialization factories keyed the same way.
28+
*
29+
* Created by `LambdaDeserialize.bootstrap`, which the JVM invokes via
30+
* `invokedynamic`.
31+
*/
2432
final class LambdaDeserialize private (lookup: MethodHandles.Lookup, targetMethods: Array[MethodHandle]) {
2533
private val targetMethodMap: util.HashMap[String, MethodHandle] = new util.HashMap[String, MethodHandle](targetMethods.length)
2634

@@ -32,16 +40,47 @@ final class LambdaDeserialize private (lookup: MethodHandles.Lookup, targetMetho
3240

3341
private val cache = new util.HashMap[String, MethodHandle]
3442

43+
/** Returns an instance of the functional interface described by
44+
* `serialized`, delegating to [[LambdaDeserializer.deserializeLambda]]
45+
* with this instance's lookup, factory cache, and target method map.
46+
*
47+
* @param serialized the serialized form of the lambda to deserialize
48+
* @throws IllegalArgumentException if the implementation method named by
49+
* `serialized` is not among this instance's target methods
50+
*/
3551
def deserializeLambda(serialized: SerializedLambda): AnyRef = LambdaDeserializer.deserializeLambda(lookup, cache, targetMethodMap, serialized)
3652
}
3753

3854
object LambdaDeserialize {
55+
/** Bootstrap method that the JVM invokes, via the `invokedynamic`
56+
* instruction in the synthetic `$deserializeLambda$` method of a class
57+
* hosting lambdas, to link that method's call site.
58+
*
59+
* @param lookup the lookup of the class hosting the lambdas
60+
* @param invokedName never used
61+
* @param invokedType the type the call site's target is adapted to,
62+
* taking a `SerializedLambda` and returning the
63+
* deserialized object
64+
* @param targetMethods handles for the lambda implementation methods of
65+
* the class, from which deserialization requests
66+
* are resolved by name and descriptor
67+
* @return a `ConstantCallSite` whose target is `deserializeLambda` bound
68+
* to a `LambdaDeserialize` built over `lookup` and
69+
* `targetMethods`
70+
*/
3971
@varargs @throws[Throwable]
4072
def bootstrap(lookup: MethodHandles.Lookup, @unused invokedName: String, invokedType: MethodType, targetMethods: MethodHandle*): CallSite = {
4173
val targetMethodsArray = targetMethods.asInstanceOf[immutable.ArraySeq[?]].unsafeArray.asInstanceOf[Array[MethodHandle]]
4274
val exact = MethodHandleConstants.LAMBDA_DESERIALIZE_DESERIALIZE_LAMBDA.bindTo(new LambdaDeserialize(lookup, targetMethodsArray)).asType(invokedType)
4375
new ConstantCallSite(exact)
4476
}
4577

78+
/** Returns the key under which an implementation method is stored in the
79+
* target method map and factory cache: `name` concatenated with
80+
* `descriptor`.
81+
*
82+
* @param name the name of the implementation method
83+
* @param descriptor the JVM method descriptor of its signature
84+
*/
4685
def nameAndDescriptorKey(name: String, descriptor: String): String = name + descriptor
4786
}

library/src/scala/runtime/LambdaDeserializer.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ object LambdaDeserializer {
5151
else result
5252
}
5353

54+
/** Deserializes a lambda like [[deserializeLambda]], but returns `null`
55+
* instead of throwing when the implementation method named by
56+
* `serialized` has no entry in `targetMethodMap`.
57+
*
58+
* @param lookup The factory for method handles. Must have access to the implementation method, the
59+
* functional interface class, and `java.io.Serializable`.
60+
* @param cache A cache used to avoid spinning up a class for each deserialization of a given lambda. May be `null`
61+
* @param targetMethodMap a mapping from lambda implementation method name and signature keys (as produced by
62+
* `LambdaDeserialize.nameAndDescriptorKey`) to their `MethodHandle`s, used to look up the
63+
* implementation method during deserialization. Must not be `null`
64+
* @param serialized The lambda to deserialize. Note that this is typically created by the `readResolve`
65+
* member of the anonymous class created by `LambdaMetaFactory`.
66+
* @return an instance of the functional interface, or `null` if the implementation
67+
* method is not found in `targetMethodMap`
68+
*/
5469
def deserializeLambdaOrNull(lookup: MethodHandles.Lookup, cache: java.util.Map[String, MethodHandle],
5570
targetMethodMap: java.util.Map[String, MethodHandle], serialized: SerializedLambda): AnyRef | Null = {
5671
assert(targetMethodMap != null)

0 commit comments

Comments
 (0)