Skip to content

Commit 2ea33a4

Browse files
authored
Merge pull request #10270 from dotty-staging/fix-#10256
Fix 10256: Avoid crashing in LazyRef.ref when checking for cycles
2 parents de3fbe2 + 0b52df2 commit 2ea33a4

File tree

4 files changed

+24
-16
lines changed

4 files changed

+24
-16
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ object Mode {
4141
*/
4242
val TypevarsMissContext: Mode = newMode(4, "TypevarsMissContext")
4343

44+
/** Are we looking for cyclic references? */
4445
val CheckCyclic: Mode = newMode(5, "CheckCyclic")
4546

4647
/** We are in a pattern alternative */

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,7 +2710,7 @@ object Types {
27102710
}
27112711
}
27122712

2713-
case class LazyRef(private var refFn: Context ?=> Type, reportCycles: Boolean = false) extends UncachedProxyType with ValueType {
2713+
case class LazyRef(private var refFn: Context ?=> Type) extends UncachedProxyType with ValueType {
27142714
private var myRef: Type = null
27152715
private var computed = false
27162716

@@ -2719,7 +2719,7 @@ object Types {
27192719
if myRef == null then
27202720
// if errors were reported previously handle this by throwing a CyclicReference
27212721
// instead of crashing immediately. A test case is neg/i6057.scala.
2722-
assert(reportCycles || ctx.reporter.errorsReported)
2722+
assert(ctx.mode.is(Mode.CheckCyclic) || ctx.reporter.errorsReported)
27232723
throw CyclicReference(NoDenotation)
27242724
else
27252725
computed = true
@@ -4545,7 +4545,9 @@ object Types {
45454545
else defn.AnyType // dummy type in case of errors
45464546
def refineSelfType(selfType: Type) =
45474547
RefinedType(selfType, sym.name,
4548-
TypeAlias(LazyRef(force, reportCycles = true)))
4548+
TypeAlias(
4549+
withMode(Mode.CheckCyclic)(
4550+
LazyRef(force))))
45494551
cinfo.selfInfo match
45504552
case self: Type =>
45514553
cinfo.derivedClassInfo(

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -406,21 +406,19 @@ object Checking {
406406
for (parent <- parents; mbr <- parent.abstractTypeMembers if qualifies(mbr.symbol))
407407
yield mbr.name.asTypeName
408408

409-
for (name <- abstractTypeNames)
410-
try {
411-
val mbr = joint.member(name)
412-
mbr.info match {
413-
case bounds: TypeBounds =>
414-
!checkNonCyclic(mbr.symbol, bounds, reportErrors = true).isError
415-
case _ =>
416-
true
417-
}
418-
}
419-
catch {
420-
case ex: RecursionOverflow =>
409+
withMode(Mode.CheckCyclic) {
410+
for name <- abstractTypeNames do
411+
try
412+
val mbr = joint.member(name)
413+
mbr.info match
414+
case bounds: TypeBounds =>
415+
!checkNonCyclic(mbr.symbol, bounds, reportErrors = true).isError
416+
case _ =>
417+
true
418+
catch case _: RecursionOverflow | _: CyclicReference =>
421419
report.error(em"cyclic reference involving type $name", pos)
422420
false
423-
}
421+
}
424422
}
425423

426424
/** Check that symbol's definition is well-formed. */

tests/neg/i10256.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait Foo[T <: Foo[T]] {
2+
type I <: Foo[I]
3+
}
4+
5+
trait Bar[T <: Foo[T]] extends Foo[T] { // error: cyclic
6+
self: T =>
7+
}

0 commit comments

Comments
 (0)