From 4977571dd1aac2125652ad8d848e89432b4f8ca8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Jul 2017 19:54:16 +0200 Subject: [PATCH 1/2] Fix #2140: Avoid exponential subtype complexity Avoid exponential subtype complexity arising from revisiting |-types unnecessarily. --- .../dotty/tools/dotc/core/TypeComparer.scala | 2 +- tests/pending/pos/i2140.scala | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/pending/pos/i2140.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 7bdec511655c..a0a917b4449f 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -993,7 +993,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp: ProtoType => false case tp: RefinedOrRecType => isCovered(tp.parent) case tp: AnnotatedType => isCovered(tp.underlying) - case AndType(tp1, tp2) => isCovered(tp1) && isCovered(tp2) + case tp: AndOrType => isCovered(tp.tp1) && isCovered(tp.tp2) case _ => false } diff --git a/tests/pending/pos/i2140.scala b/tests/pending/pos/i2140.scala new file mode 100644 index 000000000000..ffd5f6339835 --- /dev/null +++ b/tests/pending/pos/i2140.scala @@ -0,0 +1,30 @@ +object Test { + def main(args: Array[String]): Unit = { + val s = 1 + val t = 23 match { + case 0 => (s) + case 1 => (s, s) + case 2 => (s, s, s) + case 3 => (s, s, s, s) + case 4 => (s, s, s, s, s) + case 5 => (s, s, s, s, s, s) + case 6 => (s, s, s, s, s, s, s) + case 7 => (s, s, s, s, s, s, s, s) + case 8 => (s, s, s, s, s, s, s, s, s) + case 9 => (s, s, s, s, s, s, s, s, s, s) + case 10 => (s, s, s, s, s, s, s, s, s, s, s) + case 11 => (s, s, s, s, s, s, s, s, s, s, s, s) + case 12 => (s, s, s, s, s, s, s, s, s, s, s, s, s) + case 13 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 14 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 15 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 16 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 17 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 18 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 19 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 20 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + case 21 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) +// case 22 => (s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s) + } + } +} From a048e50c3fa2e571489490682220309df48c1cd4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 19 Jul 2017 21:26:59 +0200 Subject: [PATCH 2/2] Fix docs and eliminate redundant case in isCovered. --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a0a917b4449f..4e911eed5bf4 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -983,14 +983,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** A type has been covered previously in subtype checking if it * is some combination of TypeRefs that point to classes, where the - * combiners are RefinedTypes, RecTypes, AndTypes or AnnotatedTypes. - * One exception: Refinements referring to basetype args are never considered - * to be already covered. This is necessary because such refined types might - * still need to be compared with a compareAliasRefined. + * combiners are RefinedTypes, RecTypes, And/Or-Types or AnnotatedTypes. */ - private def isCovered(tp: Type): Boolean = tp.dealias.stripTypeVar match { + private def isCovered(tp: Type): Boolean = tp.dealias.stripTypeVar match { case tp: TypeRef => tp.symbol.isClass && tp.symbol != NothingClass && tp.symbol != NullClass - case tp: ProtoType => false case tp: RefinedOrRecType => isCovered(tp.parent) case tp: AnnotatedType => isCovered(tp.underlying) case tp: AndOrType => isCovered(tp.tp1) && isCovered(tp.tp2)