Skip to content

Commit

Permalink
Merge pull request #5191 from som-snytt/issue/9382
Browse files Browse the repository at this point in the history
SI-9382 Privatize enhanced x in Tuple2Zipped.Ops
  • Loading branch information
lrytz committed May 30, 2016
2 parents 7d5a0b3 + 0b79f4b commit 9edbe3d
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 99 deletions.
41 changes: 21 additions & 20 deletions src/library/scala/runtime/Tuple2Zipped.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
** / __/ __// _ | / / / _ | (c) 2002-2016, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
Expand Down Expand Up @@ -34,14 +34,15 @@ object ZippedTraversable2 {
}

final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1, Repr1], IterableLike[El2, Repr2])) extends AnyVal with ZippedTraversable2[El1, El2] {
// This would be better as "private def coll1 = colls._1" but
// SI-6215 precludes private methods in value classes.
private def coll1 = colls._1
private def coll2 = colls._2

def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(colls._1.repr)
b.sizeHint(colls._1)
val elems2 = colls._2.iterator
val b = cbf(coll1.repr)
b.sizeHint(coll1)
val elems2 = coll2.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext)
b += f(el1, elems2.next())
else
Expand All @@ -52,10 +53,10 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1
}

def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(colls._1.repr)
val elems2 = colls._2.iterator
val b = cbf(coll1.repr)
val elems2 = coll2.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext)
b ++= f(el1, elems2.next())
else
Expand All @@ -66,11 +67,11 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1
}

def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
val b1 = cbf1(colls._1.repr)
val b2 = cbf2(colls._2.repr)
val elems2 = colls._2.iterator
val b1 = cbf1(coll1.repr)
val b2 = cbf2(coll2.repr)
val elems2 = coll2.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext) {
val el2 = elems2.next()
if (f(el1, el2)) {
Expand All @@ -85,9 +86,9 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1
}

def exists(@deprecatedName('f) p: (El1, El2) => Boolean): Boolean = {
val elems2 = colls._2.iterator
val elems2 = coll2.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext) {
if (p(el1, elems2.next()))
return true
Expand All @@ -101,21 +102,21 @@ final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1
!exists((x, y) => !p(x, y))

def foreach[U](f: (El1, El2) => U): Unit = {
val elems2 = colls._2.iterator
val elems2 = coll2.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext)
f(el1, elems2.next())
else
return
}
}

override def toString = "(%s, %s).zipped".format(colls._1.toString, colls._2.toString)
override def toString = s"($coll1, $coll2).zipped"
}

object Tuple2Zipped {
final class Ops[T1, T2](val x: (T1, T2)) extends AnyVal {
final class Ops[T1, T2](private val x: (T1, T2)) extends AnyVal {
def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], That]
(implicit w1: T1 <:< CC1[El1],
w2: T2 <:< CC2[El2],
Expand Down
48 changes: 26 additions & 22 deletions src/library/scala/runtime/Tuple3Zipped.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ object ZippedTraversable3 {
final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (TraversableLike[El1, Repr1], IterableLike[El2, Repr2], IterableLike[El3, Repr3]))
extends AnyVal with ZippedTraversable3[El1, El2, El3] {

private def coll1 = colls._1
private def coll2 = colls._2
private def coll3 = colls._3

def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(colls._1.repr)
val elems2 = colls._2.iterator
val elems3 = colls._3.iterator
val b = cbf(coll1.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
b += f(el1, elems2.next(), elems3.next())
else
Expand All @@ -49,11 +53,11 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers
}

def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
val b = cbf(colls._1.repr)
val elems2 = colls._2.iterator
val elems3 = colls._3.iterator
val b = cbf(coll1.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
b ++= f(el1, elems2.next(), elems3.next())
else
Expand All @@ -66,14 +70,14 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers
implicit cbf1: CBF[Repr1, El1, To1],
cbf2: CBF[Repr2, El2, To2],
cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = {
val b1 = cbf1(colls._1.repr)
val b2 = cbf2(colls._2.repr)
val b3 = cbf3(colls._3.repr)
val elems2 = colls._2.iterator
val elems3 = colls._3.iterator
val b1 = cbf1(coll1.repr)
val b2 = cbf2(coll2.repr)
val b3 = cbf3(coll3.repr)
val elems2 = coll2.iterator
val elems3 = coll3.iterator
def result = (b1.result(), b2.result(), b3.result())

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext) {
val el2 = elems2.next()
val el3 = elems3.next()
Expand All @@ -91,10 +95,10 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers
}

def exists(@deprecatedName('f) p: (El1, El2, El3) => Boolean): Boolean = {
val elems2 = colls._2.iterator
val elems3 = colls._3.iterator
val elems2 = coll2.iterator
val elems3 = coll3.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext) {
if (p(el1, elems2.next(), elems3.next()))
return true
Expand All @@ -108,22 +112,22 @@ final class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](val colls: (Travers
!exists((x, y, z) => !p(x, y, z))

def foreach[U](f: (El1, El2, El3) => U): Unit = {
val elems2 = colls._2.iterator
val elems3 = colls._3.iterator
val elems2 = coll2.iterator
val elems3 = coll3.iterator

for (el1 <- colls._1) {
for (el1 <- coll1) {
if (elems2.hasNext && elems3.hasNext)
f(el1, elems2.next(), elems3.next())
else
return
}
}

override def toString: String = "(%s, %s, %s).zipped".format(colls._1.toString, colls._2.toString, colls._3.toString)
override def toString = s"($coll1, $coll2, $coll3).zipped"
}

object Tuple3Zipped {
final class Ops[T1, T2, T3](val x: (T1, T2, T3)) extends AnyVal {
final class Ops[T1, T2, T3](private val x: (T1, T2, T3)) extends AnyVal {
def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], El3, CC3[X] <: TraversableOnce[X], That]
(implicit w1: T1 <:< CC1[El1],
w2: T2 <:< CC2[El2],
Expand Down
10 changes: 10 additions & 0 deletions test/files/neg/t9382.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
t9382.scala:3: error: value x is not a member of (List[Int], List[Int])
def f = (List(1,2,3), List(4,5,6)).x
^
t9382.scala:4: error: value x is not a member of (List[Int], List[Int], List[Int])
def g = (List(1,2,3), List(4,5,6), List(7,8,9)).x
^
t9382.scala:5: error: value x is not a member of (Int, Int)
def huh = (1,2).x
^
three errors found
6 changes: 6 additions & 0 deletions test/files/neg/t9382.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

trait T {
def f = (List(1,2,3), List(4,5,6)).x
def g = (List(1,2,3), List(4,5,6), List(7,8,9)).x
def huh = (1,2).x
}
41 changes: 0 additions & 41 deletions test/files/run/tuple-zipped.scala

This file was deleted.

16 changes: 0 additions & 16 deletions test/junit/scala/collection/immutable/StreamTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,4 @@ class StreamTest {
def withFilter_map_properly_lazy_in_tail: Unit = {
assertStreamOpLazyInTail(_.withFilter(_ % 2 == 0).map(identity), List(1, 2))
}

@Test
def test_si9379() {
class Boom {
private var i = -1
def inc = {
i += 1
if (i > 1000) throw new NoSuchElementException("Boom! Too many elements!")
i
}
}
val b = new Boom
val s = Stream.continually(b.inc)
// zipped.toString must allow s to short-circuit evaluation
assertTrue((s, s).zipped.toString contains s.toString)
}
}
68 changes: 68 additions & 0 deletions test/junit/scala/runtime/ZippedTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

package scala.runtime

import scala.language.postfixOps

import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

/** Tests Tuple?Zipped */
@RunWith(classOf[JUnit4])
class ZippedTest {
@Test
def crossZipped() {

val xs1 = List.range(1, 100)
val xs2 = xs1.view
val xs3 = xs1 take 10
val ss1 = Stream from 1
val ss2 = ss1.view
val ss3 = ss1 take 10
val as1 = 1 to 100 toArray
val as2 = as1.view
val as3 = as1 take 10

def xss1 = List[Seq[Int]](xs1, xs2, xs3, ss1, ss2, ss3, as1, as2, as3)
def xss2 = List[Seq[Int]](xs1, xs2, xs3, ss3, as1, as2, as3) // no infinities
def xss3 = List[Seq[Int]](xs2, xs3, ss3, as1) // representative sampling

for (cc1 <- xss1 ; cc2 <- xss2) {
val sum1 = (cc1, cc2).zipped map { case (x, y) => x + y } sum
val sum2 = (cc1, cc2).zipped map (_ + _) sum

assert(sum1 == sum2)
}

for (cc1 <- xss1 ; cc2 <- xss2 ; cc3 <- xss3) {
val sum1 = (cc1, cc2, cc3).zipped map { case (x, y, z) => x + y + z } sum
val sum2 = (cc1, cc2, cc3).zipped map (_ + _ + _) sum

assert(sum1 == sum2)
}

assert((ss1, ss1).zipped exists ((x, y) => true))
assert((ss1, ss1, ss1).zipped exists ((x, y, z) => true))

assert(!(ss1, ss2, 1 to 3).zipped.exists(_ + _ + _ > 100000))
assert((1 to 3, ss1, ss2).zipped.forall(_ + _ + _ > 0))
assert((ss1, 1 to 3, ss2).zipped.map(_ + _ + _).size == 3)
}

@Test
def test_si9379() {
class Boom {
private var i = -1
def inc = {
i += 1
if (i > 1000) throw new NoSuchElementException("Boom! Too many elements!")
i
}
}
val b = new Boom
val s = Stream.continually(b.inc)
// zipped.toString must allow s to short-circuit evaluation
assertTrue((s, s).zipped.toString contains s.toString)
}
}

0 comments on commit 9edbe3d

Please sign in to comment.