Skip to content

Commit

Permalink
Calibrate findMember logging thresholds and test case
Browse files Browse the repository at this point in the history
Adds IterableSelfRec.scala which caused lockup of the compiler.
After a lot of work the problem was determined to be polyomial or
exponential behavior of the compiler when executing findMember
on refined types that contain several bindings where the
resutling & causes a recursive invokation of findMember with
the same name. We do have a stop for this now, but if the
stop comes too late the runtime will grow very fast.

Problem addressed by kiccking in earlier with the stopping logic.
  • Loading branch information
odersky committed May 21, 2015
1 parent 10bb6a0 commit 78640eb
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
14 changes: 11 additions & 3 deletions src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,17 @@ object Config {
/** How many recursive calls to isSubType are performed before logging starts. */
final val LogPendingSubTypesThreshold = 50

/** How many recursive calls to findMember are performed before logging names starts */
final val LogPendingFindMemberThreshold = 20
/** How many recursive calls to findMember are performed before logging names starts
* Note: this threshold has to be chosen carefully. Too large, and programs
* like tests/pos/IterableSelfRec go into polynomial (or even exponential?)
* compile time slowdown. Too small and normal programs will cause the compiler to
* do inefficient operations on findMember. The current value is determined
* so that (1) IterableSelfRec still compiles in reasonable time (< 10sec) (2) Compiling
* dotty itself only causes small pending names lists to be generated (we measured
* at max 6 elements) and these lists are never searched with contains.
*/
final val LogPendingFindMemberThreshold = 10

/** Maximal number of outstanding recursive calls to findMember */
final val PendingFindMemberLimit = LogPendingFindMemberThreshold * 2
final val PendingFindMemberLimit = LogPendingFindMemberThreshold * 4
}
52 changes: 52 additions & 0 deletions tests/pos/IterableSelfRec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package dotty.collection
package immutable

import annotation.unchecked.uncheckedVariance

trait Collection[T] { self =>
type This <: Collection { type This <: self.This }
def companion: CollectionCompanion[This]
}

trait Iterable[T] extends Collection[T] { self =>
type This <: Iterable { type This <: self.This }
override def companion: IterableCompanion[This] = Iterable.asInstanceOf

def iterator: Iterator[T]
}

trait Seq[T] extends Iterable[T] { self =>
type This <: Seq { type This <: self.This }
override def companion: IterableCompanion[This] = Seq.asInstanceOf

def apply(x: Int): T
}

abstract class CollectionCompanion[+CC <: Collection { type This <: CC }]

abstract class IterableCompanion[+CC <: Iterable { type This <: CC }] extends CollectionCompanion[CC] {
def fromIterator[T](it: Iterator[T]): CC[T]
def map[T, U](xs: Iterable[T], f: T => U): CC[U] =
fromIterator(xs.iterator.map(f))
def filter[T](xs: Iterable[T], p: T => Boolean): CC[T] =
fromIterator(xs.iterator.filter(p))
def flatMap[T, U](xs: Iterable[T], f: T => TraversableOnce[U]): CC[U] =
fromIterator(xs.iterator.flatMap(f))

implicit def transformOps[T](xs: CC[T] @uncheckedVariance): TransformOps[CC, T] = ??? // new TransformOps[CC, T](xs)
}

class TransformOps[+CC <: Iterable { type This <: CC }, T] (val xs: CC[T]) extends AnyVal {
def companion[T](xs: CC[T] @uncheckedVariance): IterableCompanion[CC] = xs.companion
def map[U](f: T => U): CC[U] = companion(xs).map(xs, f)
def filter(p: T => Boolean): CC[T] = companion(xs).filter(xs, p)
def flatMap[U](f: T => TraversableOnce[U]): CC[U] = companion(xs).flatMap(xs, f)
}

object Iterable extends IterableCompanion[Iterable] {
def fromIterator[T](it: Iterator[T]): Iterable[T] = ???
}
object Seq extends IterableCompanion[Seq] {
def fromIterator[T](it: Iterator[T]): Seq[T] = ???
}

0 comments on commit 78640eb

Please sign in to comment.