import scala.collection.immutable.HashSet object Test extends dotty.runtime.LegacyApp { case class Collision(value: Int) extends Ordered[Collision] { def compare(that:Collision) = value compare that.value override def hashCode = value / 5 } def testCorrectness[T : Ordering](n: Int, mkKey: Int => T): Unit = { val o = implicitly[Ordering[T]] val s = HashSet.empty[T] ++ (0 until n).map(mkKey) for (i <- 0 until n) { val ki = mkKey(i) val a = s.filter(o.lt(_,ki)) val b = s.filterNot(o.lt(_,ki)) require(a.size == i && (0 until i).forall(i => a.contains(mkKey(i)))) require(b.size == n - i && (i until n).forall(i => b.contains(mkKey(i)))) } } // this tests the structural sharing of the new filter // I could not come up with a simple test that tests structural sharing when only parts are reused, but // at least this fails with the old and passes with the new implementation def testSharing(): Unit = { val s = HashSet.empty[Int] ++ (0 until 100) require(s.filter(_ => true) eq s) require(s.filterNot(_ => false) eq s) } // this tests that neither hashCode nor equals are called during filter def testNoHashing(): Unit = { var hashCount = 0 var equalsCount = 0 case class HashCounter(value:Int) extends Ordered[HashCounter] { def compare(that:HashCounter) = value compare that.value override def hashCode = { hashCount += 1 value } override def equals(that:Any) = { equalsCount += 1 that match { case HashCounter(value) => this.value == value case _ => false } } } val s = HashSet.empty[HashCounter] ++ (0 until 100).map(HashCounter) val hashCount0 = hashCount val equalsCount0 = equalsCount val t = s.filter(_