Skip to content

Commit ec70a23

Browse files
committed
Make Stepper capture checked
1 parent 37b41b6 commit ec70a23

File tree

2 files changed

+140
-15
lines changed

2 files changed

+140
-15
lines changed

tests/pos-special/stdlib/collection/Stepper.scala

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package scala.collection
1515
import java.util.function.{Consumer, DoubleConsumer, IntConsumer, LongConsumer}
1616
import java.util.{PrimitiveIterator, Spliterator, Iterator => JIterator}
1717
import java.{lang => jl}
18+
import language.experimental.captureChecking
1819

1920
import scala.collection.Stepper.EfficientSplit
2021

@@ -38,6 +39,8 @@ import scala.collection.Stepper.EfficientSplit
3839
* @tparam A the element type of the Stepper
3940
*/
4041
trait Stepper[@specialized(Double, Int, Long) +A] {
42+
this: Stepper[A]^ =>
43+
4144
/** Check if there's an element available. */
4245
def hasStep: Boolean
4346

@@ -183,9 +186,11 @@ object Stepper {
183186

184187
/** A Stepper for arbitrary element types. See [[Stepper]]. */
185188
trait AnyStepper[+A] extends Stepper[A] {
189+
this: AnyStepper[A]^ =>
190+
186191
def trySplit(): AnyStepper[A]
187192

188-
def spliterator[B >: A]: Spliterator[B] = new AnyStepper.AnyStepperSpliterator(this)
193+
def spliterator[B >: A]: Spliterator[B]^{this} = new AnyStepper.AnyStepperSpliterator(this)
189194

190195
def javaIterator[B >: A]: JIterator[B] = new JIterator[B] {
191196
def hasNext: Boolean = hasStep
@@ -194,10 +199,10 @@ trait AnyStepper[+A] extends Stepper[A] {
194199
}
195200

196201
object AnyStepper {
197-
class AnyStepperSpliterator[A](s: AnyStepper[A]) extends Spliterator[A] {
202+
class AnyStepperSpliterator[A](s: AnyStepper[A]^) extends Spliterator[A] {
198203
def tryAdvance(c: Consumer[_ >: A]): Boolean =
199204
if (s.hasStep) { c.accept(s.nextStep()); true } else false
200-
def trySplit(): Spliterator[A] = {
205+
def trySplit(): Spliterator[A]^{this} = {
201206
val sp = s.trySplit()
202207
if (sp == null) null else sp.spliterator
203208
}
@@ -253,17 +258,19 @@ object AnyStepper {
253258

254259
/** A Stepper for Ints. See [[Stepper]]. */
255260
trait IntStepper extends Stepper[Int] {
261+
this: IntStepper^ =>
262+
256263
def trySplit(): IntStepper
257264

258-
def spliterator[B >: Int]: Spliterator.OfInt = new IntStepper.IntStepperSpliterator(this)
265+
def spliterator[B >: Int]: Spliterator.OfInt^{this} = new IntStepper.IntStepperSpliterator(this)
259266

260267
def javaIterator[B >: Int]: PrimitiveIterator.OfInt = new PrimitiveIterator.OfInt {
261268
def hasNext: Boolean = hasStep
262269
def nextInt(): Int = nextStep()
263270
}
264271
}
265272
object IntStepper {
266-
class IntStepperSpliterator(s: IntStepper) extends Spliterator.OfInt {
273+
class IntStepperSpliterator(s: IntStepper^) extends Spliterator.OfInt {
267274
def tryAdvance(c: IntConsumer): Boolean =
268275
if (s.hasStep) { c.accept(s.nextStep()); true } else false
269276
// Override for efficiency: don't wrap the function and call the `tryAdvance` overload
@@ -272,7 +279,7 @@ object IntStepper {
272279
case _ => if (s.hasStep) { c.accept(jl.Integer.valueOf(s.nextStep())); true } else false
273280
}
274281
// override required for dotty#6152
275-
override def trySplit(): Spliterator.OfInt = {
282+
override def trySplit(): Spliterator.OfInt^{this} = {
276283
val sp = s.trySplit()
277284
if (sp == null) null else sp.spliterator
278285
}
@@ -291,18 +298,19 @@ object IntStepper {
291298

292299
/** A Stepper for Doubles. See [[Stepper]]. */
293300
trait DoubleStepper extends Stepper[Double] {
301+
this: DoubleStepper^ =>
294302
def trySplit(): DoubleStepper
295303

296-
def spliterator[B >: Double]: Spliterator.OfDouble = new DoubleStepper.DoubleStepperSpliterator(this)
304+
def spliterator[B >: Double]: Spliterator.OfDouble^{this} = new DoubleStepper.DoubleStepperSpliterator(this)
297305

298-
def javaIterator[B >: Double]: PrimitiveIterator.OfDouble = new PrimitiveIterator.OfDouble {
306+
def javaIterator[B >: Double]: PrimitiveIterator.OfDouble^{this} = new PrimitiveIterator.OfDouble {
299307
def hasNext: Boolean = hasStep
300308
def nextDouble(): Double = nextStep()
301309
}
302310
}
303311

304312
object DoubleStepper {
305-
class DoubleStepperSpliterator(s: DoubleStepper) extends Spliterator.OfDouble {
313+
class DoubleStepperSpliterator(s: DoubleStepper^) extends Spliterator.OfDouble {
306314
def tryAdvance(c: DoubleConsumer): Boolean =
307315
if (s.hasStep) { c.accept(s.nextStep()); true } else false
308316
// Override for efficiency: don't wrap the function and call the `tryAdvance` overload
@@ -311,7 +319,7 @@ object DoubleStepper {
311319
case _ => if (s.hasStep) { c.accept(java.lang.Double.valueOf(s.nextStep())); true } else false
312320
}
313321
// override required for dotty#6152
314-
override def trySplit(): Spliterator.OfDouble = {
322+
override def trySplit(): Spliterator.OfDouble^{this} = {
315323
val sp = s.trySplit()
316324
if (sp == null) null else sp.spliterator
317325
}
@@ -330,18 +338,20 @@ object DoubleStepper {
330338

331339
/** A Stepper for Longs. See [[Stepper]]. */
332340
trait LongStepper extends Stepper[Long] {
333-
def trySplit(): LongStepper
341+
this: LongStepper^ =>
342+
343+
def trySplit(): LongStepper^{this}
334344

335-
def spliterator[B >: Long]: Spliterator.OfLong = new LongStepper.LongStepperSpliterator(this)
345+
def spliterator[B >: Long]: Spliterator.OfLong^{this} = new LongStepper.LongStepperSpliterator(this)
336346

337-
def javaIterator[B >: Long]: PrimitiveIterator.OfLong = new PrimitiveIterator.OfLong {
347+
def javaIterator[B >: Long]: PrimitiveIterator.OfLong^{this} = new PrimitiveIterator.OfLong {
338348
def hasNext: Boolean = hasStep
339349
def nextLong(): Long = nextStep()
340350
}
341351
}
342352

343353
object LongStepper {
344-
class LongStepperSpliterator(s: LongStepper) extends Spliterator.OfLong {
354+
class LongStepperSpliterator(s: LongStepper^) extends Spliterator.OfLong {
345355
def tryAdvance(c: LongConsumer): Boolean =
346356
if (s.hasStep) { c.accept(s.nextStep()); true } else false
347357
// Override for efficiency: don't wrap the function and call the `tryAdvance` overload
@@ -350,7 +360,7 @@ object LongStepper {
350360
case _ => if (s.hasStep) { c.accept(java.lang.Long.valueOf(s.nextStep())); true } else false
351361
}
352362
// override required for dotty#6152
353-
override def trySplit(): Spliterator.OfLong = {
363+
override def trySplit(): Spliterator.OfLong^{this} = {
354364
val sp = s.trySplit()
355365
if (sp == null) null else sp.spliterator
356366
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection
14+
15+
import java.{lang => jl}
16+
17+
import language.experimental.captureChecking
18+
import scala.collection.Stepper.EfficientSplit
19+
20+
/** An implicit StepperShape instance is used in the [[IterableOnce.stepper]] to return a possibly
21+
* specialized Stepper `S` according to the element type `T`.
22+
*/
23+
sealed trait StepperShape[-T, S <: Stepper[_]^] extends Pure {
24+
/** Return the Int constant (as defined in the `StepperShape` companion object) for this `StepperShape`. */
25+
def shape: StepperShape.Shape
26+
27+
/** Create an unboxing primitive sequential Stepper from a boxed `AnyStepper`.
28+
* This is an identity operation for reference shapes. */
29+
def seqUnbox(st: AnyStepper[T]): S
30+
31+
/** Create an unboxing primitive parallel (i.e. `with EfficientSplit`) Stepper from a boxed `AnyStepper`.
32+
* This is an identity operation for reference shapes. */
33+
def parUnbox(st: AnyStepper[T] with EfficientSplit): S with EfficientSplit
34+
}
35+
36+
object StepperShape extends StepperShapeLowPriority1 {
37+
class Shape private[StepperShape] (private val s: Int) extends AnyVal
38+
39+
// reference
40+
val ReferenceShape = new Shape(0)
41+
42+
// primitive
43+
val IntShape = new Shape(1)
44+
val LongShape = new Shape(2)
45+
val DoubleShape = new Shape(3)
46+
47+
// widening
48+
val ByteShape = new Shape(4)
49+
val ShortShape = new Shape(5)
50+
val CharShape = new Shape(6)
51+
val FloatShape = new Shape(7)
52+
53+
implicit val intStepperShape: StepperShape[Int, IntStepper] = new StepperShape[Int, IntStepper] {
54+
def shape = IntShape
55+
def seqUnbox(st: AnyStepper[Int]): IntStepper = new Stepper.UnboxingIntStepper(st)
56+
def parUnbox(st: AnyStepper[Int] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingIntStepper(st) with EfficientSplit
57+
}
58+
implicit val jIntegerStepperShape: StepperShape[jl.Integer, IntStepper] = intStepperShape.asInstanceOf[StepperShape[jl.Integer, IntStepper]]
59+
60+
implicit val longStepperShape: StepperShape[Long, LongStepper] = new StepperShape[Long, LongStepper] {
61+
def shape = LongShape
62+
def seqUnbox(st: AnyStepper[Long]): LongStepper = new Stepper.UnboxingLongStepper(st)
63+
def parUnbox(st: AnyStepper[Long] with EfficientSplit): LongStepper with EfficientSplit = new Stepper.UnboxingLongStepper(st) with EfficientSplit
64+
}
65+
implicit val jLongStepperShape: StepperShape[jl.Long, LongStepper] = longStepperShape.asInstanceOf[StepperShape[jl.Long, LongStepper]]
66+
67+
implicit val doubleStepperShape: StepperShape[Double, DoubleStepper] = new StepperShape[Double, DoubleStepper] {
68+
def shape = DoubleShape
69+
def seqUnbox(st: AnyStepper[Double]): DoubleStepper = new Stepper.UnboxingDoubleStepper(st)
70+
def parUnbox(st: AnyStepper[Double] with EfficientSplit): DoubleStepper with EfficientSplit = new Stepper.UnboxingDoubleStepper(st) with EfficientSplit
71+
}
72+
implicit val jDoubleStepperShape: StepperShape[jl.Double, DoubleStepper] = doubleStepperShape.asInstanceOf[StepperShape[jl.Double, DoubleStepper]]
73+
74+
implicit val byteStepperShape: StepperShape[Byte, IntStepper] = new StepperShape[Byte, IntStepper] {
75+
def shape = ByteShape
76+
def seqUnbox(st: AnyStepper[Byte]): IntStepper = new Stepper.UnboxingByteStepper(st)
77+
def parUnbox(st: AnyStepper[Byte] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingByteStepper(st) with EfficientSplit
78+
}
79+
implicit val jByteStepperShape: StepperShape[jl.Byte, IntStepper] = byteStepperShape.asInstanceOf[StepperShape[jl.Byte, IntStepper]]
80+
81+
implicit val shortStepperShape: StepperShape[Short, IntStepper] = new StepperShape[Short, IntStepper] {
82+
def shape = ShortShape
83+
def seqUnbox(st: AnyStepper[Short]): IntStepper = new Stepper.UnboxingShortStepper(st)
84+
def parUnbox(st: AnyStepper[Short] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingShortStepper(st) with EfficientSplit
85+
}
86+
implicit val jShortStepperShape: StepperShape[jl.Short, IntStepper] = shortStepperShape.asInstanceOf[StepperShape[jl.Short, IntStepper]]
87+
88+
implicit val charStepperShape: StepperShape[Char, IntStepper] = new StepperShape[Char, IntStepper] {
89+
def shape = CharShape
90+
def seqUnbox(st: AnyStepper[Char]): IntStepper = new Stepper.UnboxingCharStepper(st)
91+
def parUnbox(st: AnyStepper[Char] with EfficientSplit): IntStepper with EfficientSplit = new Stepper.UnboxingCharStepper(st) with EfficientSplit
92+
}
93+
implicit val jCharacterStepperShape: StepperShape[jl.Character, IntStepper] = charStepperShape.asInstanceOf[StepperShape[jl.Character, IntStepper]]
94+
95+
implicit val floatStepperShape: StepperShape[Float, DoubleStepper] = new StepperShape[Float, DoubleStepper] {
96+
def shape = FloatShape
97+
def seqUnbox(st: AnyStepper[Float]): DoubleStepper = new Stepper.UnboxingFloatStepper(st)
98+
def parUnbox(st: AnyStepper[Float] with EfficientSplit): DoubleStepper with EfficientSplit = new Stepper.UnboxingFloatStepper(st) with EfficientSplit
99+
}
100+
implicit val jFloatStepperShape: StepperShape[jl.Float, DoubleStepper] = floatStepperShape.asInstanceOf[StepperShape[jl.Float, DoubleStepper]]
101+
}
102+
103+
trait StepperShapeLowPriority1 extends StepperShapeLowPriority2 {
104+
implicit def anyStepperShape[T]: StepperShape[T, AnyStepper[T]] = anyStepperShapePrototype.asInstanceOf[StepperShape[T, AnyStepper[T]]]
105+
}
106+
107+
trait StepperShapeLowPriority2 {
108+
implicit def baseStepperShape[T]: StepperShape[T, Stepper[T]] = anyStepperShapePrototype.asInstanceOf[StepperShape[T, Stepper[T]]]
109+
110+
protected val anyStepperShapePrototype: StepperShape[AnyRef, Stepper[AnyRef]] = new StepperShape[AnyRef, Stepper[AnyRef]] {
111+
def shape = StepperShape.ReferenceShape
112+
def seqUnbox(st: AnyStepper[AnyRef]): Stepper[AnyRef] = st
113+
def parUnbox(st: AnyStepper[AnyRef] with EfficientSplit): Stepper[AnyRef] with EfficientSplit = st
114+
}
115+
}

0 commit comments

Comments
 (0)