Skip to content

Commit 642c5e4

Browse files
committed
Fixed cycle detection.
Now detects the cycles reported by @retronym
1 parent 9d6c104 commit 642c5e4

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ object StdNames {
304304
val ArrayAnnotArg: N = "ArrayAnnotArg"
305305
val Constant: N = "Constant"
306306
val ConstantType: N = "ConstantType"
307+
val DummyHi: N = "DummyHi"
308+
val DummyLo: N = "DummyLo"
307309
val ExistentialTypeTree: N = "ExistentialTypeTree"
308310
val Flag : N = "Flag"
309311
val Ident: N = "Ident"

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ class Namer { typer: Typer =>
673673

674674
def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = {
675675
completeParams(tdef.tparams)
676-
sym.info = TypeBounds.empty // avoid cyclic reference errors for F-bounds
676+
setDummyInfo(sym)
677677
val tparamSyms = tdef.tparams map symbolOfTree
678678
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
679679
val toParameterize = tparamSyms.nonEmpty && !isDerived
@@ -690,4 +690,21 @@ class Namer { typer: Typer =>
690690
sym.info = NoCompleter
691691
checkNonCyclic(sym, unsafeInfo, reportErrors = true)
692692
}
693+
694+
/** Temporarily set info of defined type T to
695+
*
696+
* T >: dummyLo <: dummyHi
697+
* type dummyLo, dummyHi
698+
*
699+
* This is done to avoid cyclic reference errors for F-bounds.
700+
* The type is intentionally chosen so that it cannot possibly be
701+
* elided when taking a union or intersection.
702+
*/
703+
private def setDummyInfo(sym: Symbol)(implicit ctx: Context): Unit = {
704+
def dummyBound(name: TypeName) =
705+
ctx.newSymbol(sym.owner, name, Synthetic | Deferred, TypeBounds.empty)
706+
val dummyLo = dummyBound(tpnme.DummyLo)
707+
val dummyHi = dummyBound(tpnme.DummyHi)
708+
sym.info = TypeBounds(TypeRef(NoPrefix, dummyLo), TypeRef(NoPrefix, dummyHi))
709+
}
693710
}

test/dotc/tests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class tests extends CompilerTest {
104104
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
105105
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
106106
@Test def neg_t1569_failedAvoid = compileFile(negDir, "t1569-failedAvoid", xerrors = 1)
107-
@Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 6)
107+
@Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 8)
108108
@Test def neg_boundspropagation = compileFile(negDir, "boundspropagation", xerrors = 4)
109109

110110
@Test def dotc = compileDir(dotcDir + "tools/dotc", twice)(allowDeepSubtypes)

tests/neg/cycles.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,16 @@ class E {
2727
}
2828
val x: F#T = ???
2929
}
30+
31+
class T1 {
32+
type X = (U, U) // cycle
33+
type U = X & Int
34+
}
35+
class T2 {
36+
type X = (U, U) // cycle
37+
type U = X | Int
38+
}
39+
object T12 {
40+
??? : (T1 {})#U
41+
??? : (T2 {})#U
42+
}

0 commit comments

Comments
 (0)