diff options
author | Martin Odersky <odersky@gmail.com> | 2015-09-08 12:13:34 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-09-08 12:13:34 +0200 |
commit | 71150c808111055d23ab88763a487dbf743c4b88 (patch) | |
tree | 8143864dea4f2da2909f70c3aaf13281ed27a808 /src | |
parent | 76d083889d52a5abbf883e5577b1fd21c9a1d903 (diff) | |
download | dotty-71150c808111055d23ab88763a487dbf743c4b88.tar.gz dotty-71150c808111055d23ab88763a487dbf743c4b88.tar.bz2 dotty-71150c808111055d23ab88763a487dbf743c4b88.zip |
Surivive Cyclic References when unpickling Scala 2 HK types
Closes $778. It seems impossible (or very hard) to avoid Cyclic References
when unpickling Scala2 files. So we try to survive them instead.
Review by @DarkDimius
Diffstat (limited to 'src')
4 files changed, 27 insertions, 7 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index f466cee77..a29c26fad 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -11,6 +11,7 @@ import Names._ import NameOps._ import Flags._ import StdNames.tpnme +import typer.Mode import util.Positions.Position import config.Printers._ import collection.mutable @@ -144,10 +145,23 @@ class TypeApplications(val self: Type) extends AnyVal { println(s"precomplete decls = ${self.typeSymbol.unforcedDecls.toList.map(_.denot).mkString("\n ")}") } val tparam = tparams.head - val arg1 = - if ((tparam is HigherKinded) && !arg.isLambda && arg.typeParams.nonEmpty) - arg.EtaExpand - else arg + def needsEtaExpand = + try { + (tparam is HigherKinded) && !arg.isLambda && arg.typeParams.nonEmpty + } + catch { + case ex: CyclicReference => + if (ctx.mode.is(Mode.Scala2Unpickling)) + // When unpickling Scala2, we might run into cyclic references when + // checking whether eta expansion is needed or eta expanding. + // (e.g. try compile collection/generic/GenericTraversableTemplate.scala). + // In that case, back out gracefully. Ideally, we should not have + // underdefined pickling data that requires post-transformations like + // eta expansion, but we can't change Scala2's. + false + else throw ex + } + val arg1 = if (needsEtaExpand) arg.EtaExpand else arg val tp1 = RefinedType(tp, tparam.name, arg1.toBounds(tparam)) matchParams(tp1, tparams.tail, args1) case nil => tp diff --git a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index d53f545d3..b948efebb 100644 --- a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -12,6 +12,7 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch import typer.Checking.checkNonCyclic +import typer.Mode import io.AbstractFile import scala.util.control.NonFatal @@ -673,7 +674,7 @@ class ClassfileParser( def unpickleScala(bytes: Array[Byte]): Some[Embedded] = { val unpickler = new unpickleScala2.Scala2Unpickler(bytes, classRoot, moduleRoot)(ctx) - unpickler.run() + unpickler.run()(ctx.addMode(Mode.Scala2Unpickling)) Some(unpickler) } diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index a3c131427..e6eb89008 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -17,6 +17,7 @@ import printing.Printer import io.AbstractFile import util.common._ import typer.Checking.checkNonCyclic +import typer.Mode import PickleBuffer._ import scala.reflect.internal.pickling.PickleFormat._ import Decorators._ @@ -520,7 +521,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas class LocalUnpickler extends LazyType { def startCoord(denot: SymDenotation): Coord = denot.symbol.coord def complete(denot: SymDenotation)(implicit ctx: Context): Unit = try { - def parseToCompletion(denot: SymDenotation) = { + def parseToCompletion(denot: SymDenotation)(implicit ctx: Context) = { val tag = readByte() val end = readNat() + readIndex def atEnd = readIndex == end @@ -566,7 +567,8 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } // println(s"unpickled ${denot.debugString}, info = ${denot.info}") !!! DEBUG } - atReadPos(startCoord(denot).toIndex, () => parseToCompletion(denot)) + atReadPos(startCoord(denot).toIndex, + () => parseToCompletion(denot)(ctx.addMode(Mode.Scala2Unpickling))) } catch { case ex: RuntimeException => handleRuntimeException(ex) } diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala index 8dd4c5b68..55d44ad7a 100644 --- a/src/dotty/tools/dotc/typer/Mode.scala +++ b/src/dotty/tools/dotc/typer/Mode.scala @@ -79,5 +79,8 @@ object Mode { */ val ImplicitExploration = newMode(12, "ImplicitExploration") + /** We are currently unpickling Scala2 info */ + val Scala2Unpickling = newMode(13, "Scala2Unpickling") + val PatternOrType = Pattern | Type } |