aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-31 10:36:42 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-31 11:44:17 +0100
commit3edab6ec1444b19203381612fba3e16ca1bafc95 (patch)
tree7e1985909b62c47004aeb29017bc05375eeba39d /src/dotty/tools/dotc/core/TypeComparer.scala
parent4a175b13e4fcefc7cb3cf70da254205a14dc2418 (diff)
downloaddotty-3edab6ec1444b19203381612fba3e16ca1bafc95.tar.gz
dotty-3edab6ec1444b19203381612fba3e16ca1bafc95.tar.bz2
dotty-3edab6ec1444b19203381612fba3e16ca1bafc95.zip
Upgrades to handle subtyping between parameterized and higher-kinded types.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala29
1 files changed, 25 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 5dbfc894d..7e04a2812 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -249,7 +249,10 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp1: PolyParam =>
(tp1 == tp2) ||
isSubTypeWhenFrozen(bounds(tp1).hi, tp2) || {
- assert(frozenConstraint || !(tp2 isRef defn.NothingClass)) // !!!DEBUG
+ if (!frozenConstraint &&
+ (tp2 isRef defn.NothingClass) &&
+ ctx.typerState.isGlobalCommittable)
+ ctx.log(s"!!! instantiating to Nothing: $tp1")
if (constraint contains tp1) addConstraint(tp1, tp2.dealias, fromBelow = false)
else thirdTry(tp1, tp2)
}
@@ -287,12 +290,12 @@ class TypeComparer(initctx: Context) extends DotClass {
case tp2: NamedType =>
thirdTryNamed(tp1, tp2)
case tp2 @ RefinedType(parent2, name2) =>
- tp1 match {
- case tp1 @ RefinedType(parent1, name1) if (name1 == name2) && name1.isTypeName =>
+ 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, parent2) && isSubType(tp1.refinedInfo, tp2.refinedInfo)
case _ =>
- def hasMatchingMember(name: Name): Boolean = traceIndented(s"hasMatchingMember($name)") (
+ 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:
@@ -408,6 +411,24 @@ class TypeComparer(initctx: Context) extends DotClass {
case _ => proto.isMatchedBy(tp)
}
+ /** Tow refinement names match if they are the same or one is the
+ * name of a type parameter of its parent type, and the other is
+ * the corresponding higher-kinded parameter name
+ */
+ private def nameMatches(name1: Name, name2: Name, tp1: Type, tp2: Type) =
+ name1.isTypeName &&
+ (name1 == name2 || isHKAlias(name1, name2, tp2) || isHKAlias(name2, name1, tp1))
+
+ /** Is name1 a higher-kinded parameter name and name2 a corresponding
+ * type parameter name?
+ */
+ private def isHKAlias(name1: Name, name2: Name, tp2: Type) =
+ name1.isHkParamName && {
+ val i = name1.hkParamIndex
+ val tparams = tp2.safeUnderlyingTypeParams
+ i < tparams.length && tparams(i).name == name2
+ }
+
/** Can type `tp` be constrained from above by adding a constraint to
* a typevar that it refers to? In that case we have to be careful not
* to approximate with the lower bound of a type in `thridTryNamed`. Instead,