Skip to content

Commit

Permalink
Fix 1 cause of infinite recursion in the new provablyDisjoint.
Browse files Browse the repository at this point in the history
And add an additional test for another cause of infinite recursion
that was fixed earlier.
  • Loading branch information
sjrd committed Dec 18, 2023
1 parent 2dd9f45 commit ec097a9
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
18 changes: 16 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2808,8 +2808,22 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
val optGadtBounds = gadtBounds(sym)
if optGadtBounds != null then disjointnessBoundary(optGadtBounds.hi)
else disjointnessBoundary(tp.superTypeNormalized)
case tp @ AppliedType(tycon: TypeRef, _) if tycon.symbol.isClass =>
tp
case tp @ AppliedType(tycon: TypeRef, targs) if tycon.symbol.isClass =>
/* The theory says we should just return `tp` here. However, due to how
* baseType works (called from `isBaseTypeWithDisjointArguments`),
* it can create infinitely growing towers of `AnnotatedType`s. This
* defeats the infinite recursion detection with the `pending` set.
* Therefore, we eagerly remove all non-refining annotations. We are
* allowed to do that because they don't affect subtyping (so cannot
* create an ill-kinded `AppliedType`) and would anyway be stripped
* later on by the recursive calls to `provablyDisjoint`, though
* `disjointnessBoundary`).
* See tests/pos/provably-disjoint-infinite-recursion-1.scala for an example.
*/
tp.derivedAppliedType(
tycon,
targs.mapConserve(_.stripAnnots(keep = _.symbol.derivesFrom(defn.RefiningAnnotationClass)))
)
case tp: TermRef =>
val isEnumValue = tp.termSymbol.isAllOf(EnumCase, butNot = JavaDefined)
if isEnumValue then tp
Expand Down
4 changes: 4 additions & 0 deletions tests/pos/provably-disjoint-infinite-recursion-1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Test {
def isTraversableAgain(from: Iterator[Int]): Boolean =
from.isInstanceOf[Iterable[?]]
}
10 changes: 10 additions & 0 deletions tests/pos/provably-disjoint-infinite-recursion-2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type Tupled[A] <: Tuple = A match
case Tuple => A & Tuple
case _ => A *: EmptyTuple

enum Day:
case Saturday, Sunday

type Foo = Tupled[Day]

def foo(): Foo = Day.Saturday *: EmptyTuple

0 comments on commit ec097a9

Please sign in to comment.