aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-06-04 18:07:05 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 13:35:00 +0200
commitae1f248ff407b231455a43ecbaf4751c0bb2bbaa (patch)
tree74baff811be9869c5079e37d32c00ccfae21019a /src
parentc136af18c1ff37663393e0ad738926776946679e (diff)
downloaddotty-ae1f248ff407b231455a43ecbaf4751c0bb2bbaa.tar.gz
dotty-ae1f248ff407b231455a43ecbaf4751c0bb2bbaa.tar.bz2
dotty-ae1f248ff407b231455a43ecbaf4751c0bb2bbaa.zip
Normalize RecTypes on creation to avoid cycles.
With this change, ski compiles (but with more errors than before). Without it, it goes into various infinite recursions.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index dadb5b95e..403b49da6 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2254,14 +2254,32 @@ object Types {
tp
}
*/
+
+ /** Create a RecType, normalizing its contents. This means:
+ *
+ * 1. Nested Rec types on the type's spine are merged with the outer one.
+ * 2. Any refinement of the form `type T = z.T` on the spine of the type
+ * where `z` refers to the created rec-type is replaced by
+ * `type T`. This avoids infinite recursons later when we
+ * try to follow these references.
+ * TODO: Figure out how to guarantee absence of cycles
+ * of length > 1
+ */
def apply(parentExp: RecType => Type)(implicit ctx: Context): RecType = {
- var rt = new RecType(parentExp)
- rt.parent match {
- case rt2: RecType =>
- rt = rt2.derivedRecType(rt2.parent.substRecThis(rt, RecThis(rt2)))
- case _ =>
+ val rt = new RecType(parentExp)
+ def normalize(tp: Type): Type = tp.stripTypeVar match {
+ case tp: RecType =>
+ normalize(tp.parent.substRecThis(tp, RecThis(rt)))
+ case tp @ RefinedType(parent, rname, rinfo) =>
+ val rinfo1 = rinfo match {
+ case TypeAlias(TypeRef(RecThis(`rt`), `rname`)) => TypeBounds.empty
+ case _ => rinfo
+ }
+ tp.derivedRefinedType(normalize(parent), rname, rinfo1)
+ case tp =>
+ tp
}
- unique(rt)
+ unique(rt.derivedRecType(normalize(rt.parent)))
}
def closeOver(parentExp: RecType => Type)(implicit ctx: Context) = {
val rt = this(parentExp)
@@ -2747,7 +2765,11 @@ object Types {
case that: RecThis => this.binder eq that.binder
case _ => false
}
- override def toString = s"RecThis(${binder.hashCode})"
+ override def toString =
+ try s"RecThis(${binder.hashCode})"
+ catch {
+ case ex: NullPointerException => s"RecThis(<under construction>)"
+ }
}
// ----- Skolem types -----------------------------------------------