summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/Types.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/Types.scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala212
1 files changed, 143 insertions, 69 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index d87a30f847..be537010f6 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -9,10 +9,12 @@ package symtab
import scala.collection.immutable
import scala.collection.mutable.{ListBuffer, HashMap, WeakHashMap}
-import scala.tools.nsc.ast.TreeGen
-import scala.tools.nsc.util.{HashSet, Position, NoPosition}
+import ast.TreeGen
+import util.{HashSet, Position, NoPosition}
+import util.Statistics._
import Flags._
+
/* A standard type pattern match:
case ErrorType =>
// internal: error
@@ -64,16 +66,7 @@ trait Types {
//statistics
- var singletonBaseTypeSeqCount = 0
- var compoundBaseTypeSeqCount = 0
- var typerefBaseTypeSeqCount = 0
- var findMemberCount = 0
- var noMemberCount = 0
- var multMemberCount = 0
- var findMemberNanos = 0l
- var subtypeCount = 0
- var sametypeCount = 0
- var subtypeNanos = 0l
+ def uniqueTypeCount = if (uniques == null) 0 else uniques.size
private var explainSwitch = false
@@ -499,9 +492,13 @@ trait Types {
*/
def asSeenFrom(pre: Type, clazz: Symbol): Type =
if (!isTrivial && (!phase.erasedTypes || pre.typeSymbol == ArrayClass)) {
+ incCounter(asSeenFromCount)
+ val start = startTimer(asSeenFromNanos)
val m = new AsSeenFromMap(pre.normalize, clazz)
val tp = m apply this
- existentialAbstraction(m.capturedParams, tp)
+ val result = existentialAbstraction(m.capturedParams, tp)
+ stopTimer(asSeenFromNanos, start)
+ result
} else this
/** The info of `sym', seen as a member of this type.
@@ -597,31 +594,36 @@ trait Types {
/** Is this type a subtype of that type? */
def <:<(that: Type): Boolean = {
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
-// val result =
- ((this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth)))
-// if (util.Statistics.enabled) {
-// subtypeNanos += System.nanoTime() - startTime
-// subtypeCount += 1
-// }
-// result
+ if (util.Statistics.enabled) stat_<:<(that)
+ else
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ }
+
+ def stat_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
+ (this eq that) ||
+ (if (explainSwitch) explain("<:", isSubType, this, that)
+ else isSubType(this, that, AnyDepth))
+ stopTimer(subtypeNanos, start)
+ result
}
/** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
*/
- def weak_<:<(that: Type): Boolean =
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
-// val result =
+ def weak_<:<(that: Type): Boolean = {
+ incCounter(subtypeCount)
+ val start = startTimer(subtypeNanos)
+ val result =
((this eq that) ||
(if (explainSwitch) explain("weak_<:", isWeakSubType, this, that)
else isWeakSubType(this, that)))
-// if (util.Statistics.enabled) {
-// subtypeNanos += System.nanoTime() - startTime
-// subtypeCount += 1
-// }
-// result
+ stopTimer(subtypeNanos, start)
+ result
+ }
/** Is this type equivalent to that type? */
def =:=(that: Type): Boolean = (
@@ -785,15 +787,17 @@ trait Types {
// See (t0851) for a situation where this happens.
if (!this.isGround)
return typeVarToOriginMap(this).findMember(name, excludedFlags, requiredFlags, stableOnly)
- if (util.Statistics.enabled) findMemberCount += 1
-// val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l
+
+ incCounter(findMemberCount)
+ val start = startTimer(findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
var members: Scope = null
var member: Symbol = NoSymbol
var excluded = excludedFlags | DEFERRED
- var self: Type = null
var continue = true
+ lazy val self: Type = this.narrow
+ lazy val membertpe = self.memberType(member)
while (continue) {
continue = false
val bcs0 = baseClasses
@@ -812,29 +816,27 @@ trait Types {
sym.getFlag(PRIVATE | LOCAL) != (PRIVATE | LOCAL).toLong ||
(bcs0.head.hasTransOwner(bcs.head)))) {
if (name.isTypeName || stableOnly && sym.isStable) {
-// if (util.Statistics.enabled) findMemberNanos += System.nanoTime() - startTime
+ stopTimer(findMemberNanos, start)
return sym
} else if (member == NoSymbol) {
member = sym
} else if (members eq null) {
+// val start = startTimer(timer1)
if (member.name != sym.name ||
!(member == sym ||
member.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow;
- (self.memberType(member) matches self.memberType(sym))
- })) {
+ !sym.hasFlag(PRIVATE) &&
+ (membertpe matches self.memberType(sym)))) {
members = new Scope(List(member, sym))
}
+// stopTimer(timer1, start)
} else {
var prevEntry = members.lookupEntry(sym.name)
while ((prevEntry ne null) &&
!(prevEntry.sym == sym ||
prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow;
- (self.memberType(prevEntry.sym) matches self.memberType(sym))
- })) {
+ !sym.hasFlag(PRIVATE) &&
+ (self.memberType(prevEntry.sym) matches self.memberType(sym)))) {
prevEntry = members lookupNextEntry prevEntry
}
if (prevEntry eq null) {
@@ -852,14 +854,13 @@ trait Types {
} // while (!bcs.isEmpty)
excluded = excludedFlags
} // while (continue)
-// if (util.Statistics.enabled) findMemberNanos += System.nanoTime() - startTime
+ stopTimer(findMemberNanos, start)
if (members eq null) {
- if (util.Statistics.enabled) if (member == NoSymbol) noMemberCount += 1;
+ if (member == NoSymbol) incCounter(noMemberCount)
member
} else {
- if (util.Statistics.enabled) multMemberCount += 1;
- //val pre = if (this.typeSymbol.isClass) this.typeSymbol.thisType else this;
- (baseClasses.head.newOverloaded(this, members.toList))
+ incCounter(multMemberCount)
+ baseClasses.head.newOverloaded(this, members.toList)
}
}
@@ -970,7 +971,7 @@ trait Types {
override def isVolatile = underlying.isVolatile
override def widen: Type = underlying.widen
override def baseTypeSeq: BaseTypeSeq = {
- if (util.Statistics.enabled) singletonBaseTypeSeqCount += 1
+ incCounter(singletonBaseTypeSeqCount)
underlying.baseTypeSeq prepend this
}
override def safeToString: String = prefixString + "type"
@@ -1179,8 +1180,7 @@ trait Types {
val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq
baseTypeSeqCache = bts lateMap paramToVar
} else {
- if (util.Statistics.enabled)
- compoundBaseTypeSeqCount += 1
+ incCounter(compoundBaseTypeSeqCount)
baseTypeSeqCache = undetBaseTypeSeq
baseTypeSeqCache = memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe)
}
@@ -1711,13 +1711,11 @@ A type's typeSymbol should never be inspected directly.
if (period != currentPeriod) {
baseTypeSeqPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- if (util.Statistics.enabled)
- typerefBaseTypeSeqCount += 1
+ incCounter(typerefBaseTypeSeqCount)
baseTypeSeqCache = undetBaseTypeSeq
baseTypeSeqCache =
if (sym.isAbstractType) transform(bounds.hi).baseTypeSeq prepend this
else sym.info.baseTypeSeq map transform
-
}
}
if (baseTypeSeqCache == undetBaseTypeSeq)
@@ -1796,7 +1794,7 @@ A type's typeSymbol should never be inspected directly.
case class MethodType(override val params: List[Symbol],
override val resultType: Type) extends Type {
override val isTrivial: Boolean =
- paramTypes.forall(_.isTrivial) && resultType.isTrivial
+ params.forall(_.tpe.isTrivial) && resultType.isTrivial
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
override def paramSectionCount: Int = resultType.paramSectionCount + 1
@@ -1910,6 +1908,10 @@ A type's typeSymbol should never be inspected directly.
override def boundSyms: List[Symbol] = quantified
override def prefix = maybeRewrap(underlying.prefix)
override def typeArgs = underlying.typeArgs map maybeRewrap
+ override def params = underlying.params mapConserve { param =>
+ val tpe1 = rewrap(param.tpe)
+ if (tpe1 eq param.tpe) param else param.cloneSymbol.setInfo(tpe1)
+ }
override def paramTypes = underlying.paramTypes map maybeRewrap
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
// maybeRewrap(underlying.instantiateTypeParams(formals, actuals))
@@ -2642,9 +2644,8 @@ A type's typeSymbol should never be inspected directly.
private var uniques: HashSet[AnyRef] = _
private var uniqueRunId = NoRunId
- def uniqueTypeCount = if (uniques == null) 0 else uniques.size // for statistics
-
private def unique[T <: AnyRef](tp: T): T = {
+ incCounter(rawTypeCount)
if (uniqueRunId != currentRunId) {
uniques = new HashSet("uniques", initialUniquesCapacity)
uniqueRunId = currentRunId
@@ -3531,6 +3532,7 @@ A type's typeSymbol should never be inspected directly.
class MissingAliasException extends Exception
val missingAliasException = new MissingAliasException
+ class MissingTypeException extends Exception
object adaptToNewRunMap extends TypeMap {
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
@@ -3542,7 +3544,8 @@ A type's typeSymbol should never be inspected directly.
var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
if (rebind0 == NoSymbol) {
if (sym.isAliasType) throw missingAliasException
- assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
+ throw new MissingTypeException // For build manager purposes
+ //assert(false, pre+"."+sym+" does no longer exist, phase = "+phase)
}
/** The two symbols have the same fully qualified name */
def corresponds(sym1: Symbol, sym2: Symbol): Boolean =
@@ -3588,6 +3591,8 @@ A type's typeSymbol should never be inspected directly.
} catch {
case ex: MissingAliasException =>
apply(tp.dealias)
+ case _: MissingTypeException =>
+ NoType
}
}
case MethodType(params, restp) =>
@@ -3757,7 +3762,7 @@ A type's typeSymbol should never be inspected directly.
/** Do `tp1' and `tp2' denote equivalent types?
*/
def isSameType(tp1: Type, tp2: Type): Boolean = try {
- sametypeCount += 1
+ incCounter(sametypeCount)
subsametypeRecursions += 1
undoLog undoUnless {
isSameType0(tp1, tp2)
@@ -4149,7 +4154,7 @@ A type's typeSymbol should never be inspected directly.
tp1 match {
case MethodType(params1, res1) =>
(params1.length == params2.length &&
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
(res1 <:< res2) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType])
case _ =>
@@ -4242,13 +4247,71 @@ A type's typeSymbol should never be inspected directly.
}
/** A function implementing `tp1' matches `tp2' */
- def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ final def matchesType(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
+ def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
+ tparams1.length == tparams2.length &&
+ matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
+ def lastTry =
+ tp2 match {
+ case ExistentialType(_, res2) if alwaysMatchSimple =>
+ matchesType(tp1, res2, true)
+ case MethodType(_, _) =>
+ false
+ case PolyType(tparams2, res2) =>
+ tparams2.isEmpty && matchesType(tp1, res2, alwaysMatchSimple)
+ case _ =>
+ alwaysMatchSimple || tp1 =:= tp2
+ }
+ tp1 match {
+ case MethodType(params1, res1) =>
+ tp2 match {
+ case MethodType(params2, res2) =>
+ params1.length == params2.length && // useful pre-secreening optimization
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ matchesType(res1, res2, alwaysMatchSimple) &&
+ tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
+ case PolyType(List(), res2) =>
+ if (params1.isEmpty) matchesType(res1, res2, alwaysMatchSimple)
+ else matchesType(tp1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ false
+ }
+ case PolyType(tparams1, res1) =>
+ tp2 match {
+ case PolyType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case MethodType(List(), res2) if (tparams1.isEmpty) =>
+ matchesType(res1, res2, alwaysMatchSimple)
+ case ExistentialType(_, res2) =>
+ alwaysMatchSimple && matchesType(tp1, res2, true)
+ case _ =>
+ tparams1.isEmpty && matchesType(res1, tp2, alwaysMatchSimple)
+ }
+ case ExistentialType(tparams1, res1) =>
+ tp2 match {
+ case ExistentialType(tparams2, res2) =>
+ matchesQuantified(tparams1, tparams2, res1, res2)
+ case _ =>
+ if (alwaysMatchSimple) matchesType(res1, tp2, true)
+ else lastTry
+ }
+ case _ =>
+ lastTry
+ }
+ }
+
+/** matchesType above is an optimized version of the following implementation:
+
+ def matchesType2(tp1: Type, tp2: Type, alwaysMatchSimple: Boolean): Boolean = {
def matchesQuantified(tparams1: List[Symbol], tparams2: List[Symbol], res1: Type, res2: Type): Boolean =
tparams1.length == tparams2.length &&
matchesType(res1, res2.substSym(tparams2, tparams1), alwaysMatchSimple)
(tp1, tp2) match {
case (MethodType(params1, res1), MethodType(params2, res2)) =>
- matchingParams(tp1.paramTypes, tp2.paramTypes, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
+ params1.length == params2.length && // useful pre-secreening optimization
+ matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) &&
matchesType(res1, res2, alwaysMatchSimple) &&
tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType]
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
@@ -4275,14 +4338,25 @@ A type's typeSymbol should never be inspected directly.
alwaysMatchSimple || tp1 =:= tp2
}
}
+*/
- /** Are `tps1' and `tps2' lists of pairwise equivalent types? */
- private def matchingParams(tps1: List[Type], tps2: List[Type], tps1isJava: Boolean, tps2isJava: Boolean): Boolean =
- (tps1.length == tps2.length) &&
- ((tps1, tps2).zipped forall ((tp1, tp2) =>
- (tp1 =:= tp2) ||
- tps1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
- tps2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass))
+ /** Are `syms1' and `syms2' parameter lists with pairwise equivalent types? */
+ private def matchingParams(syms1: List[Symbol], syms2: List[Symbol], syms1isJava: Boolean, syms2isJava: Boolean): Boolean = syms1 match {
+ case Nil =>
+ syms2.isEmpty
+ case sym1 :: rest1 =>
+ syms2 match {
+ case Nil =>
+ false
+ case sym2 :: rest2 =>
+ val tp1 = sym1.tpe
+ val tp2 = sym2.tpe
+ (tp1 =:= tp2 ||
+ syms1isJava && tp2.typeSymbol == ObjectClass && tp1.typeSymbol == AnyClass ||
+ syms2isJava && tp1.typeSymbol == ObjectClass && tp2.typeSymbol == AnyClass) &&
+ matchingParams(rest1, rest2, syms1isJava, syms2isJava)
+ }
+ }
/** like map2, but returns list `xs' itself - instead of a copy - if function
* `f' maps all elements to themselves.