From 2d45d5b23983fa20b353fc83ba4e9b8585e5f662 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 7 Apr 2015 21:25:28 +0200 Subject: Change of TERMREFsymbol/TYPEREFsymbol semantics Used to be "with fixed sym". Now it is: With initial symbol as given in the serialized info. It turns out the only previous uses of (TERM|TYPE)REFsymbol were types that were made symbolic in self types. But exactly that caused that problems in unpickling which we tried to workaround by changing WithFixedSym#newLikeThis. And these fixes became less and less intuitive and still could not solve the problem for good. Last hurdle was pickle-testing all files in ast together. It's much simpler to reserve (TERM|TYPE)REFsymbol for NamedTypes that have an initial symbol. Like the previous "WithFixedSym" pickling, this avoids inifinite recursions in pickling/extmethods.scala. But it also avoids problens with unpickling ast/*.scala. The reason it is better is that it more accurately models that types that exist before pickling. This change also undoes previous changes to WithFixedSym#newlikeThis. Better to keep the more restrictive contract for these. --- .../tools/dotc/core/pickling/TreePickler.scala | 49 ++++++++-------------- 1 file changed, 18 insertions(+), 31 deletions(-) (limited to 'src/dotty/tools/dotc/core/pickling/TreePickler.scala') diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala index 14a92e8e6..85addc563 100644 --- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala @@ -32,20 +32,6 @@ class TreePickler(pickler: TastyPickler) { symRefs.get(sym) } - private var makeSymbolicRefsTo: Symbol = NoSymbol - - /** All references to members of class `sym` are pickled - * as symbolic references. Used to pickle the self info of a class. - * Without this precaution we get an infinite cycle when unpickling pos/extmethods.scala - * The problem arises when a self type of a trait is a type parameter of the same trait. - */ - private def withSymbolicRefsTo[T](sym: Symbol)(op: => T): T = { - val saved = makeSymbolicRefsTo - makeSymbolicRefsTo = sym - try op - finally makeSymbolicRefsTo = saved - } - def preRegister(tree: Tree)(implicit ctx: Context): Unit = tree match { case tree: MemberDef => if (!symRefs.contains(tree.symbol)) symRefs(tree.symbol) = NoAddr @@ -88,6 +74,11 @@ class TreePickler(pickler: TastyPickler) { assert(!sym.is(Flags.Package), sym) forwardSymRefs(sym) = ref :: forwardSymRefs.getOrElse(sym, Nil) } + + private def isLocallyDefined(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match { + case Some(label) => assert(sym.exists); label != NoAddr + case None => false + } def pickle(trees: List[Tree])(implicit ctx: Context) = { @@ -162,7 +153,8 @@ class TreePickler(pickler: TastyPickler) { writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg) pickleName(qualifiedName(sym)) } - else if (tpe.prefix == NoPrefix) { + else { + assert(tpe.prefix == NoPrefix) def pickleRef() = { writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) pickleSymRef(sym) @@ -178,10 +170,6 @@ class TreePickler(pickler: TastyPickler) { } else pickleRef() } - else { - writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) - pickleSymRef(sym); pickleType(tpe.prefix) - } case tpe: TermRefWithSignature => writeByte(TERMREF) pickleNameAndSig(tpe.name, tpe.signature); pickleType(tpe.prefix) @@ -190,12 +178,13 @@ class TreePickler(pickler: TastyPickler) { // instantiated lambdas are pickled as APPLIEDTYPE; #Apply will // be reconstituted when unpickling. pickleType(tpe.prefix) - else tpe.prefix match { - case prefix: ThisType if prefix.cls == makeSymbolicRefsTo => - pickleType(NamedType.withFixedSym(tpe.prefix, tpe.symbol)) - case _ => - writeByte(if (tpe.isType) TYPEREF else TERMREF) - pickleName(tpe.name); pickleType(tpe.prefix) + else if (isLocallyDefined(tpe.symbol)) { + writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) + pickleSymRef(tpe.symbol); pickleType(tpe.prefix) + } + else { + writeByte(if (tpe.isType) TYPEREF else TERMREF) + pickleName(tpe.name); pickleType(tpe.prefix) } case tpe: ThisType => writeByte(THIS) @@ -432,12 +421,10 @@ class TreePickler(pickler: TastyPickler) { if ((selfInfo ne NoType) || !tree.self.isEmpty) { writeByte(SELFDEF) pickleName(tree.self.name) - withSymbolicRefsTo(tree.symbol.owner) { - pickleType { - cinfo.selfInfo match { - case sym: Symbol => sym.info - case tp: Type => tp - } + pickleType { + cinfo.selfInfo match { + case sym: Symbol => sym.info + case tp: Type => tp } } } -- cgit v1.2.3