summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala3
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala8
-rwxr-xr-xsrc/library/scala/collection/IndexedSeqOptimized.scala10
-rw-r--r--src/library/scala/collection/TraversableLike.scala17
-rw-r--r--src/library/scala/collection/generic/Growable.scala17
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala9
-rw-r--r--src/library/scala/io/Codec.scala55
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala9
-rw-r--r--src/reflect/scala/reflect/internal/BaseTypeSeqs.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala86
15 files changed, 173 insertions, 106 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 12daa32186..248a505b54 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -46,8 +46,13 @@ trait Members {
def touched = _touched
def touched_=(b: Boolean): Unit = {
- if (b)
- blocks foreach (_.touched = true)
+ @annotation.tailrec def loop(xs: List[BasicBlock]) {
+ xs match {
+ case Nil =>
+ case x :: xs => x.touched = true ; loop(xs)
+ }
+ }
+ if (b) loop(blocks.toList)
_touched = b
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index cb58111b51..04e860f9db 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -1225,16 +1225,20 @@ abstract class ClassfileParser {
}
def skipAttributes() {
- val attrCount = in.nextChar
- for (i <- 0 until attrCount) {
- in.skip(2); in.skip(in.nextInt)
+ var attrCount: Int = in.nextChar
+ while (attrCount > 0) {
+ in skip 2
+ in skip in.nextInt
+ attrCount -= 1
}
}
def skipMembers() {
- val memberCount = in.nextChar
- for (i <- 0 until memberCount) {
- in.skip(6); skipAttributes()
+ var memberCount: Int = in.nextChar
+ while (memberCount > 0) {
+ in skip 6
+ skipAttributes()
+ memberCount -= 1
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 173ca1e628..116b6ab58f 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -10,6 +10,7 @@ import scala.tools.nsc.symtab.Flags
import scala.collection.{ mutable, immutable }
import scala.language.postfixOps
import scala.language.existentials
+import scala.annotation.tailrec
/** Specialize code on types.
*
@@ -403,11 +404,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case _ => false
})
def specializedTypeVars(tpes: List[Type]): immutable.Set[Symbol] = {
- if (tpes.isEmpty) immutable.Set.empty else {
- val buf = Set.newBuilder[Symbol]
- tpes foreach (tp => buf ++= specializedTypeVars(tp))
- buf.result
+ @tailrec def loop(result: immutable.Set[Symbol], xs: List[Type]): immutable.Set[Symbol] = {
+ if (xs.isEmpty) result
+ else loop(result ++ specializedTypeVars(xs.head), xs.tail)
}
+ loop(immutable.Set.empty, tpes)
}
def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = (
if (definitions.neverHasTypeParameters(sym)) immutable.Set.empty
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 6e89f6387e..f4e40a216e 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -114,7 +114,8 @@ abstract class UnCurry extends InfoTransform
def isByNameRef(tree: Tree) = (
tree.isTerm
&& !byNameArgs(tree)
- && tree.hasSymbolWhich(isByName)
+ && (tree.symbol ne null)
+ && (isByName(tree.symbol))
)
/** Uncurry a type of a tree node.
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index c147dc483d..cf5b1fa2c4 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -221,7 +221,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes {
} else if (retMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) {
// add a marker annotation that will make tree.tpe behave as pt, subtyping wise
// tree will look like having any possible annotation
-
+
// note 1: we are only adding a plus marker if the method's result type is a cps type
// (annotsExpected.nonEmpty == cpsParamAnnotation(pt).nonEmpty)
// note 2: we are not adding the expected cps annotations, since they will be added
@@ -234,7 +234,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes {
/** Returns an adapted type for a return expression if the method's result type (pt) is a CPS type.
* Otherwise, it returns the `default` type (`typedReturn` passes `NothingClass.tpe`).
- *
+ *
* A return expression in a method that has a CPS result type is an error unless the return
* is in tail position. Therefore, we are making sure that only the types of return expressions
* are adapted which will either be removed, or lead to an error.
@@ -396,8 +396,10 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes {
override def addAnnotations(tree: Tree, tpe: Type): Type = {
import scala.util.control._
if (!cpsEnabled) {
- if (Exception.failAsValue(classOf[MissingRequirementError])(false)(hasCpsParamTypes(tpe)))
+ val report = try hasCpsParamTypes(tpe) catch { case _: MissingRequirementError => false }
+ if (report)
global.reporter.error(tree.pos, "this code must be compiled with the Scala continuations plugin enabled")
+
return tpe
}
diff --git a/src/library/scala/collection/IndexedSeqOptimized.scala b/src/library/scala/collection/IndexedSeqOptimized.scala
index 09c4b14ba0..9721a42e91 100755
--- a/src/library/scala/collection/IndexedSeqOptimized.scala
+++ b/src/library/scala/collection/IndexedSeqOptimized.scala
@@ -33,11 +33,17 @@ trait IndexedSeqOptimized[+A, +Repr] extends Any with IndexedSeqLike[A, Repr] {
while (i < len) { f(this(i)); i += 1 }
}
+ private def prefixLengthImpl(p: A => Boolean, expectTrue: Boolean): Int = {
+ var i = 0
+ while (i < length && p(apply(i)) == expectTrue) i += 1
+ i
+ }
+
override /*IterableLike*/
- def forall(p: A => Boolean): Boolean = prefixLength(p(_)) == length
+ def forall(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = true) == length
override /*IterableLike*/
- def exists(p: A => Boolean): Boolean = prefixLength(!p(_)) != length
+ def exists(p: A => Boolean): Boolean = prefixLengthImpl(p, expectTrue = false) != length
override /*IterableLike*/
def find(p: A => Boolean): Option[A] = {
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index c1a68b6b16..a55257d128 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -252,18 +252,21 @@ trait TraversableLike[+A, +Repr] extends Any
b.result
}
+ private def filterImpl(p: A => Boolean, isFlipped: Boolean): Repr = {
+ val b = newBuilder
+ for (x <- this)
+ if (p(x) != isFlipped) b += x
+
+ b.result
+ }
+
/** Selects all elements of this $coll which satisfy a predicate.
*
* @param p the predicate used to test elements.
* @return a new $coll consisting of all elements of this $coll that satisfy the given
* predicate `p`. The order of the elements is preserved.
*/
- def filter(p: A => Boolean): Repr = {
- val b = newBuilder
- for (x <- this)
- if (p(x)) b += x
- b.result
- }
+ def filter(p: A => Boolean): Repr = filterImpl(p, isFlipped = false)
/** Selects all elements of this $coll which do not satisfy a predicate.
*
@@ -271,7 +274,7 @@ trait TraversableLike[+A, +Repr] extends Any
* @return a new $coll consisting of all elements of this $coll that do not satisfy the given
* predicate `p`. The order of the elements is preserved.
*/
- def filterNot(p: A => Boolean): Repr = filter(!p(_))
+ def filterNot(p: A => Boolean): Repr = filterImpl(p, isFlipped = true)
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
diff --git a/src/library/scala/collection/generic/Growable.scala b/src/library/scala/collection/generic/Growable.scala
index cb75212e3d..52a0d32de1 100644
--- a/src/library/scala/collection/generic/Growable.scala
+++ b/src/library/scala/collection/generic/Growable.scala
@@ -6,10 +6,11 @@
** |/ **
\* */
-
package scala.collection
package generic
+import scala.annotation.tailrec
+
/** This trait forms part of collections that can be augmented
* using a `+=` operator and that can be cleared of all elements using
* a `clear` method.
@@ -45,7 +46,19 @@ trait Growable[-A] extends Clearable {
* @param xs the TraversableOnce producing the elements to $add.
* @return the $coll itself.
*/
- def ++=(xs: TraversableOnce[A]): this.type = { xs.seq foreach += ; this }
+ def ++=(xs: TraversableOnce[A]): this.type = {
+ @tailrec def loop(xs: collection.LinearSeq[A]) {
+ if (xs.nonEmpty) {
+ this += xs.head
+ loop(xs.tail)
+ }
+ }
+ xs.seq match {
+ case xs: collection.LinearSeq[_] => loop(xs)
+ case xs => xs foreach +=
+ }
+ this
+ }
/** Clears the $coll's contents. After this operation, the
* $coll is empty.
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index b7b487964c..97d469bca2 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -6,8 +6,6 @@
** |/ **
\* */
-
-
package scala.collection
package mutable
@@ -178,8 +176,11 @@ final class ListBuffer[A]
this
}
- override def ++=(xs: TraversableOnce[A]): this.type =
- if (xs.asInstanceOf[AnyRef] eq this) ++= (this take size) else super.++=(xs)
+ override def ++=(xs: TraversableOnce[A]): this.type = xs match {
+ case x: AnyRef if x eq this => this ++= (this take size)
+ case _ => super.++=(xs)
+
+ }
override def ++=:(xs: TraversableOnce[A]): this.type =
if (xs.asInstanceOf[AnyRef] eq this) ++=: (this take size) else super.++=:(xs)
diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala
index 5d046e48b0..bda4234460 100644
--- a/src/library/scala/io/Codec.scala
+++ b/src/library/scala/io/Codec.scala
@@ -43,42 +43,37 @@ class Codec(val charSet: Charset) {
override def toString = name
// these methods can be chained to configure the variables above
- def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this }
- def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this }
- def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this }
+ def onMalformedInput(newAction: Action): this.type = { _onMalformedInput = newAction ; this }
+ def onUnmappableCharacter(newAction: Action): this.type = { _onUnmappableCharacter = newAction ; this }
+ def decodingReplaceWith(newReplacement: String): this.type = { _decodingReplacement = newReplacement ; this }
def encodingReplaceWith(newReplacement: Array[Byte]): this.type = { _encodingReplacement = newReplacement ; this }
- def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this }
+ def onCodingException(handler: Handler): this.type = { _onCodingException = handler ; this }
def name = charSet.name
- def encoder =
- applyFunctions[CharsetEncoder](charSet.newEncoder(),
- (_ onMalformedInput _onMalformedInput, _onMalformedInput != null),
- (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null),
- (_ replaceWith _encodingReplacement, _encodingReplacement != null)
- )
-
- def decoder =
- applyFunctions[CharsetDecoder](charSet.newDecoder(),
- (_ onMalformedInput _onMalformedInput, _onMalformedInput != null),
- (_ onUnmappableCharacter _onUnmappableCharacter, _onUnmappableCharacter != null),
- (_ replaceWith _decodingReplacement, _decodingReplacement != null)
- )
+ def encoder: CharsetEncoder = {
+ val enc = charSet.newEncoder()
+ if (_onMalformedInput ne null) enc onMalformedInput _onMalformedInput
+ if (_onUnmappableCharacter ne null) enc onUnmappableCharacter _onUnmappableCharacter
+ if (_encodingReplacement ne null) enc replaceWith _encodingReplacement
+ enc
+ }
+ def decoder: CharsetDecoder = {
+ val dec = charSet.newDecoder()
+ if (_onMalformedInput ne null) dec onMalformedInput _onMalformedInput
+ if (_onUnmappableCharacter ne null) dec onUnmappableCharacter _onUnmappableCharacter
+ if (_decodingReplacement ne null) dec replaceWith _decodingReplacement
+ dec
+ }
def wrap(body: => Int): Int =
try body catch { case e: CharacterCodingException => _onCodingException(e) }
-
- // call a series of side effecting methods on an object, finally returning the object
- private def applyFunctions[T](x: T, fs: Configure[T]*) =
- fs.foldLeft(x)((x, pair) => pair match {
- case (f, cond) => if (cond) f(x) else x
- })
}
trait LowPriorityCodecImplicits {
self: Codec.type =>
/** The Codec of Last Resort. */
- implicit def fallbackSystemCodec: Codec = defaultCharsetCodec
+ implicit lazy val fallbackSystemCodec: Codec = defaultCharsetCodec
}
object Codec extends LowPriorityCodecImplicits {
@@ -90,9 +85,9 @@ object Codec extends LowPriorityCodecImplicits {
* the fact that you can influence anything at all via -Dfile.encoding
* as an accident, with any anomalies considered "not a bug".
*/
- def defaultCharsetCodec = apply(Charset.defaultCharset)
- def fileEncodingCodec = apply(scala.util.Properties.encodingString)
- def default = defaultCharsetCodec
+ def defaultCharsetCodec = apply(Charset.defaultCharset)
+ def fileEncodingCodec = apply(scala.util.Properties.encodingString)
+ def default = defaultCharsetCodec
def apply(encoding: String): Codec = new Codec(Charset forName encoding)
def apply(charSet: Charset): Codec = new Codec(charSet)
@@ -130,7 +125,7 @@ object Codec extends LowPriorityCodecImplicits {
bytes
}
- implicit def string2codec(s: String) = apply(s)
- implicit def charset2codec(c: Charset) = apply(c)
- implicit def decoder2codec(cd: CharsetDecoder) = apply(cd)
+ implicit def string2codec(s: String): Codec = apply(s)
+ implicit def charset2codec(c: Charset): Codec = apply(c)
+ implicit def decoder2codec(cd: CharsetDecoder): Codec = apply(cd)
}
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 637a7a4c40..0170bf2032 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -2927,7 +2927,8 @@ trait Trees { self: Universe =>
def transform(tree: Tree): Tree = itransform(this, tree)
/** Transforms a list of trees. */
- def transformTrees(trees: List[Tree]): List[Tree] = trees mapConserve (transform(_))
+ def transformTrees(trees: List[Tree]): List[Tree] =
+ if (trees.isEmpty) Nil else trees mapConserve transform
/** Transforms a `Template`. */
def transformTemplate(tree: Template): Template =
@@ -2957,8 +2958,10 @@ trait Trees { self: Universe =>
if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
else transform(stat)) filter (EmptyTree != _)
/** Transforms `Modifiers`. */
- def transformModifiers(mods: Modifiers): Modifiers =
- mods.mapAnnotations(transformTrees)
+ def transformModifiers(mods: Modifiers): Modifiers = {
+ if (mods.annotations.isEmpty) mods
+ else mods mapAnnotations transformTrees
+ }
/** Transforms a tree with a given owner symbol. */
def atOwner[A](owner: Symbol)(trans: => A): A = {
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
index eba10e8ffb..18a4a36840 100644
--- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
@@ -193,15 +193,23 @@ trait BaseTypeSeqs {
i += 1
}
var minTypes: List[Type] = List()
+ def alreadyInMinTypes(tp: Type): Boolean = {
+ @annotation.tailrec def loop(tps: List[Type]): Boolean = tps match {
+ case Nil => false
+ case x :: xs => (tp =:= x) || loop(xs)
+ }
+ loop(minTypes)
+ }
+
i = 0
while (i < nparents) {
if (nextTypeSymbol(i) == minSym) {
nextRawElem(i) match {
case RefinedType(variants, decls) =>
for (tp <- variants)
- if (!(minTypes exists (tp =:= _))) minTypes = tp :: minTypes
+ if (!alreadyInMinTypes(tp)) minTypes ::= tp
case tp =>
- if (!(minTypes exists (tp =:= _))) minTypes = tp :: minTypes
+ if (!alreadyInMinTypes(tp)) minTypes ::= tp
}
index(i) = index(i) + 1
}
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index fd5c3909b8..3d43500ef1 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -2048,7 +2048,17 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Returns all symbols overriden by this symbol. */
final def allOverriddenSymbols: List[Symbol] = (
if ((this eq NoSymbol) || !owner.isClass) Nil
- else owner.ancestors map overriddenSymbol filter (_ != NoSymbol)
+ else {
+ def loop(xs: List[Symbol]): List[Symbol] = xs match {
+ case Nil => Nil
+ case x :: xs =>
+ overriddenSymbol(x) match {
+ case NoSymbol => loop(xs)
+ case sym => sym :: loop(xs)
+ }
+ }
+ loop(owner.ancestors)
+ }
)
/** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 35e10d73c8..308ab93c07 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -928,8 +928,11 @@ trait Trees extends api.Trees { self: SymbolTable =>
def withPosition(flag: Long, position: Position) =
copy() setPositions positions + (flag -> position)
- override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers =
- Modifiers(flags, privateWithin, f(annotations)) setPositions positions
+ override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = {
+ val newAnns = f(annotations)
+ if (annotations == newAnns) this
+ else Modifiers(flags, privateWithin, newAnns) setPositions positions
+ }
override def toString = "Modifiers(%s, %s, %s)".format(flagString, annotations mkString ", ", positions)
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index c121c6020e..9ccb962ec3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -4102,8 +4102,13 @@ trait Types extends api.Types { self: SymbolTable =>
/** Called by mapOver to determine whether the original symbols can
* be returned, or whether they must be cloned. Overridden in VariantTypeMap.
*/
- protected def noChangeToSymbols(origSyms: List[Symbol]) =
- origSyms forall (sym => sym.info eq this(sym.info))
+ protected def noChangeToSymbols(origSyms: List[Symbol]): Boolean = {
+ @tailrec def loop(syms: List[Symbol]): Boolean = syms match {
+ case Nil => true
+ case x :: xs => (x.info eq this(x.info)) && loop(xs)
+ }
+ loop(origSyms)
+ }
/** Map this function over given scope */
def mapOver(scope: Scope): Scope = {
@@ -5038,41 +5043,9 @@ trait Types extends api.Types { self: SymbolTable =>
else if (bd <= 7) td max (bd - 2)
else (td - 1) max (bd - 3)
- /** The maximum depth of type `tp` */
- def typeDepth(tp: Type): Int = tp match {
- case TypeRef(pre, sym, args) =>
- typeDepth(pre) max typeDepth(args) + 1
- case RefinedType(parents, decls) =>
- typeDepth(parents) max typeDepth(decls.toList.map(_.info)) + 1
- case TypeBounds(lo, hi) =>
- typeDepth(lo) max typeDepth(hi)
- case MethodType(paramtypes, result) =>
- typeDepth(result)
- case NullaryMethodType(result) =>
- typeDepth(result)
- case PolyType(tparams, result) =>
- typeDepth(result) max typeDepth(tparams map (_.info)) + 1
- case ExistentialType(tparams, result) =>
- typeDepth(result) max typeDepth(tparams map (_.info)) + 1
- case _ =>
- 1
- }
-
- private def maxDepth(tps: List[Type], by: Type => Int): Int = {
- //OPT replaced with tailrecursive function to save on #closures
- // was:
- // var d = 0
- // for (tp <- tps) d = d max by(tp) //!!!OPT!!!
- // d
- def loop(tps: List[Type], acc: Int): Int = tps match {
- case tp :: rest => loop(rest, acc max by(tp))
- case _ => acc
- }
- loop(tps, 0)
- }
-
- private def typeDepth(tps: List[Type]): Int = maxDepth(tps, typeDepth)
- private def baseTypeSeqDepth(tps: List[Type]): Int = maxDepth(tps, _.baseTypeSeqDepth)
+ private def symTypeDepth(syms: List[Symbol]): Int = typeDepth(syms map (_.info))
+ private def typeDepth(tps: List[Type]): Int = maxDepth(tps)
+ private def baseTypeSeqDepth(tps: List[Type]): Int = maxBaseTypeSeqDepth(tps)
/** Is intersection of given types populated? That is,
* for all types tp1, tp2 in intersection
@@ -7020,6 +6993,45 @@ trait Types extends api.Types { self: SymbolTable =>
private[scala] val typeIsAny = (tp: Type) => tp.typeSymbolDirect eq AnyClass
private[scala] val typeIsHigherKinded = (tp: Type) => tp.isHigherKinded
+ /** The maximum depth of type `tp` */
+ def typeDepth(tp: Type): Int = tp match {
+ case TypeRef(pre, sym, args) =>
+ math.max(typeDepth(pre), typeDepth(args) + 1)
+ case RefinedType(parents, decls) =>
+ math.max(typeDepth(parents), symTypeDepth(decls.toList) + 1)
+ case TypeBounds(lo, hi) =>
+ math.max(typeDepth(lo), typeDepth(hi))
+ case MethodType(paramtypes, result) =>
+ typeDepth(result)
+ case NullaryMethodType(result) =>
+ typeDepth(result)
+ case PolyType(tparams, result) =>
+ math.max(typeDepth(result), symTypeDepth(tparams) + 1)
+ case ExistentialType(tparams, result) =>
+ math.max(typeDepth(result), symTypeDepth(tparams) + 1)
+ case _ =>
+ 1
+ }
+ //OPT replaced with tailrecursive function to save on #closures
+ // was:
+ // var d = 0
+ // for (tp <- tps) d = d max by(tp) //!!!OPT!!!
+ // d
+ private[scala] def maxDepth(tps: List[Type]): Int = {
+ @tailrec def loop(tps: List[Type], acc: Int): Int = tps match {
+ case tp :: rest => loop(rest, math.max(acc, typeDepth(tp)))
+ case _ => acc
+ }
+ loop(tps, 0)
+ }
+ private[scala] def maxBaseTypeSeqDepth(tps: List[Type]): Int = {
+ @tailrec def loop(tps: List[Type], acc: Int): Int = tps match {
+ case tp :: rest => loop(rest, math.max(acc, tp.baseTypeSeqDepth))
+ case _ => acc
+ }
+ loop(tps, 0)
+ }
+
@tailrec private def typesContain(tps: List[Type], sym: Symbol): Boolean = tps match {
case tp :: rest => (tp contains sym) || typesContain(rest, sym)
case _ => false