aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-02-24 11:52:57 +0100
committerMartin Odersky <odersky@gmail.com>2014-02-24 18:56:48 +0100
commit91e74ee45c8cedac279ec66f8277c94d05f2f2e3 (patch)
tree988e65878c5f7a891288486d1e20da751283c18a
parent23969f6e10a16b51d23c3da3f29b4f7edaef6e5a (diff)
downloaddotty-91e74ee45c8cedac279ec66f8277c94d05f2f2e3.tar.gz
dotty-91e74ee45c8cedac279ec66f8277c94d05f2f2e3.tar.bz2
dotty-91e74ee45c8cedac279ec66f8277c94d05f2f2e3.zip
Performance improvement: Streamline successful toplevel subtype checks
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala25
-rw-r--r--src/dotty/tools/dotc/core/Types.scala17
2 files changed, 20 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 720d0b41d..0da8f7174 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -8,7 +8,7 @@ import Decorators._
import StdNames.{nme, tpnme}
import collection.mutable
import printing.Disambiguation.disambiguated
-import util.{SimpleMap, Stats, DotClass}
+import util.{Stats, DotClass}
import config.Config
import config.Printers._
@@ -56,6 +56,7 @@ class TypeComparer(initctx: Context) extends DotClass {
private var myNothingClass: ClassSymbol = null
private var myNullClass: ClassSymbol = null
private var myObjectClass: ClassSymbol = null
+ private var myAnyType: TypeRef = null
def AnyClass = {
if (myAnyClass == null) myAnyClass = defn.AnyClass
@@ -73,6 +74,10 @@ class TypeComparer(initctx: Context) extends DotClass {
if (myObjectClass == null) myObjectClass = defn.ObjectClass
myObjectClass
}
+ def AnyType = {
+ if (myAnyType == null) myAnyType = AnyClass.typeRef
+ myAnyType
+ }
/** Update constraint for `param` to `bounds`, check that
* new constraint is still satisfiable.
@@ -178,6 +183,14 @@ class TypeComparer(initctx: Context) extends DotClass {
inst
}
+ def topLevelSubType(tp1: Type, tp2: Type): Boolean = {
+ if (tp2 eq NoType) return false
+ if ((tp2 eq tp1) ||
+ (tp2 eq WildcardType) ||
+ (tp2 eq AnyType) && tp1.isValueType) return true
+ isSubType(tp1, tp2)
+ }
+
def isSubTypeWhenFrozen(tp1: Type, tp2: Type): Boolean = {
val saved = frozenConstraint
frozenConstraint = true
@@ -189,7 +202,7 @@ class TypeComparer(initctx: Context) extends DotClass {
!(tp2 isRef NothingClass) && isSubType(tp1, tp2)
def isSubType(tp1: Type, tp2: Type): Boolean = /*>|>*/ ctx.traceIndented(s"isSubType ${tp1.show} <:< ${tp2.show}", subtyping) /*<|<*/ {
- if (tp1 == NoType || tp2 == NoType) false
+ if (tp2 eq NoType) false
else if (tp1 eq tp2) true
else {
val saved = constraint
@@ -216,7 +229,7 @@ class TypeComparer(initctx: Context) extends DotClass {
successCount = savedSuccessCount
}
else if (recCount == 0) {
- if (needsGc) ctx.typerState.gc()
+ if (needsGc) state.gc()
Stats.record("successful subType", successCount)
Stats.record("total subType", totalCount)
successCount = 0
@@ -247,7 +260,7 @@ class TypeComparer(initctx: Context) extends DotClass {
def monitoredIsSubType(tp1: Type, tp2: Type) = {
if (pendingSubTypes == null) {
pendingSubTypes = new mutable.HashSet[(Type, Type)]
- ctx.log(s"!!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${ctx.typerState.constraint.show}")
+ ctx.log(s"!!! deep subtype recursion involving ${tp1.show} <:< ${tp2.show}, constraint = ${state.constraint.show}")
ctx.log(s"!!! constraint = ${constraint.show}")
assert(!Config.flagDeepSubTypeRecursions)
if (Config.traceDeepSubTypeRecursions && !this.isInstanceOf[ExplainingTypeComparer])
@@ -337,7 +350,7 @@ class TypeComparer(initctx: Context) extends DotClass {
addConstraint(tp1, tp2, fromBelow = false) && {
if ((!frozenConstraint) &&
(tp2 isRef defn.NothingClass) &&
- ctx.typerState.isGlobalCommittable) {
+ state.isGlobalCommittable) {
def msg = s"!!! instantiated to Nothing: $tp1, constraint = ${constraint.show}"
if (Config.flagInstantiationToNothing) assert(false, msg)
else ctx.log(msg)
@@ -1174,7 +1187,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
def comparePoly = (
param1 == tp2
|| isSubTypeWhenFrozen(bounds(param1).hi, tp2)
- || { if ((tp2 isRef defn.NothingClass) && ctx.typerState.isGlobalCommittable)
+ || { if ((tp2 isRef defn.NothingClass) && state.isGlobalCommittable)
ctx.log(s"!!! instantiating to Nothing: $tp1")
addConstraint(param1, tp2, fromBelow = false)
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index c1d3de582..00d719acb 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -466,7 +466,7 @@ object Types {
/** Is this type a subtype of that type? */
final def <:<(that: Type)(implicit ctx: Context): Boolean = track("<:<") {
- ctx.typeComparer.isSubType(this, that)
+ ctx.typeComparer.topLevelSubType(this, that)
}
/** Is this type the same as that type?
@@ -2263,21 +2263,6 @@ object Types {
case SuperType(thistp, supertp) =>
this(this(x, thistp), supertp)
- case bounds @ TypeBounds(lo, hi) =>
- if (lo eq hi) {
- val saved = variance
- variance = variance * bounds.variance
- val result = this(x, lo)
- variance = saved
- result
- }
- else {
- variance = -variance
- val y = this(x, lo)
- variance = -variance
- this(y, hi)
- }
-
case tp @ ClassInfo(prefix, _, _, _, _) =>
this(x, prefix)