diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/Types.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 212 |
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. |