Skip to content

Commit d778a3d

Browse files
committed
Avoid infinite recursions when checking F-bounded types
1 parent f663665 commit d778a3d

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import typer.RefChecks.{checkAllOverrides, checkSelfAgainstParents, OverridingPa
1414
import typer.Checking.{checkBounds, checkAppliedTypesIn}
1515
import typer.ErrorReporting.{Addenda, err}
1616
import typer.ProtoTypes.{AnySelectionProto, LhsProto}
17-
import util.{SimpleIdentitySet, EqHashMap, SrcPos, Property}
17+
import util.{SimpleIdentitySet, EqHashMap, EqHashSet, SrcPos, Property}
1818
import transform.SymUtils.*
1919
import transform.{Recheck, PreRecheck}
2020
import Recheck.*
@@ -147,6 +147,8 @@ object CheckCaptures:
147147
private def disallowRootCapabilitiesIn(tp: Type, carrier: Symbol, what: String, have: String, addendum: String, pos: SrcPos)(using Context) =
148148
val check = new TypeTraverser:
149149

150+
private val seen = new EqHashSet[TypeRef]
151+
150152
extension (tparam: Symbol) def isParametricIn(carrier: Symbol): Boolean =
151153
val encl = carrier.maybeOwner.enclosingMethodOrClass
152154
if encl.isClass then tparam.isParametricIn(encl)
@@ -160,19 +162,21 @@ object CheckCaptures:
160162
def traverse(t: Type) =
161163
t.dealiasKeepAnnots match
162164
case t: TypeRef =>
163-
capt.println(i"disallow $t, $tp, $what, ${t.isSealed}")
164-
t.info match
165-
case TypeBounds(_, hi) if !t.isSealed && !t.symbol.isParametricIn(carrier) =>
166-
if hi.isAny then
167-
report.error(
168-
em"""$what cannot $have $tp since
169-
|that type refers to the type variable $t, which is not sealed.
170-
|$addendum""",
171-
pos)
172-
else
173-
traverse(hi)
174-
case _ =>
175-
traverseChildren(t)
165+
if !seen.contains(t) then
166+
capt.println(i"disallow $t, $tp, $what, ${t.isSealed}")
167+
seen += t
168+
t.info match
169+
case TypeBounds(_, hi) if !t.isSealed && !t.symbol.isParametricIn(carrier) =>
170+
if hi.isAny then
171+
report.error(
172+
em"""$what cannot $have $tp since
173+
|that type refers to the type variable $t, which is not sealed.
174+
|$addendum""",
175+
pos)
176+
else
177+
traverse(hi)
178+
case _ =>
179+
traverseChildren(t)
176180
case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot =>
177181
()
178182
case t =>

0 commit comments

Comments
 (0)