aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala108
1 files changed, 66 insertions, 42 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 52abc99a3..51c6f7271 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -307,6 +307,11 @@ class TypeComparer(initctx: Context) extends DotClass {
}
}
+ private def narrowRefined(tp: Type): Type = tp match {
+ case tp: RefinedType => RefinedThis(tp)
+ case _ => tp
+ }
+
/** If the prefix of a named type is `this` (i.e. an instance of type
* `ThisType` or `RefinedThis`), and there is a refinement type R that
* "refines" (transitively contains as its parent) a class reference
@@ -650,52 +655,71 @@ class TypeComparer(initctx: Context) extends DotClass {
}
compareNamed
case tp2 @ RefinedType(parent2, name2) =>
+ def qualifies(m: SingleDenotation) = isSubType(m.info, tp2.refinedInfo)
+ def memberMatches(mbr: Denotation): Boolean = mbr match { // inlined hasAltWith for performance
+ case mbr: SingleDenotation => qualifies(mbr)
+ case _ => mbr hasAltWith qualifies
+ }
+ def compareRefinedSlow: Boolean = {
+ def hasMatchingMember(name: Name): Boolean = /*>|>*/ ctx.traceIndented(s"hasMatchingMember($name) ${tp1.member(name).info.show}", subtyping) /*<|<*/ {
+ val tp1r = rebaseQual(tp1, name)
+ (memberMatches(narrowRefined(tp1r) member name)
+ ||
+ { // special case for situations like:
+ // foo <: C { type T = foo.T }
+ tp2.refinedInfo match {
+ case TypeBounds(lo, hi) if lo eq hi =>
+ !ctx.phase.erasedTypes && (tp1r select name) =:= lo
+ case _ => false
+ }
+ })
+ }
+ val matchesParent = {
+ val saved = pendingRefinedBases
+ try {
+ addPendingName(name2, tp2, tp2)
+ isSubType(tp1, parent2)
+ } finally pendingRefinedBases = saved
+ }
+ (matchesParent && (
+ name2 == nme.WILDCARD
+ || hasMatchingMember(name2)
+ || fourthTry(tp1, tp2))
+ || needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2)))
+ }
def compareRefined: Boolean = tp1.widen match {
case tp1 @ RefinedType(parent1, name1) if name1 == name2 && name1.isTypeName =>
- // optimized case; all info on tp1.name1 is in refinement tp1.refinedInfo.
- isSubType(normalizedInfo(tp1), tp2.refinedInfo) && {
- val saved = pendingRefinedBases
- try {
- addPendingName(name1, tp1, tp2)
- isSubType(parent1, parent2)
- }
- finally pendingRefinedBases = saved
+ normalizedInfo(tp1) match {
+ case bounds1 @ TypeBounds(lo1, hi1) =>
+ val fastResult = isSubType(bounds1, tp2.refinedInfo) && {
+ val saved = pendingRefinedBases
+ try {
+ addPendingName(name1, tp1, tp2)
+ isSubType(parent1, parent2)
+ } finally pendingRefinedBases = saved
+ }
+ if (lo1 eq hi1) fastResult
+ else {
+ val slowResult = compareRefinedSlow
+ if (fastResult != slowResult) {
+ println(i"!!! difference for $tp1 <: $tp2, fast = $fastResult, ${memberMatches(tp1.member(name1))}, slow = $slowResult ${lo1.getClass} ${hi1.getClass}")
+ println(TypeComparer.explained(implicit ctx => tp1 <:< parent2))
+ val tp1r = rebaseQual(tp1, name1)
+ println(s"rebased = $tp1r / ${narrowRefined(tp1r)}")
+ val mbr = narrowRefined(tp1r) member name1
+ println(i"member = $mbr : ${mbr.info} / ${mbr.getClass}")
+ val mbr2 = (tp1r) member name1
+ println(i"member = $mbr2 : ${mbr2.info} / ${mbr2.getClass}")
+ println(TypeComparer.explained(implicit ctx => mbr.info <:< tp2.refinedInfo))
+ compareRefinedSlow
+ }
+ slowResult
+ }
+ case _ =>
+ compareRefinedSlow
}
case _ =>
- def qualifies(m: SingleDenotation) = isSubType(m.info, tp2.refinedInfo)
- def memberMatches(mbr: Denotation): Boolean = mbr match { // inlined hasAltWith for performance
- case mbr: SingleDenotation => qualifies(mbr)
- case _ => mbr hasAltWith qualifies
- }
- def hasMatchingMember(name: Name): Boolean = /*>|>*/ ctx.traceIndented(s"hasMatchingMember($name) ${tp1.member(name).info.show}", subtyping) /*<|<*/ {
- val tp1r = rebaseQual(tp1, name)
- ( memberMatches(tp1r member name)
- ||
- { // special case for situations like:
- // foo <: C { type T = foo.T }
- tp2.refinedInfo match {
- case TypeBounds(lo, hi) if lo eq hi =>
- !ctx.phase.erasedTypes && (tp1r select name) =:= lo
- case _ => false
- }
- }
- )
- }
- val matchesParent = {
- val saved = pendingRefinedBases
- try {
- addPendingName(name2, tp2, tp2)
- isSubType(tp1, parent2)
- }
- finally pendingRefinedBases = saved
- }
- ( matchesParent && (
- name2 == nme.WILDCARD
- || hasMatchingMember(name2)
- || fourthTry(tp1, tp2)
- )
- || needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2))
- )
+ compareRefinedSlow
}
compareRefined
case OrType(tp21, tp22) =>