diff options
author | Martin Odersky <odersky@gmail.com> | 2014-08-08 16:12:01 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-08-08 18:32:33 +0200 |
commit | 058729ceac3354a2cc34490b528e76afb09ee0ce (patch) | |
tree | 2b98e78b607c7f0438ebd2eac8b68f5a72b46a04 /src/dotty/tools/dotc/core | |
parent | f87153bc5d74f66e2fcf22dc7282da31813430da (diff) | |
download | dotty-058729ceac3354a2cc34490b528e76afb09ee0ce.tar.gz dotty-058729ceac3354a2cc34490b528e76afb09ee0ce.tar.bz2 dotty-058729ceac3354a2cc34490b528e76afb09ee0ce.zip |
LazyRefs break cycles for unpickled types
Insert LazyRefs to break cycles for F-bounded types that
are unpickled or read from Java signatures.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 7 |
4 files changed, 26 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index fd47ee4ec..c543a5a0c 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -147,7 +147,7 @@ object SymDenotations { } private def completeFrom(completer: LazyType)(implicit ctx: Context): Unit = { - if (myFlags is Touched) throw new CyclicReference(this) + if (myFlags is Touched) throw CyclicReference(this) myFlags |= Touched // completions.println(s"completing ${this.debugString}") @@ -1034,7 +1034,7 @@ object SymDenotations { } private def computeBases(implicit ctx: Context): Unit = { - if (myBaseClasses eq Nil) throw new CyclicReference(this) + if (myBaseClasses eq Nil) throw CyclicReference(this) myBaseClasses = Nil val seen = new mutable.BitSet val locked = new mutable.BitSet @@ -1294,7 +1294,7 @@ object SymDenotations { basetp = computeBaseTypeRefOf(tp) baseTypeRefCache.put(tp, basetp) } else if (basetp == NoPrefix) { - throw new CyclicReference(this) + throw CyclicReference(this) } basetp case _ => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index a81d200d3..8ec5c7295 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1236,7 +1236,7 @@ object Types { if (ctx.underlyingRecursions < LogPendingUnderlyingThreshold) op else if (ctx.pendingUnderlying contains this) - throw new CyclicReference(symbol) + throw CyclicReference(symbol) else try { ctx.pendingUnderlying += this @@ -1487,7 +1487,7 @@ object Types { unique(new CachedConstantType(value)) } - case class LazyRef(refFn: () => Type) extends UncachedProxyType with TermType { + case class LazyRef(refFn: () => Type) extends UncachedProxyType with ValueType { lazy val ref = refFn() override def underlying(implicit ctx: Context) = ref override def toString = s"LazyRef($ref)" @@ -2689,10 +2689,17 @@ object Types { extends FatalTypeError( s"""malformed type: $pre is not a legal prefix for $denot because it contains abstract type member${if (absMembers.size == 1) "" else "s"} ${absMembers.mkString(", ")}""") - class CyclicReference(val denot: SymDenotation) + class CyclicReference private (val denot: SymDenotation) extends FatalTypeError(s"cyclic reference involving $denot") { def show(implicit ctx: Context) = s"cyclic reference involving ${denot.show}" - printStackTrace() + } + + object CyclicReference { + def apply(denot: SymDenotation)(implicit ctx: Context): CyclicReference = { + val ex = new CyclicReference(denot) + if (!(ctx.mode is typer.Mode.CheckCyclic)) ex.printStackTrace() + ex + } } class MergeError(msg: String) extends FatalTypeError(msg) diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 59658c9c1..193c872f1 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -11,6 +11,7 @@ import java.lang.Integer.toHexString import scala.collection.{ mutable, immutable } import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch +import typer.Checking.checkNonCyclic import io.AbstractFile class ClassfileParser( @@ -337,7 +338,11 @@ class ClassfileParser( val savedIndex = index try { index = start - denot.info = sig2typeBounds(tparams, skiptvs = false) + denot.info = + checkNonCyclic( // we need the checkNonCyclic call to insert LazyRefs for F-bounded cycles + denot.symbol, + sig2typeBounds(tparams, skiptvs = false), + reportErrors = false) } finally { index = savedIndex } diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala index de3f626da..2e21358e4 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala @@ -15,6 +15,7 @@ import printing.Texts._ import printing.Printer import io.AbstractFile import util.common._ +import typer.Checking.checkNonCyclic import PickleBuffer._ import scala.reflect.internal.pickling.PickleFormat._ import Decorators._ @@ -516,7 +517,11 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: denot setFlag Scala2x case denot => val tp1 = depoly(tp, denot) - denot.info = if (tag == ALIASsym) TypeAlias(tp1) else tp1 + denot.info = + if (tag == ALIASsym) TypeAlias(tp1) + else if (denot.isType) checkNonCyclic(denot.symbol, tp1, reportErrors = false) + // we need the checkNonCyclic call to insert LazyRefs for F-bounded cycles + else tp1 if (denot.isConstructor) addConstructorTypeParams(denot) if (atEnd) { assert(!(denot is SuperAccessor), denot) |