diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2015-11-26 16:37:50 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2015-11-30 22:30:39 +0100 |
commit | 6e4b4f4dd2f09ce787dfb2da4ae9fffe2b30b07a (patch) | |
tree | 4f51b763651017d041a0a0b000517376d96e1a46 | |
parent | 112564655f4f23552cb9ae48d0fdb7d8ac5b725c (diff) | |
download | dotty-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.
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 20 | ||||
-rw-r--r-- | test/dotc/scala-collections.whitelist | 4 |
2 files changed, 14 insertions, 10 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)) } diff --git a/test/dotc/scala-collections.whitelist b/test/dotc/scala-collections.whitelist index a0c9ce588..25ebe6694 100644 --- a/test/dotc/scala-collections.whitelist +++ b/test/dotc/scala-collections.whitelist @@ -287,9 +287,7 @@ ./scala-scala/src/library/scala/collection/generic/SortedMapFactory.scala ./scala-scala/src/library/scala/collection/generic/SortedSetFactory.scala ./scala-scala/src/library/scala/collection/generic/SetFactory.scala - -# deep subtype -#./scala-scala/src/library/scala/collection/generic/ParFactory.scala +./scala-scala/src/library/scala/collection/generic/ParFactory.scala # https://github.com/lampepfl/dotty/issues/974 #./scala-scala/src/library/scala/collection/generic/MutableSortedSetFactory.scala |