Skip to content

Commit 74a56f9

Browse files
committed
Correct the added Scaladoc where it did not match the implementation
Adjudicated from an independent review of this branch. Comment-only. - LazyVals.LazyValControlState was described as a state held only while a lazy val is unbound. NullValue is the permanent sentinel for a lazy val that evaluated to null, so it outlives the computation. - ModuleSerializationProxy said the resolved instance is cached per class. It is, through ClassValue, but the ClassValueCompat fallback recomputes on every access where java.lang.ClassValue is unavailable. - ArrayCharSequence.charAt can also throw for a slice whose bounds fall outside the array, since the constructor does not validate them, and toString takes its count from the declared bounds, so a negative start shifts the window rather than clipping it. - ScalaRunTime.isArray described atLevel as a minimum; below 1 it never holds. stringOf's maxElements renders nothing at all below 1. - StructuralCallSite.find can throw NoSuchMethodException from the reflective lookup a mega-morphic cache performs, and add records nothing and leaves the cache alone once the site is mega-morphic. - IntegralProxy.until and to documented only the zero-step failure; the same deferred length computation also throws for a range of more than Int.MaxValue elements. - Tuples.productToArray is called for arities 1 to 22; the empty tuple is handled separately with Array.emptyObjectArray. - VarArgsBuilder.result returns a sequence over the whole fixed-length array rather than only the elements added, and its n parameter is an allocation length that nothing enforces. Twenty-nine @return tags that merely restated a summary already beginning with "Returns" or "Creates" are removed, across TupledFunctions, TupleXXL, TupleMirror and the two Zipped iterables. The project's convention is to drop a @return in exactly that case. Declined: documenting, on each scala.runtime.java8 specialisation bridge, that unboxing null yields a zero and that a wrongly typed argument throws ClassCastException. Both are true of BoxesRunTime generally, these bridges are compiler-facing rather than called directly, and there are hundreds of them.
1 parent ce44ce8 commit 74a56f9

13 files changed

Lines changed: 62 additions & 62 deletions

library/src/scala/runtime/ArrayCharSequence.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends
4343
*
4444
* @param index the index of the character to return, from `0` to `length - 1`
4545
* @throws ArrayIndexOutOfBoundsException if `index` is negative or not less
46-
* than `length` (the exception message reports the bounds of the
47-
* underlying array, not of this sequence)
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)
4850
*/
4951
def charAt(index: Int): Char = {
5052
if (0 <= index && index < length)
@@ -78,8 +80,10 @@ final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends
7880
*
7981
* The bounds are clamped to the underlying array before copying: a
8082
* negative `start` is treated as `0` and the end is capped at the array's
81-
* length, so a sequence constructed with out-of-range bounds yields its
82-
* in-range characters (or the empty string) rather than throwing.
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.
8387
*/
8488
override def toString() = {
8589
val start = math.max(this.start, 0)

library/src/scala/runtime/LazyVals.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ object LazyVals {
4848
/* ------------- Start of public API ------------- */
4949

5050
// This trait extends Serializable to fix #16806 that caused a race condition
51-
/** A control state stored in the field of a lazy val while the val is not
52-
* yet bound to its computed value: [[Evaluating]], a [[Waiting]] latch,
53-
* or [[NullValue]].
51+
/** A state stored in the field of a lazy val other than an ordinary computed value:
52+
* [[Evaluating]] or a [[Waiting]] latch while the val is not yet bound, and
53+
* [[NullValue]], which is the permanent sentinel for a lazy val that evaluated to
54+
* `null`.
5455
*
5556
* Extends `Serializable` so that an object can be serialized while one of
5657
* its lazy vals holds a control state (issue #16806).

library/src/scala/runtime/ModuleSerializationProxy.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ private[runtime] object ModuleSerializationProxy {
4444
* method that serializes an instance of this class instead of the object
4545
* itself. On deserialization, `readResolve` replaces the proxy with the
4646
* object's unique instance, obtained reflectively from the `MODULE$` field
47-
* of `moduleClass` (and cached per class), so deserialization yields the
48-
* singleton rather than a fresh copy.
47+
* of `moduleClass`, so deserialization yields the singleton rather than a
48+
* fresh copy. The lookup is cached per class where `java.lang.ClassValue` is
49+
* available, and repeated on each deserialization where it is not.
4950
*
5051
* @param moduleClass the class of the object whose instance the proxy
5152
* resolves to

library/src/scala/runtime/ScalaNumberProxy.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ trait IntegralProxy[T] extends Any with ScalaWholeNumberProxy[T] with RangedProx
106106
* @param step the increment between consecutive elements; may be negative
107107
* @return an exclusive [[scala.collection.immutable.NumericRange]] from this
108108
* value until `end` with the given step
109-
* @throws IllegalArgumentException if `step` is zero (thrown when the
110-
* range's length is first computed)
109+
* @throws IllegalArgumentException if `step` is zero, or if the range has more
110+
* than `Int.MaxValue` elements; both are raised when the range's length
111+
* is first computed, not when it is constructed
111112
*/
112113
def until(end: T, step: T): NumericRange.Exclusive[T] = NumericRange(self, end, step)
113114
/** Returns a range from the wrapped value up to and including `end`, in
@@ -125,8 +126,9 @@ trait IntegralProxy[T] extends Any with ScalaWholeNumberProxy[T] with RangedProx
125126
* @param step the increment between consecutive elements; may be negative
126127
* @return an inclusive [[scala.collection.immutable.NumericRange]] from this
127128
* value to `end` with the given step
128-
* @throws IllegalArgumentException if `step` is zero (thrown when the
129-
* range's length is first computed)
129+
* @throws IllegalArgumentException if `step` is zero, or if the range has more
130+
* than `Int.MaxValue` elements; both are raised when the range's length
131+
* is first computed, not when it is constructed
130132
*/
131133
def to(end: T, step: T): NumericRange.Inclusive[T] = NumericRange.inclusive(self, end, step)
132134
}

library/src/scala/runtime/ScalaRunTime.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ object ScalaRunTime {
3131
/** Tests whether `x` is an array with at least `atLevel` dimensions.
3232
*
3333
* @param x the value to test; `null` yields `false`
34-
* @param atLevel the minimum number of array dimensions required; the default, 1, accepts any array
34+
* @param atLevel the number of array dimensions required; a value below 1 never
35+
* holds, since the check descends one component type per level and
36+
* fails once it reaches a non-array; the default, 1, accepts any array
3537
* @return `true` if `x` is a non-null array of at least `atLevel` dimensions, `false` otherwise
3638
*/
3739
def isArray(x: Any, atLevel: Int = 1): Boolean =
@@ -289,7 +291,8 @@ object ScalaRunTime {
289291
* back to `String.valueOf(arg)`.
290292
*
291293
* @param arg the value to stringify
292-
* @param maxElements the maximum number of elements rendered per collection or array
294+
* @param maxElements the maximum number of elements rendered per collection or array;
295+
* a value below 1 renders none of them
293296
*/
294297
def stringOf(arg: Any, maxElements: Int): String = {
295298
def packageOf(x: AnyRef) = x.getClass.getPackage match {

library/src/scala/runtime/StructuralCallSite.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ final class StructuralCallSite private (callType: MethodType) {
5252
* per-receiver entries; see [[MethodCache.find]].
5353
*
5454
* @param receiver the runtime `Class` of the receiver object
55+
* @throws NoSuchMethodException from the reflective lookup a mega-morphic cache
56+
* performs, in place of returning `null`
5557
*/
5658
def find(receiver: Class[?]): Method | Null = get.find(receiver)
5759

5860
/** Records that `m` is the method to call for receiver class `receiver`,
59-
* replacing this call site's cache with the extended one, and returns
60-
* `m`.
61+
* replacing this call site's cache with the extended one, and returns `m`.
62+
*
63+
* Once the cache has turned mega-morphic it records nothing per receiver and
64+
* returns itself, so the call site's cache is then left as it was.
6165
*
6266
* @param receiver the runtime `Class` of the receiver object
6367
* @param m the method resolved for `receiver`

library/src/scala/runtime/Tuple2Zipped.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ object ZippedIterable2 {
4242
* @tparam El1 the first element type of each pair
4343
* @tparam El2 the second element type of each pair
4444
* @param zz the zipped iterable to convert
45-
* @return an `Iterable` producing the element pairs of `zz`
4645
*/
4746
implicit def zippedIterable2ToIterable[El1, El2](zz: ZippedIterable2[El1, El2]): Iterable[(El1, El2)] = {
4847
new scala.collection.AbstractIterable[(El1, El2)] {

library/src/scala/runtime/Tuple3Zipped.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ object ZippedIterable3 {
4141
* @tparam El2 the second element type of each triple
4242
* @tparam El3 the third element type of each triple
4343
* @param zz the zipped iterable to convert
44-
* @return an `Iterable` producing the element triples of `zz`
4544
*/
4645
implicit def zippedIterable3ToIterable[El1, El2, El3](zz: ZippedIterable3[El1, El2, El3]): Iterable[(El1, El2, El3)] = {
4746
new scala.collection.AbstractIterable[(El1, El2, El3)] {

library/src/scala/runtime/TupleMirror.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ final class TupleMirror(arity: Int) extends scala.deriving.Mirror.Product with S
1919
* than copied.
2020
*
2121
* @param product the product supplying the elements of the resulting tuple
22-
* @return a tuple containing the elements of `product`, in order
2322
* @throws IllegalArgumentException if `product.productArity` differs from the
2423
* arity this mirror was constructed with
2524
*/

library/src/scala/runtime/TupleXXL.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ final class TupleXXL private (es: IArray[Object]) extends Product {
4141
/** Returns whether `that` can be compared for equality against this tuple.
4242
*
4343
* @param that the value to test
44-
* @return `true` if `that` is a `TupleXXL` with the same arity as this tuple, `false` otherwise
4544
*/
4645
override def canEqual(that: Any): Boolean = that match {
4746
case that: TupleXXL => that.productArity == this.productArity
@@ -56,7 +55,6 @@ final class TupleXXL private (es: IArray[Object]) extends Product {
5655
* a `TupleXXL` is never equal to this tuple.
5756
*
5857
* @param that the value to compare against
59-
* @return `true` if `that` is a `TupleXXL` equal to this tuple, `false` otherwise
6058
*/
6159
override def equals(that: Any): Boolean = that match {
6260
case that: TupleXXL =>
@@ -95,19 +93,16 @@ object TupleXXL {
9593
* The iterator is fully consumed into a fresh array.
9694
*
9795
* @param elems the iterator supplying the elements; must produce more than 22 values (asserted)
98-
* @return a `TupleXXL` with the produced values as its elements
9996
*/
10097
def fromIterator(elems: Iterator[Any]): TupleXXL = new TupleXXL(elems.map(_.asInstanceOf[Object]).toArray.asInstanceOf[IArray[Object]]) // TODO use Iterator.toIArray
10198
/** Creates a `TupleXXL` backed directly by `elems`; the array is not copied.
10299
*
103100
* @param elems the immutable array to use as the tuple's backing storage; must have more than 22 elements (asserted)
104-
* @return a `TupleXXL` whose elements are those of `elems`
105101
*/
106102
def fromIArray(elems: IArray[Object]): TupleXXL = new TupleXXL(elems)
107103
/** Creates a `TupleXXL` with the given elements.
108104
*
109105
* @param elems the elements of the tuple; more than 22 must be supplied (asserted)
110-
* @return a `TupleXXL` with the given elements, in order
111106
*/
112107
def apply(elems: Any*): TupleXXL = new TupleXXL(IArray(elems.asInstanceOf[Seq[AnyRef]]*))
113108
/** Extracts the elements of a `TupleXXL`, enabling `case TupleXXL(xs*)` patterns.

0 commit comments

Comments
 (0)