diff options
author | Martin Odersky <odersky@gmail.com> | 2015-07-19 12:37:34 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-09-18 18:07:27 +0200 |
commit | 47049965ce2b72e49b0d1ca29c10966f7d5012fb (patch) | |
tree | cd99305ee63d8efa4421cc1609a90d8972cf3319 /src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | |
parent | 3be3aa3bc8c8e37bdb1f1495e40cfe357f678f28 (diff) | |
download | dotty-47049965ce2b72e49b0d1ca29c10966f7d5012fb.tar.gz dotty-47049965ce2b72e49b0d1ca29c10966f7d5012fb.tar.bz2 dotty-47049965ce2b72e49b0d1ca29c10966f7d5012fb.zip |
Avoid cycles when eliminating existentials in unpickling
New hk-scheme caused cycles in elimExistentials which are fixed
by this patch.
Diffstat (limited to 'src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index c0b5ab64b..68439846d 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -584,15 +584,35 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas * tp { name: T } */ def elimExistentials(boundSyms: List[Symbol], tp: Type)(implicit ctx: Context): Type = { + // Need to be careful not to run into cyclic references here (observed when + // comiling t247.scala). That's why we avoiud taking `symbol` of a TypeRef + // unless names match up. + val isBound = (tp: Type) => { + def refersTo(tp: Type, sym: Symbol): Boolean = tp match { + case tp @ TypeRef(_, name) => sym.name == name && sym == tp.symbol + case tp: TypeVar => refersTo(tp.underlying, sym) + case tp : LazyRef => refersTo(tp.ref, sym) + case _ => false + } + boundSyms.exists(refersTo(tp, _)) + } + // Cannot use standard `existsPart` method because it calls `lookupRefined` + // which can cause CyclicReference errors. + val isBoundAccumulator = new ExistsAccumulator(isBound) { + override def foldOver(x: Boolean, tp: Type): Boolean = tp match { + case tp: TypeRef => applyToPrefix(x, tp) + case _ => super.foldOver(x, tp) + } + } def removeSingleton(tp: Type): Type = if (tp isRef defn.SingletonClass) defn.AnyType else tp def elim(tp: Type): Type = tp match { case tp @ RefinedType(parent, name) => val parent1 = elim(tp.parent) tp.refinedInfo match { - case TypeAlias(info: TypeRef) if boundSyms contains info.symbol => + case TypeAlias(info: TypeRef) if isBound(info) => RefinedType(parent1, name, info.symbol.info) - case info: TypeRef if boundSyms contains info.symbol => + case info: TypeRef if isBound(info) => val info1 = info.symbol.info assert(info1.derivesFrom(defn.SingletonClass)) RefinedType(parent1, name, info1.mapReduceAnd(removeSingleton)(_ & _)) @@ -605,8 +625,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas tp } val tp1 = elim(tp) - val isBound = (tp: Type) => boundSyms contains tp.typeSymbol - if (tp1 existsPart isBound) { + if (isBoundAccumulator(false, tp1)) { val anyTypes = boundSyms map (_ => defn.AnyType) val boundBounds = boundSyms map (_.info.bounds.hi) val tp2 = tp1.subst(boundSyms, boundBounds).subst(boundSyms, anyTypes) |