aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-02-03 22:40:54 +0100
committerMartin Odersky <odersky@gmail.com>2014-02-03 22:41:03 +0100
commit4e34962fba727975c071d6288913d89b4692a08f (patch)
treee3ffccfe4f3c047149b32da1635ae749f8eecd4c /src
parent2a760aa7cee00829fe7b1649cad1efa5ddf8e259 (diff)
downloaddotty-4e34962fba727975c071d6288913d89b4692a08f.tar.gz
dotty-4e34962fba727975c071d6288913d89b4692a08f.tar.bz2
dotty-4e34962fba727975c071d6288913d89b4692a08f.zip
Commenting out unused alternative isSubType implementation.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala564
1 files changed, 283 insertions, 281 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 9e6982847..46caf3116 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -264,287 +264,6 @@ class TypeComparer(initctx: Context) extends DotClass {
}
}
-/* Alternative implementation of isSubType, currently put on hold. Did not work
- * out. Keep around for a while longer in case we want to mine it for ideas.
- */
-
- def compare(tp1: Type, tp2: Type): Boolean = ctx.debugTraceIndented(s"$tp1 <:< $tp2") {
- tp2 match {
- case tp2: ProtoType =>
- isMatchedByProto(tp2, tp1)
- case tp2: TypeVar =>
- isSubType(tp1, tp2.underlying)
- case tp2: WildcardType =>
- def compareWildcard = tp2.optBounds match {
- case TypeBounds(_, hi2) => isSubType(tp1, hi2)
- case NoType => true
- }
- compareWildcard
- case tp2: AnnotatedType =>
- isSubType(tp1, tp2.tpe) // todo: refine?
- case ErrorType =>
- true
- case AndType(left2, right2) =>
- isSubType(tp1, left2) && isSubType(tp1, right2)
- case _ =>
- compare1(tp1, tp2)
- }
- }
-
- def compare1(tp1: Type, tp2: Type): Boolean = {
- tp1 match {
- case tref1: TypeRef =>
- val sym1 = tref1.symbol
- tref1.info match {
- case TypeBounds(lo1, hi1) =>
- if (lo1 eq hi1) return compare(hi1, tp2)
- else if (sym1 is GADTFlexType)
- return isSubType(hi1, tp2) ||
- trySetType(tref1, TypeBounds(lo1, hi1 & tp2))
- case _ =>
- if ((sym1 eq NothingClass) && tp2.isInstanceOf[ValueType]) return true
- if ((sym1 eq NullClass) && tp2.dealias.typeSymbol.isNullableClass) return true
- }
- case param1: PolyParam if isConstrained(param1) =>
- def comparePoly = (
- param1 == tp2
- || isSubTypeWhenFrozen(bounds(param1).hi, tp2)
- || { if ((tp2 isRef defn.NothingClass) && ctx.typerState.isGlobalCommittable)
- ctx.log(s"!!! instantiating to Nothing: $tp1")
- addConstraint(param1, tp2, fromBelow = false)
- }
- )
- return comparePoly
- case tp1 @ ThisType(cls) if cls is ModuleClass =>
- tp2 match {
- case tp2: TermRef =>
- return tp2.symbol.moduleClass == cls && cls.owner.thisType <:< tp2.prefix
- case _ =>
- }
- case tp1: TypeVar =>
- return compare(tp1.underlying, tp2)
- case tp1: WildcardType =>
- def compareWildcard = tp1.optBounds match {
- case TypeBounds(lo1, _) => isSubType(lo1, tp2) // todo: use short-circuiting to current method more often?
- case NoType => true
- }
- return compareWildcard
- case tp1: AnnotatedType =>
- return isSubType(tp1.tpe, tp2)
- case ErrorType =>
- return true
- case OrType(left1, right1) =>
- return isSubType(left1, tp2) && isSubType(right1, tp2)
- case _ =>
- }
- rightIsSuper(tp1, tp2)
- }
-
- def rightIsSuper(tp1: Type, tp2: Type): Boolean = tp2 match {
- case tp2: NamedType =>
- def compareNamed: Boolean = {
- val sym2 = tp2.symbol
- val pre2 = tp2.prefix
- tp1 match {
- case tp1: NamedType =>
- val sym1 = tp1.symbol
- val pre1 = tp1.prefix
- if (sym1 == sym2) {
- if ( ctx.erasedTypes
- || sym1.isStaticOwner
- || isSubType(pre1, pre2)
- || pre1.isInstanceOf[ThisType] && pre2.isInstanceOf[ThisType]) return true
- } else if (tp1.name == tp2.name && isSubType(pre1, pre2)) return true
- case _ =>
- }
- if (sym2.isClass) {
- val base = tp1.baseType(sym2)
- if (base.exists && (base ne tp1)) isSubType(base, tp2)
- else
- (sym2 == defn.SingletonClass) && tp1.isStable ||
- (defn.hkTraits contains sym2) && isSubTypeHK(tp1.widen, tp2) ||
- leftIsSub2(tp1, tp2)
- }
- else tp2.info match {
- case TypeBounds(lo2, hi2) =>
- if (lo2 eq hi2)
- isSubType(tp1.dealias, hi2.dealias)
- else if (sym2 is GADTFlexType)
- isSubType(tp1, lo2) || trySetType(tp2, TypeBounds(lo2 | tp1, hi2))
- else {
- (frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2) ||
- leftIsSub(tp1, tp2)
- }
- case _ =>
- leftIsSub(tp1, tp2)
- }
- }
- compareNamed
-
- case tp2 @ RefinedType(parent2, name2) =>
- def matchRefinements(tp1: Type, tp2: Type, seen: Set[Name]): Type = tp1 match {
- case tp1 @ RefinedType(parent1, name1) if !(seen contains name1) =>
- tp2 match {
- case tp2 @ RefinedType(parent2, name2) if nameMatches(name1, name2, tp1, tp2) =>
- if (isSubType(tp1.refinedInfo, tp2.refinedInfo))
- matchRefinements(parent1, parent2, seen + name1)
- else NoType
- case _ => tp2
- }
- case _ => tp2
- }
- def compareRefined: Boolean = tp1.widen match {
- case tp1 @ RefinedType(parent1, name1) if nameMatches(name1, name2, tp1, tp2) =>
- // optimized case; all info on tp1.name2 is in refinement tp1.refinedInfo.
- isSubType(tp1.refinedInfo, tp2.refinedInfo) && {
- val ancestor2 = matchRefinements(parent1, parent2, Set.empty + name1)
- ancestor2.exists && isSubType(tp1, ancestor2)
- }
- case _ =>
- def hasMatchingMember(name: Name): Boolean = traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}") (
- tp1.member(name).hasAltWith(alt => isSubType(alt.info, tp2.refinedInfo))
- ||
- { // special case for situations like:
- // foo <: C { type T = foo.T }
- tp2.refinedInfo match {
- case TypeBounds(lo, hi) if lo eq hi =>
- val ref = tp1 select name
- isSubType(ref, lo) && isSubType(hi, ref)
- case _ => false
- }
- }
- ||
- name.isHkParamName && {
- val idx = name.hkParamIndex
- val tparams = tp1.typeParams
- idx < tparams.length && hasMatchingMember(tparams(idx).name)
- }
- )
- isSubType(tp1, parent2) && (
- name2 == nme.WILDCARD
- || hasMatchingMember(name2)
- || leftIsSub2(tp1, tp2))
- }
- compareRefined
-
- case param2: PolyParam =>
- def comparePoly =
- param2 == tp1 || {
- if (isConstrained(param2))
- isSubTypeWhenFrozen(tp1, bounds(param2).lo) ||
- addConstraint(param2, tp1.widen, fromBelow = true)
- else
- (ctx.mode is Mode.TypevarsMissContext) ||
- isNonBottomSubType(tp1, bounds(param2).lo) ||
- leftIsSub(tp1, tp2)
- }
- comparePoly
-
- case ThisType(cls) if (cls is ModuleClass) =>
- def compareThis: Boolean = {
- tp1 match {
- case tp1: TermRef =>
- if (tp1.symbol.moduleClass == cls)
- return tp1.prefix <:< cls.owner.thisType
- case _ =>
- }
- leftIsSub(tp1, tp2)
- }
- compareThis
-
- case tp2: BoundType =>
- tp1 == tp2 || leftIsSub(tp1, tp2)
- case OrType(tp21, tp22) =>
- isSubType(tp1, tp21) || isSubType(tp1, tp22)
-
- case tp2 @ MethodType(_, formals2) =>
- def compareMethod = tp1 match {
- case tp1 @ MethodType(_, formals1) =>
- tp1.signature == tp2.signature &&
- (if (Config.newMatch) subsumeParams(formals1, formals2, tp1.isJava, tp2.isJava)
- else matchingParams(formals1, formals2, tp1.isJava, tp2.isJava)) &&
- tp1.isImplicit == tp2.isImplicit && // needed?
- isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
- case _ =>
- false
- }
- compareMethod
-
- case tp2: PolyType =>
- def comparePoly = tp1 match {
- case tp1: PolyType =>
- (tp1.signature sameParams tp2.signature) &&
- matchingTypeParams(tp1, tp2) &&
- isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
- case _ =>
- false
- }
- comparePoly
-
- case tp2 @ ExprType(restpe2) =>
- def compareExpr = tp1 match {
- // We allow ()T to be a subtype of => T.
- // We need some subtype relationship between them so that e.g.
- // def toString and def toString() don't clash when seen
- // as members of the same type. And it seems most logical to take
- // ()T <:< => T, since everything one can do with a => T one can
- // also do with a ()T by automatic () insertion.
- case tp1 @ MethodType(Nil, _) => isSubType(tp1.resultType, restpe2)
- case _ => isSubType(tp1.widenExpr, restpe2)
- }
- compareExpr
-
- case tp2 @ TypeBounds(lo2, hi2) =>
- def compareBounds = tp1 match {
- case tp1 @ TypeBounds(lo1, hi1) =>
- val v = tp1.variance + tp2.variance
- ((v > 0) || (lo2 isRef NothingClass) || isSubType(lo2, lo1)) &&
- ((v < 0) || (hi2 isRef AnyClass) || isSubType(hi1, hi2))
- case tp1: ClassInfo =>
- val tt = tp1.typeRef
- isSubType(lo2, tt) && isSubType(tt, hi2)
- case _ =>
- false
- }
- compareBounds
-
- case ClassInfo(pre2, cls2, _, _, _) =>
- def compareClassInfo = tp1 match {
- case ClassInfo(pre1, cls1, _, _, _) =>
- (cls1 eq cls2) && isSubType(pre2, pre1)
- case _ =>
- false
- }
- compareClassInfo
-
- case _ =>
- leftIsSub(tp1, tp2)
- }
-
- def leftIsSub(tp1: Type, tp2: Type): Boolean = tp1 match {
- case tp1: TypeRef =>
- tp1.info match {
- case TypeBounds(lo1, hi1) => isSubType(hi1, tp2)
- case _ => false
- }
- case tp1: SingletonType =>
- isSubType(tp1.underlying.widenExpr, tp2)
- case tp1: RefinedType =>
- isSubType(tp1.parent, tp2)
- case _ =>
- leftIsSub2(tp1, tp2)
- }
-
- def leftIsSub2(tp1: Type, tp2: Type): Boolean = tp1 match {
- case param1: PolyParam =>
- assert(!isConstrained(param1))
- (ctx.mode is Mode.TypevarsMissContext) || isSubType(bounds(param1).hi, tp2)
- case AndType(tp11, tp12) =>
- isSubType(tp11, tp2) || isSubType(tp12, tp2)
- case _ =>
- false
- }
-
def firstTry(tp1: Type, tp2: Type): Boolean = {
tp2 match {
case tp2: NamedType =>
@@ -1421,3 +1140,286 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
override def toString = "Subtype trace:" + { try b.toString finally b.clear() }
}
+
+/* Alternative implementation of isSubType, currently put on hold. Did not work
+ * out. Keep around for a while longer in case we want to mine it for ideas.
+
+
+ def compare(tp1: Type, tp2: Type): Boolean = ctx.debugTraceIndented(s"$tp1 <:< $tp2") {
+ tp2 match {
+ case tp2: ProtoType =>
+ isMatchedByProto(tp2, tp1)
+ case tp2: TypeVar =>
+ isSubType(tp1, tp2.underlying)
+ case tp2: WildcardType =>
+ def compareWildcard = tp2.optBounds match {
+ case TypeBounds(_, hi2) => isSubType(tp1, hi2)
+ case NoType => true
+ }
+ compareWildcard
+ case tp2: AnnotatedType =>
+ isSubType(tp1, tp2.tpe) // todo: refine?
+ case ErrorType =>
+ true
+ case AndType(left2, right2) =>
+ isSubType(tp1, left2) && isSubType(tp1, right2)
+ case _ =>
+ compare1(tp1, tp2)
+ }
+ }
+
+ def compare1(tp1: Type, tp2: Type): Boolean = {
+ tp1 match {
+ case tref1: TypeRef =>
+ val sym1 = tref1.symbol
+ tref1.info match {
+ case TypeBounds(lo1, hi1) =>
+ if (lo1 eq hi1) return compare(hi1, tp2)
+ else if (sym1 is GADTFlexType)
+ return isSubType(hi1, tp2) ||
+ trySetType(tref1, TypeBounds(lo1, hi1 & tp2))
+ case _ =>
+ if ((sym1 eq NothingClass) && tp2.isInstanceOf[ValueType]) return true
+ if ((sym1 eq NullClass) && tp2.dealias.typeSymbol.isNullableClass) return true
+ }
+ case param1: PolyParam if isConstrained(param1) =>
+ def comparePoly = (
+ param1 == tp2
+ || isSubTypeWhenFrozen(bounds(param1).hi, tp2)
+ || { if ((tp2 isRef defn.NothingClass) && ctx.typerState.isGlobalCommittable)
+ ctx.log(s"!!! instantiating to Nothing: $tp1")
+ addConstraint(param1, tp2, fromBelow = false)
+ }
+ )
+ return comparePoly
+ case tp1 @ ThisType(cls) if cls is ModuleClass =>
+ tp2 match {
+ case tp2: TermRef =>
+ return tp2.symbol.moduleClass == cls && cls.owner.thisType <:< tp2.prefix
+ case _ =>
+ }
+ case tp1: TypeVar =>
+ return compare(tp1.underlying, tp2)
+ case tp1: WildcardType =>
+ def compareWildcard = tp1.optBounds match {
+ case TypeBounds(lo1, _) => isSubType(lo1, tp2) // todo: use short-circuiting to current method more often?
+ case NoType => true
+ }
+ return compareWildcard
+ case tp1: AnnotatedType =>
+ return isSubType(tp1.tpe, tp2)
+ case ErrorType =>
+ return true
+ case OrType(left1, right1) =>
+ return isSubType(left1, tp2) && isSubType(right1, tp2)
+ case _ =>
+ }
+ rightIsSuper(tp1, tp2)
+ }
+
+ def rightIsSuper(tp1: Type, tp2: Type): Boolean = tp2 match {
+ case tp2: NamedType =>
+ def compareNamed: Boolean = {
+ val sym2 = tp2.symbol
+ val pre2 = tp2.prefix
+ tp1 match {
+ case tp1: NamedType =>
+ val sym1 = tp1.symbol
+ val pre1 = tp1.prefix
+ if (sym1 == sym2) {
+ if ( ctx.erasedTypes
+ || sym1.isStaticOwner
+ || isSubType(pre1, pre2)
+ || pre1.isInstanceOf[ThisType] && pre2.isInstanceOf[ThisType]) return true
+ } else if (tp1.name == tp2.name && isSubType(pre1, pre2)) return true
+ case _ =>
+ }
+ if (sym2.isClass) {
+ val base = tp1.baseType(sym2)
+ if (base.exists && (base ne tp1)) isSubType(base, tp2)
+ else
+ (sym2 == defn.SingletonClass) && tp1.isStable ||
+ (defn.hkTraits contains sym2) && isSubTypeHK(tp1.widen, tp2) ||
+ leftIsSub2(tp1, tp2)
+ }
+ else tp2.info match {
+ case TypeBounds(lo2, hi2) =>
+ if (lo2 eq hi2)
+ isSubType(tp1.dealias, hi2.dealias)
+ else if (sym2 is GADTFlexType)
+ isSubType(tp1, lo2) || trySetType(tp2, TypeBounds(lo2 | tp1, hi2))
+ else {
+ (frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2) ||
+ leftIsSub(tp1, tp2)
+ }
+ case _ =>
+ leftIsSub(tp1, tp2)
+ }
+ }
+ compareNamed
+
+ case tp2 @ RefinedType(parent2, name2) =>
+ def matchRefinements(tp1: Type, tp2: Type, seen: Set[Name]): Type = tp1 match {
+ case tp1 @ RefinedType(parent1, name1) if !(seen contains name1) =>
+ tp2 match {
+ case tp2 @ RefinedType(parent2, name2) if nameMatches(name1, name2, tp1, tp2) =>
+ if (isSubType(tp1.refinedInfo, tp2.refinedInfo))
+ matchRefinements(parent1, parent2, seen + name1)
+ else NoType
+ case _ => tp2
+ }
+ case _ => tp2
+ }
+ def compareRefined: Boolean = tp1.widen match {
+ case tp1 @ RefinedType(parent1, name1) if nameMatches(name1, name2, tp1, tp2) =>
+ // optimized case; all info on tp1.name2 is in refinement tp1.refinedInfo.
+ isSubType(tp1.refinedInfo, tp2.refinedInfo) && {
+ val ancestor2 = matchRefinements(parent1, parent2, Set.empty + name1)
+ ancestor2.exists && isSubType(tp1, ancestor2)
+ }
+ case _ =>
+ def hasMatchingMember(name: Name): Boolean = traceIndented(s"hasMatchingMember($name) ${tp1.member(name)}") (
+ tp1.member(name).hasAltWith(alt => isSubType(alt.info, tp2.refinedInfo))
+ ||
+ { // special case for situations like:
+ // foo <: C { type T = foo.T }
+ tp2.refinedInfo match {
+ case TypeBounds(lo, hi) if lo eq hi =>
+ val ref = tp1 select name
+ isSubType(ref, lo) && isSubType(hi, ref)
+ case _ => false
+ }
+ }
+ ||
+ name.isHkParamName && {
+ val idx = name.hkParamIndex
+ val tparams = tp1.typeParams
+ idx < tparams.length && hasMatchingMember(tparams(idx).name)
+ }
+ )
+ isSubType(tp1, parent2) && (
+ name2 == nme.WILDCARD
+ || hasMatchingMember(name2)
+ || leftIsSub2(tp1, tp2))
+ }
+ compareRefined
+
+ case param2: PolyParam =>
+ def comparePoly =
+ param2 == tp1 || {
+ if (isConstrained(param2))
+ isSubTypeWhenFrozen(tp1, bounds(param2).lo) ||
+ addConstraint(param2, tp1.widen, fromBelow = true)
+ else
+ (ctx.mode is Mode.TypevarsMissContext) ||
+ isNonBottomSubType(tp1, bounds(param2).lo) ||
+ leftIsSub(tp1, tp2)
+ }
+ comparePoly
+
+ case ThisType(cls) if (cls is ModuleClass) =>
+ def compareThis: Boolean = {
+ tp1 match {
+ case tp1: TermRef =>
+ if (tp1.symbol.moduleClass == cls)
+ return tp1.prefix <:< cls.owner.thisType
+ case _ =>
+ }
+ leftIsSub(tp1, tp2)
+ }
+ compareThis
+
+ case tp2: BoundType =>
+ tp1 == tp2 || leftIsSub(tp1, tp2)
+ case OrType(tp21, tp22) =>
+ isSubType(tp1, tp21) || isSubType(tp1, tp22)
+
+ case tp2 @ MethodType(_, formals2) =>
+ def compareMethod = tp1 match {
+ case tp1 @ MethodType(_, formals1) =>
+ tp1.signature == tp2.signature &&
+ (if (Config.newMatch) subsumeParams(formals1, formals2, tp1.isJava, tp2.isJava)
+ else matchingParams(formals1, formals2, tp1.isJava, tp2.isJava)) &&
+ tp1.isImplicit == tp2.isImplicit && // needed?
+ isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
+ case _ =>
+ false
+ }
+ compareMethod
+
+ case tp2: PolyType =>
+ def comparePoly = tp1 match {
+ case tp1: PolyType =>
+ (tp1.signature sameParams tp2.signature) &&
+ matchingTypeParams(tp1, tp2) &&
+ isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
+ case _ =>
+ false
+ }
+ comparePoly
+
+ case tp2 @ ExprType(restpe2) =>
+ def compareExpr = tp1 match {
+ // We allow ()T to be a subtype of => T.
+ // We need some subtype relationship between them so that e.g.
+ // def toString and def toString() don't clash when seen
+ // as members of the same type. And it seems most logical to take
+ // ()T <:< => T, since everything one can do with a => T one can
+ // also do with a ()T by automatic () insertion.
+ case tp1 @ MethodType(Nil, _) => isSubType(tp1.resultType, restpe2)
+ case _ => isSubType(tp1.widenExpr, restpe2)
+ }
+ compareExpr
+
+ case tp2 @ TypeBounds(lo2, hi2) =>
+ def compareBounds = tp1 match {
+ case tp1 @ TypeBounds(lo1, hi1) =>
+ val v = tp1.variance + tp2.variance
+ ((v > 0) || (lo2 isRef NothingClass) || isSubType(lo2, lo1)) &&
+ ((v < 0) || (hi2 isRef AnyClass) || isSubType(hi1, hi2))
+ case tp1: ClassInfo =>
+ val tt = tp1.typeRef
+ isSubType(lo2, tt) && isSubType(tt, hi2)
+ case _ =>
+ false
+ }
+ compareBounds
+
+ case ClassInfo(pre2, cls2, _, _, _) =>
+ def compareClassInfo = tp1 match {
+ case ClassInfo(pre1, cls1, _, _, _) =>
+ (cls1 eq cls2) && isSubType(pre2, pre1)
+ case _ =>
+ false
+ }
+ compareClassInfo
+
+ case _ =>
+ leftIsSub(tp1, tp2)
+ }
+
+ def leftIsSub(tp1: Type, tp2: Type): Boolean = tp1 match {
+ case tp1: TypeRef =>
+ tp1.info match {
+ case TypeBounds(lo1, hi1) => isSubType(hi1, tp2)
+ case _ => false
+ }
+ case tp1: SingletonType =>
+ isSubType(tp1.underlying.widenExpr, tp2)
+ case tp1: RefinedType =>
+ isSubType(tp1.parent, tp2)
+ case _ =>
+ leftIsSub2(tp1, tp2)
+ }
+
+ def leftIsSub2(tp1: Type, tp2: Type): Boolean = tp1 match {
+ case param1: PolyParam =>
+ assert(!isConstrained(param1))
+ (ctx.mode is Mode.TypevarsMissContext) || isSubType(bounds(param1).hi, tp2)
+ case AndType(tp11, tp12) =>
+ isSubType(tp11, tp2) || isSubType(tp12, tp2)
+ case _ =>
+ false
+ }
+
+*/