summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-07-26 15:32:33 +0000
committerMartin Odersky <odersky@gmail.com>2007-07-26 15:32:33 +0000
commit0b34dfbcfec17eda8634ff4f68cfe75503592bbf (patch)
treeaf658af2ab3729e5f6b3e68311ba99f1638cfb7f
parentc61bd2d85cba92d1b297f9d78d92f44dc3604d80 (diff)
downloadscala-0b34dfbcfec17eda8634ff4f68cfe75503592bbf.tar.gz
scala-0b34dfbcfec17eda8634ff4f68cfe75503592bbf.tar.bz2
scala-0b34dfbcfec17eda8634ff4f68cfe75503592bbf.zip
Fixed bug1210
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala21
-rw-r--r--test/files/neg/bug1210.check7
-rwxr-xr-xtest/files/neg/bug1210.scala28
-rwxr-xr-xtest/files/pos/bug1210a.scala9
4 files changed, 62 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 2b7a02662e..740a3774f9 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1362,6 +1362,7 @@ A type's typeSymbol should never be inspected directly.
sym.info.typeParams.length == args.length) {
//transform(sym.info.resultType).normalize // cycles have been checked in typeRef
val xform=transform(sym.info.resultType)
+ assert(xform ne this, this)
if(xform eq this) xform else xform.normalize // @M TODO: why is this necessary?
}/* else if (!isHigherKinded) { // sym.info.typeParams.length != args.length
log("Error: normalizing "+sym.rawname+" with mismatch between type params "+sym.info.typeParams+" and args "+args)
@@ -1810,19 +1811,33 @@ A type's typeSymbol should never be inspected directly.
def mkConstantType(value: Constant): ConstantType =
unique(new ConstantType(value) with UniqueType)
- /** The canonical creator for typerefs */
+ /** The canonical creator for typerefs
+ * todo: see how we can clean this up a bit
+ */
def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
var sym1 = if (sym.isAbstractType) rebind(pre, sym) else sym
def transform(tp: Type): Type =
tp.resultType.asSeenFrom(pre, sym1.owner).instantiateTypeParams(sym1.typeParams, args)
-
if (sym1.isAliasType && sym1.info.typeParams.length == args.length) {
// note: we require that object is initialized,
// that's why we use info.typeParams instead of typeParams.
if (sym1.hasFlag(LOCKED))
throw new TypeError("illegal cyclic reference involving " + sym1)
sym1.setFlag(LOCKED)
- val result = transform(sym1.info)
+ //println("locking "+sym1+sym1.locationString+"/"+sym1.isAliasType+"/"+sym1.ownerChain)
+ def follow(tp: Type): Unit = transform(tp) match {
+ case tp2 @ TypeRef(_, sym2, _) =>
+ if (sym2.isAliasType) {
+ if (sym2.hasFlag(LOCKED))
+ throw new TypeError("illegal cyclic reference involving " + sym2)
+ sym2.setFlag(LOCKED)
+ follow(sym2.info)
+ sym2.resetFlag(LOCKED)
+ }
+ case _ =>
+ }
+ follow(sym1.info)
+ //println("unlocking "+sym1)
sym1.resetFlag(LOCKED)
//result // @M: original version -- this would expand the type alias immediately
rawTypeRef(pre, sym1, args) //@MAT -- don't expand type alias, but still check there are no cycles
diff --git a/test/files/neg/bug1210.check b/test/files/neg/bug1210.check
new file mode 100644
index 0000000000..4db920556f
--- /dev/null
+++ b/test/files/neg/bug1210.check
@@ -0,0 +1,7 @@
+bug1210.scala:13: error: illegal cyclic reference involving type Settings
+ val v: List[selfType] = f[selfType]((x: selfType) => x.v)
+ ^
+bug1210.scala:24: error: illegal cyclic reference involving type Settings
+ f[selfType](_.g)
+ ^
+two errors found
diff --git a/test/files/neg/bug1210.scala b/test/files/neg/bug1210.scala
new file mode 100755
index 0000000000..eb163a956e
--- /dev/null
+++ b/test/files/neg/bug1210.scala
@@ -0,0 +1,28 @@
+object Test
+{
+ def f[T](recurse: T => List[T]): List[T] =
+ {
+ Nil
+ }
+
+ abstract class M
+ { self =>
+ type Settings
+ type selfType = M {type Settings = self.Settings}
+
+ val v: List[selfType] = f[selfType]((x: selfType) => x.v)
+ }
+
+ abstract class M2
+ { self =>
+ type Settings
+ type selfType = M2 {type Settings = self.Settings}
+
+ def g: List[selfType] = Nil
+
+ {
+ f[selfType](_.g)
+ }
+ }
+}
+
diff --git a/test/files/pos/bug1210a.scala b/test/files/pos/bug1210a.scala
new file mode 100755
index 0000000000..a349a26753
--- /dev/null
+++ b/test/files/pos/bug1210a.scala
@@ -0,0 +1,9 @@
+object Test {
+ def id[T](f: T => T): T = error("bla")
+
+ abstract class M[Settings] {
+ type selfType = M[Settings]
+
+ val v: selfType = id[M.this.selfType](x => x.v)
+ }
+}