diff options
author | Martin Odersky <odersky@gmail.com> | 2016-06-04 18:07:05 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-07-11 13:35:00 +0200 |
commit | ae1f248ff407b231455a43ecbaf4751c0bb2bbaa (patch) | |
tree | 74baff811be9869c5079e37d32c00ccfae21019a /src | |
parent | c136af18c1ff37663393e0ad738926776946679e (diff) | |
download | dotty-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.scala | 36 |
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 ----------------------------------------------- |