aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/unpickleScala2
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-07-19 12:37:34 +0200
committerMartin Odersky <odersky@gmail.com>2015-09-18 18:07:27 +0200
commit47049965ce2b72e49b0d1ca29c10966f7d5012fb (patch)
treecd99305ee63d8efa4421cc1609a90d8972cf3319 /src/dotty/tools/dotc/core/unpickleScala2
parent3be3aa3bc8c8e37bdb1f1495e40cfe357f678f28 (diff)
downloaddotty-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')
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala27
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)