aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-11-24 17:17:27 +0100
committerMartin Odersky <odersky@gmail.com>2014-11-24 17:17:27 +0100
commit642c5e4500abfc5cef51eee7ed0a98930a24312f (patch)
treeeeda27483b71058860e364ca675bc3a835ebe2cb
parent9d6c1040448c48dac2ac3f292fd1e3b65b061b78 (diff)
downloaddotty-642c5e4500abfc5cef51eee7ed0a98930a24312f.tar.gz
dotty-642c5e4500abfc5cef51eee7ed0a98930a24312f.tar.bz2
dotty-642c5e4500abfc5cef51eee7ed0a98930a24312f.zip
Fixed cycle detection.
Now detects the cycles reported by @retronym
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala19
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/cycles.scala13
4 files changed, 34 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 8393eb56f..e17b655f9 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -304,6 +304,8 @@ object StdNames {
val ArrayAnnotArg: N = "ArrayAnnotArg"
val Constant: N = "Constant"
val ConstantType: N = "ConstantType"
+ val DummyHi: N = "DummyHi"
+ val DummyLo: N = "DummyLo"
val ExistentialTypeTree: N = "ExistentialTypeTree"
val Flag : N = "Flag"
val Ident: N = "Ident"
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index bc64e10fc..7490e88e9 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -673,7 +673,7 @@ class Namer { typer: Typer =>
def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = {
completeParams(tdef.tparams)
- sym.info = TypeBounds.empty // avoid cyclic reference errors for F-bounds
+ setDummyInfo(sym)
val tparamSyms = tdef.tparams map symbolOfTree
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
val toParameterize = tparamSyms.nonEmpty && !isDerived
@@ -690,4 +690,21 @@ class Namer { typer: Typer =>
sym.info = NoCompleter
checkNonCyclic(sym, unsafeInfo, reportErrors = true)
}
+
+ /** Temporarily set info of defined type T to
+ *
+ * T >: dummyLo <: dummyHi
+ * type dummyLo, dummyHi
+ *
+ * This is done to avoid cyclic reference errors for F-bounds.
+ * The type is intentionally chosen so that it cannot possibly be
+ * elided when taking a union or intersection.
+ */
+ private def setDummyInfo(sym: Symbol)(implicit ctx: Context): Unit = {
+ def dummyBound(name: TypeName) =
+ ctx.newSymbol(sym.owner, name, Synthetic | Deferred, TypeBounds.empty)
+ val dummyLo = dummyBound(tpnme.DummyLo)
+ val dummyHi = dummyBound(tpnme.DummyHi)
+ sym.info = TypeBounds(TypeRef(NoPrefix, dummyLo), TypeRef(NoPrefix, dummyHi))
+ }
} \ No newline at end of file
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 30de5e15d..1c437e833 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -104,7 +104,7 @@ class tests extends CompilerTest {
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
@Test def neg_t1569_failedAvoid = compileFile(negDir, "t1569-failedAvoid", xerrors = 1)
- @Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 6)
+ @Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 8)
@Test def neg_boundspropagation = compileFile(negDir, "boundspropagation", xerrors = 4)
@Test def dotc = compileDir(dotcDir + "tools/dotc", twice)(allowDeepSubtypes)
diff --git a/tests/neg/cycles.scala b/tests/neg/cycles.scala
index dbcbe1efb..0dd24c309 100644
--- a/tests/neg/cycles.scala
+++ b/tests/neg/cycles.scala
@@ -27,3 +27,16 @@ class E {
}
val x: F#T = ???
}
+
+class T1 {
+ type X = (U, U) // cycle
+ type U = X & Int
+}
+class T2 {
+ type X = (U, U) // cycle
+ type U = X | Int
+}
+object T12 {
+ ??? : (T1 {})#U
+ ??? : (T2 {})#U
+}