diff options
author | Martin Odersky <odersky@gmail.com> | 2014-01-23 10:59:51 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-01-26 18:52:33 +0100 |
commit | a00702c69d21480a34aabca38c41277f6813fc52 (patch) | |
tree | f12bd23a5016466b2f2238b287724c66583c230d /src | |
parent | 47b36b45455ecd73853dc63e9e047833cf4612c5 (diff) | |
download | dotty-a00702c69d21480a34aabca38c41277f6813fc52.tar.gz dotty-a00702c69d21480a34aabca38c41277f6813fc52.tar.bz2 dotty-a00702c69d21480a34aabca38c41277f6813fc52.zip |
Prune useless subtyping tests.
To make this work we moved the basetype test to thirdTryNamed where the lhs does not need to be a named type.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 0cf94c829..0794b842b 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -511,13 +511,8 @@ class TypeComparer(initctx: Context) extends DotClass { || isSubType(pre1, pre2) || pre1.isInstanceOf[ThisType] && pre2.isInstanceOf[ThisType] ) - else ( + else tp1.name == tp2.name && isSubType(pre1, pre2) - || sym2.isClass && { - val base = tp1.baseType(sym2) - base.exists && (base ne tp1) && isSubType(base, tp2) - } - ) ) || thirdTryNamed(tp1, tp2) case _ => secondTry(tp1, tp2) @@ -616,10 +611,14 @@ class TypeComparer(initctx: Context) extends DotClass { || fourthTry(tp1, tp2)) case _ => val cls2 = tp2.symbol - (cls2 == defn.SingletonClass && tp1.isStable + cls2.isClass && { + val base = tp1.baseType(cls2) + (base.exists && (base ne tp1) && isSubType(base, tp2) + || cls2 == defn.SingletonClass && tp1.isStable || cls2 == defn.NotNullClass && tp1.isNotNull || (defn.hkTraits contains cls2) && isSubTypeHK(tp1, tp2) - || fourthTry(tp1, tp2)) + ) + } || fourthTry(tp1, tp2) } def thirdTry(tp1: Type, tp2: Type): Boolean = tp2 match { @@ -722,15 +721,38 @@ class TypeComparer(initctx: Context) extends DotClass { (tp1.symbol eq NullClass) && tp2.dealias.typeSymbol.isNullableClass } case tp1: SingletonType => - isSubType(tp1.underlying.widenExpr, tp2) + isNewSubType(tp1.underlying.widenExpr, tp2) case tp1: RefinedType => - isSubType(tp1.parent, tp2) + isNewSubType(tp1.parent, tp2) case AndType(tp11, tp12) => - isSubType(tp11, tp2) || isSubType(tp12, tp2) + isNewSubType(tp11, tp2) || isNewSubType(tp12, tp2) case _ => false } + /** Like tp1 <:< tp2, but returns false immediately if we know that + * the case was covered previouslky during subtyping. + */ + private def isNewSubType(tp1: Type, tp2: Type): Boolean = + if (isCovered(tp1) && isCovered(tp2)) { + //println(s"useless subtype: $tp1 <:< $tp2") + false + } + else isSubType(tp1, tp2) + + /** A type has been covered previously in subtype check if it + * is some combination of TypeRefs that point to classes, where the + * combiners are RefinedTypes, AndTypes or AnnotatedTypes. + */ + private def isCovered(tp: Type): Boolean = tp.dealias.stripTypeVar match { + case tp: TypeRef => tp.symbol.isClass && tp.symbol != NothingClass && tp.symbol != NullClass + case tp: ProtoType => false + case tp: RefinedType => isCovered(tp.parent) + case tp: AnnotatedType => isCovered(tp.underlying) + case AndType(tp1, tp2) => isCovered(tp1) && isCovered(tp2) + case _ => false + } + /** The current bounds of type parameter `param` */ def bounds(param: PolyParam): TypeBounds = constraint at param match { case bounds: TypeBounds if !ignoreConstraint => bounds |