aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeComparer.scala
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2015-11-26 16:37:50 +0100
committerGuillaume Martres <smarter@ubuntu.com>2015-11-30 22:30:39 +0100
commit6e4b4f4dd2f09ce787dfb2da4ae9fffe2b30b07a (patch)
tree4f51b763651017d041a0a0b000517376d96e1a46 /src/dotty/tools/dotc/core/TypeComparer.scala
parent112564655f4f23552cb9ae48d0fdb7d8ac5b725c (diff)
downloaddotty-6e4b4f4dd2f09ce787dfb2da4ae9fffe2b30b07a.tar.gz
dotty-6e4b4f4dd2f09ce787dfb2da4ae9fffe2b30b07a.tar.bz2
dotty-6e4b4f4dd2f09ce787dfb2da4ae9fffe2b30b07a.zip
TypeComparer: delay looking up members of AndTypes
In ParFactory.scala we have checks that look like: (Foo { type Bar = X }) & (Foo { type Bar = X }) <:< (Foo { type Bar = X }) where `Foo` is a recursive type. Before this commit, we would first try to check this by looking up `Bar` in the `AndType` on the left, which means looking it up in both branches and then merging the result, but the merge requires more subtyping checks, which in turn require looking up a member inside an `AndType`, seemingly ad infinitum. We now avoid this by checking if either branch of the `AndType` on the left is a subtype of the `RefinedType` on the right before looking up a member in the `AndType` itself.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeComparer.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index d0abe86a7..1d9928e2d 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -331,17 +331,23 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
comparePolyParam
case tp2: RefinedType =>
+ def compareRefinedSlow: Boolean = {
+ val name2 = tp2.refinedName
+ isSubType(tp1, tp2.parent) &&
+ (name2 == nme.WILDCARD || hasMatchingMember(name2, tp1, tp2))
+ }
def compareRefined: Boolean = {
val tp1w = tp1.widen
val skipped2 = skipMatching(tp1w, tp2)
if ((skipped2 eq tp2) || !Config.fastPathForRefinedSubtype) {
- val name2 = tp2.refinedName
- val normalPath =
- isSubType(tp1, tp2.parent) &&
- ( name2 == nme.WILDCARD
- || hasMatchingMember(name2, tp1, tp2)
- || fourthTry(tp1, tp2)
- )
+ val normalPath = tp1 match {
+ case tp1: AndType =>
+ // Delay calling `compareRefinedSlow` because looking up a member
+ // of an `AndType` can lead to a cascade of subtyping checks
+ fourthTry(tp1, tp2) || compareRefinedSlow
+ case _ =>
+ compareRefinedSlow || fourthTry(tp1, tp2)
+ }
normalPath ||
needsEtaLift(tp1, tp2) && tp1.testLifted(tp2.typeParams, isSubType(_, tp2), classBounds(tp2))
}