Skip to content

Commit bf1ea23

Browse files
committed
Fix 2 causes of infinite recursion in the new provablyDisjoint.
1 parent 75295fa commit bf1ea23

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2808,8 +2808,22 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28082808
val optGadtBounds = gadtBounds(sym)
28092809
if optGadtBounds != null then disjointnessBoundary(optGadtBounds.hi)
28102810
else disjointnessBoundary(tp.superTypeNormalized)
2811-
case tp @ AppliedType(tycon: TypeRef, _) if tycon.symbol.isClass =>
2812-
tp
2811+
case tp @ AppliedType(tycon: TypeRef, targs) if tycon.symbol.isClass =>
2812+
/* The theory says we should just return `tp` here. However, due to how
2813+
* baseType works (called from `isBaseTypeWithDisjointArguments`),
2814+
* it can create infinitely growing towers of `AnnotatedType`s. This
2815+
* defeats the infinite recursion detection with the `pending` set.
2816+
* Therefore, we eagerly remove all non-refining annotations. We are
2817+
* allowed to do that because they don't affect subtyping (so cannot
2818+
* create an ill-kinded `AppliedType`) and would anyway be stripped
2819+
* later on by the recursive calls to `provablyDisjoint`, though
2820+
* `disjointnessBoundary`).
2821+
* See tests/pos/provably-disjoint-infinite-recursion-1.scala for an example.
2822+
*/
2823+
tp.derivedAppliedType(
2824+
tycon,
2825+
targs.mapConserve(_.stripAnnots(keep = _.symbol.derivesFrom(defn.RefiningAnnotationClass)))
2826+
)
28132827
case tp: TermRef =>
28142828
val isEnumValue = tp.termSymbol.isAllOf(EnumCase, butNot = JavaDefined)
28152829
if isEnumValue then tp
@@ -2957,7 +2971,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
29572971
cls.children.map { child =>
29582972
if child.isTerm then child.info.classSymbol
29592973
else child
2960-
}
2974+
}.filter(_ != cls)
29612975

29622976
// TODO? Special-case for Nothing and Null? We probably need Nothing/Null disjoint from Nothing/Null
29632977
def eitherDerivesFromOther(cls1: Symbol, cls2: Symbol): Boolean =
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Test {
2+
def isTraversableAgain(from: Iterator[Int]): Boolean =
3+
from.isInstanceOf[Iterable[?]]
4+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type Tupled[A] <: Tuple = A match
2+
case Tuple => A & Tuple
3+
case _ => A *: EmptyTuple
4+
5+
enum Day:
6+
case Saturday, Sunday
7+
8+
type Foo = Tupled[Day]
9+
10+
def foo(): Foo = Day.Saturday *: EmptyTuple

0 commit comments

Comments
 (0)