From 55d3501efcf5704b9a77cbb770e5927bd479e213 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 8 Mar 2020 11:01:47 +0100 Subject: [PATCH 1/2] Fix #5876: Don't dereference pending LazyRefs when normalizing In monitoredIsSubType, don't dereference pending LazyRefs when normalizing a type to check whether it is in the log of seen types. --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Types.scala | 2 ++ tests/pos-deep-subtype/i5876.scala | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/pos-deep-subtype/i5876.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index acb545efdca4..d0ac4e275aad 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -210,9 +210,9 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w case t: LazyRef => // Dereference a lazyref to detect underlying matching types, but // be careful not to get into an infinite recursion. If recursion count - // exceeds `DerefLimit`, approximate with `NoType` instead. + // exceeds `DerefLimit`, approximate with `t` instead. derefCount += 1 - if (derefCount >= DerefLimit) NoType + if t.pending || derefCount >= DerefLimit then t else try mapOver(t.ref) finally derefCount -= 1 case tp: TypeVar => tp diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 4f627c815073..a050e633b3cd 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2578,6 +2578,8 @@ object Types { private var myRef: Type = null private var computed = false + def pending(using Context): Boolean = computed && myRef == null + def ref(implicit ctx: Context): Type = if computed then if myRef == null then diff --git a/tests/pos-deep-subtype/i5876.scala b/tests/pos-deep-subtype/i5876.scala new file mode 100644 index 000000000000..e8a510135dc4 --- /dev/null +++ b/tests/pos-deep-subtype/i5876.scala @@ -0,0 +1,9 @@ +type HasThisB[T] = HasThis { type This <: T } +trait HasThis { + type This >: this.type <: HasThisB[This] +} + +type FB[T] = F { type This <: T } +class F extends HasThis { + type This >: this.type <: FB[This] +} \ No newline at end of file From bbe2655d415279126e94be75c9db742028e5acf4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 8 Mar 2020 16:32:45 +0100 Subject: [PATCH 2/2] Drop redundant method --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 2 +- compiler/src/dotty/tools/dotc/core/Types.scala | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index d0ac4e275aad..c42db67be990 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -212,7 +212,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w // be careful not to get into an infinite recursion. If recursion count // exceeds `DerefLimit`, approximate with `t` instead. derefCount += 1 - if t.pending || derefCount >= DerefLimit then t + if t.evaluating || derefCount >= DerefLimit then t else try mapOver(t.ref) finally derefCount -= 1 case tp: TypeVar => tp diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index a050e633b3cd..4f627c815073 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2578,8 +2578,6 @@ object Types { private var myRef: Type = null private var computed = false - def pending(using Context): Boolean = computed && myRef == null - def ref(implicit ctx: Context): Type = if computed then if myRef == null then