aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2015-04-09 09:53:08 +0200
committerDmitry Petrashko <dark@d-d.me>2015-04-09 09:53:08 +0200
commit957923ec75c71ac9f7efe67823781438177aaa59 (patch)
treebb30156964be6feb7dc0f63a214a9c7b42f50596 /src
parente1e0e9abb6c2b6285d598e260cc1d1c4ac2d3c2a (diff)
parent9a7a7b889c9ded58ceaefb90f6ee208c9d2ab534 (diff)
downloaddotty-957923ec75c71ac9f7efe67823781438177aaa59.tar.gz
dotty-957923ec75c71ac9f7efe67823781438177aaa59.tar.bz2
dotty-957923ec75c71ac9f7efe67823781438177aaa59.zip
Merge pull request #465 from dotty-staging/fix/pickling
Fix/pickling
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/config/JavaPlatform.scala5
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala25
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala10
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala59
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala11
-rw-r--r--src/dotty/tools/dotc/core/Types.scala21
-rw-r--r--src/dotty/tools/dotc/core/pickling/NameBuffer.scala4
-rw-r--r--src/dotty/tools/dotc/core/pickling/PickleFormat.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyName.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyPrinter.scala3
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreePickler.scala64
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala165
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala15
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala1
15 files changed, 218 insertions, 171 deletions
diff --git a/src/dotty/tools/dotc/config/JavaPlatform.scala b/src/dotty/tools/dotc/config/JavaPlatform.scala
index 043f41a44..41a9c7113 100644
--- a/src/dotty/tools/dotc/config/JavaPlatform.scala
+++ b/src/dotty/tools/dotc/config/JavaPlatform.scala
@@ -4,9 +4,8 @@ package config
import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath}
import ClassPath.{ JavaContext, DefaultJavaContext }
-import core.Contexts._
-import core.SymDenotations._, core.Symbols._, dotty.tools.dotc.core._
-import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._
+import core._
+import Symbols._, Types._, Contexts._, Denotations._, SymDenotations._, StdNames._, Names._
import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._
class JavaPlatform extends Platform {
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 6ca1bae8f..849e934f0 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -476,12 +476,14 @@ object Denotations {
/** The version of this SingleDenotation that was valid in the first phase
* of this run.
*/
- def initial: SingleDenotation = {
- var current = nextInRun
- while (current.validFor.code > this.myValidFor.code) current = current.nextInRun
- current
- }
-
+ def initial: SingleDenotation =
+ if (validFor == Nowhere) this
+ else {
+ var current = nextInRun
+ while (current.validFor.code > this.myValidFor.code) current = current.nextInRun
+ current
+ }
+
def history: List[SingleDenotation] = {
val b = new ListBuffer[SingleDenotation]
var current = initial
@@ -493,6 +495,9 @@ object Denotations {
b.toList
}
+ /** Invalidate all caches and fields that depend on base classes and their contents */
+ def invalidateInheritedInfo(): Unit = ()
+
/** Move validity period of this denotation to a new run. Throw a StaleSymbol error
* if denotation is no longer valid.
*/
@@ -502,9 +507,10 @@ object Denotations {
var d: SingleDenotation = denot
do {
d.validFor = Period(ctx.period.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId)
+ d.invalidateInheritedInfo()
d = d.nextInRun
} while (d ne denot)
- syncWithParents
+ this
case _ =>
if (coveredInterval.containsPhaseId(ctx.phaseId)) staleSymbolError
else NoDenotation
@@ -611,16 +617,13 @@ object Denotations {
val current = symbol.current
// println(s"installing $this after $phase/${phase.id}, valid = ${current.validFor}")
// printPeriods(current)
- if (current.nextInRun ne current)
- this.nextInRun = current.nextInRun
- else
- this.nextInRun = this
this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId)
if (current.validFor.firstPhaseId == targetId) {
// replace current with this denotation
var prev = current
while (prev.nextInRun ne current) prev = prev.nextInRun
prev.nextInRun = this
+ this.nextInRun = current.nextInRun
current.validFor = Nowhere
} else {
// insert this denotation after current
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 60e429bb3..13ff92a8a 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -147,20 +147,26 @@ object NameOps {
/** The superaccessor for method with given name */
def superName: TermName = (nme.SUPER_PREFIX ++ name).toTermName
- /** The expanded name of `name` relative to this class `base` with given `separator`
+ /** The expanded name of `name` relative to given class `base`.
*/
def expandedName(base: Symbol)(implicit ctx: Context): N =
expandedName(if (base is Flags.ExpandedName) base.name else base.fullNameSeparated('$'))
/** The expanded name of `name` relative to `basename` with given `separator`
*/
- def expandedName(prefix: Name)(implicit ctx: Context): N =
+ def expandedName(prefix: Name): N =
name.fromName(prefix ++ nme.EXPAND_SEPARATOR ++ name).asInstanceOf[N]
def unexpandedName: N = {
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
}
+
+ def expandedPrefix: N = {
+ val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
+ assert(idx >= 0)
+ name.take(idx).asInstanceOf[N]
+ }
def shadowedName: N = likeTyped(nme.SHADOWED ++ name)
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 1285d3fdd..e572f129b 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -41,15 +41,19 @@ trait SymDenotations { this: Context =>
def stillValid(denot: SymDenotation): Boolean =
if (denot is ValidForever) true
- else try {
- val owner = denot.owner.denot
- stillValid(owner) && (
- !owner.isClass
- || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
- || denot.isSelfSym
- )
- } catch {
- case ex: StaleSymbol => false
+ else {
+ val initial = denot.initial
+ if (initial ne denot)
+ ctx.withPhase(initial.validFor.firstPhaseId).stillValid(initial.asSymDenotation)
+ else try {
+ val owner = denot.owner.denot
+ stillValid(owner) && (
+ !owner.isClass
+ || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
+ || denot.isSelfSym)
+ } catch {
+ case ex: StaleSymbol => false
+ }
}
}
@@ -70,6 +74,12 @@ object SymDenotations {
override def hasUniqueSym: Boolean = exists
+ /** Debug only
+ override def validFor_=(p: Period) = {
+ super.validFor_=(p)
+ }
+ */
+
// ------ Getting and setting fields -----------------------------
private[this] var myFlags: FlagSet = adaptFlags(initFlags)
@@ -171,13 +181,13 @@ object SymDenotations {
myInfo = tp
}
- /** The name, except
- * - if this is a module class, strip the module class suffix
- * - if this is a companion object with a clash-avoiding name, strip the
+ /** The name, except
+ * - if this is a module class, strip the module class suffix
+ * - if this is a companion object with a clash-avoiding name, strip the
* "avoid clash" suffix
*/
def effectiveName(implicit ctx: Context) =
- if (this is ModuleClass) name.stripModuleClassSuffix
+ if (this is ModuleClass) name.stripModuleClassSuffix
else name.stripAvoidClashSuffix
/** The privateWithin boundary, NoSymbol if no boundary is given.
@@ -195,7 +205,7 @@ object SymDenotations {
/** Update the annotations of this denotation */
private[core] final def annotations_=(annots: List[Annotation]): Unit =
- myAnnotations = annots
+ myAnnotations = annots
/** Does this denotation have an annotation matching the given class symbol? */
final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
@@ -241,9 +251,9 @@ object SymDenotations {
/** The symbols defined in this class or object.
* Careful! This does not force the type, so is compilation order dependent.
* This method should be used only in the following circumstances:
- *
- * 1. When accessing type parameters or type parameter accessors (both are entered before
- * completion).
+ *
+ * 1. When accessing type parameters or type parameter accessors (both are entered before
+ * completion).
* 2. When obtaining the current scope in order to enter, rename or delete something there.
* 3. When playing it safe in order not to raise CylicReferences, e.g. for printing things
* or taking more efficient shortcuts (e.g. the stillValid test).
@@ -292,7 +302,6 @@ object SymDenotations {
if (isType) fn.toTypeName else fn.toTermName
}
-
/** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */
def flatName(separator: Char = '$')(implicit ctx: Context): Name =
if (symbol == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot || (owner is PackageClass)) name
@@ -457,7 +466,7 @@ object SymDenotations {
}
/** Is this a user defined "def" method? Excluded are accessors and anonymous functions. */
- final def isSourceMethod(implicit ctx: Context) =
+ final def isSourceMethod(implicit ctx: Context) =
this.is(Method, butNot = AccessorOrLabel) && !isAnonymousFunction
/** Is this a setter? */
@@ -649,7 +658,7 @@ object SymDenotations {
*/
/** The class implementing this module, NoSymbol if not applicable. */
final def moduleClass(implicit ctx: Context): Symbol = {
- def notFound = {println(s"missing module class for $name: $myInfo"); NoSymbol}
+ def notFound = { println(s"missing module class for $name: $myInfo"); NoSymbol }
if (this is ModuleVal)
myInfo match {
case info: TypeRef => info.symbol
@@ -1002,7 +1011,7 @@ object SymDenotations {
s"$kindString $name"
}
- def debugString = toString+"#"+symbol.id // !!! DEBUG
+ def debugString = toString + "#" + symbol.id // !!! DEBUG
// ----- copies and transforms ----------------------------------------
@@ -1097,8 +1106,8 @@ object SymDenotations {
private var firstRunId: RunId = initRunId
- /** If caches influenced by parent classes are still valid, the denotation
- * itself, otherwise a freshly initialized copy.
+ /** invalidate caches influenced by parent classes if one of the parents
+ * is younger than the denotation itself.
*/
override def syncWithParents(implicit ctx: Context): SingleDenotation = {
def isYounger(tref: TypeRef) = tref.symbol.denot match {
@@ -1124,7 +1133,7 @@ object SymDenotations {
}
/** Invalidate all caches and fields that depend on base classes and their contents */
- private def invalidateInheritedInfo(): Unit = {
+ override def invalidateInheritedInfo(): Unit = {
myBaseClasses = null
mySuperClassBits = null
myMemberFingerPrint = FingerPrint.unknown
@@ -1168,7 +1177,7 @@ object SymDenotations {
private[this] var myBaseClasses: List[ClassSymbol] = null
private[this] var mySuperClassBits: BitSet = null
- /** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
+ /** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
private def checkBasesUpToDate()(implicit ctx: Context) =
if (baseTypeRefValid != ctx.runId) {
baseTypeRefCache = new java.util.HashMap[CachedType, Type]
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 02526a30b..6c3fef1a9 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -191,6 +191,17 @@ class TypeApplications(val self: Type) extends AnyVal {
if (res.isInstantiatedLambda) res.select(tpnme.Apply) else res
}
}
+
+ /** Simplify a fully instantiated type of the form `LambdaX{... type Apply = T } # Apply` to `T`.
+ */
+ def simplifyApply(implicit ctx: Context): Type = self match {
+ case self @ TypeRef(prefix, tpnme.Apply) if prefix.isInstantiatedLambda =>
+ prefix.member(tpnme.Apply).info match {
+ case TypeAlias(alias) => alias
+ case _ => self
+ }
+ case _ => self
+ }
final def appliedTo(arg: Type)(implicit ctx: Context): Type = appliedTo(arg :: Nil)
final def appliedTo(arg1: Type, arg2: Type)(implicit ctx: Context): Type = appliedTo(arg1 :: arg2 :: Nil)
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ea4101558..31567fee0 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -480,7 +480,7 @@ object Types {
case ex: MergeError =>
throw new MergeError(s"${ex.getMessage} as members of type ${pre.show}")
case ex: Throwable =>
- println(i"findMember exception for $this: ${this.widen} member $name")
+ println(s"findMember exception for $this member $name")
throw ex // DEBUG
} finally {
recCount -= 1
@@ -1158,7 +1158,7 @@ object Types {
private[this] var lastDenotation: Denotation = _
private[this] var lastSymbol: Symbol = _
private[this] var checkedPeriod = Nowhere
-
+
// Invariants:
// (1) checkedPeriod != Nowhere => lastDenotation != null
// (2) lastDenotation != null => lastSymbol != null
@@ -1238,8 +1238,7 @@ object Types {
// phase but a defined denotation earlier (e.g. a TypeRef to an abstract type
// is undefined after erasure.) We need to be able to do time travel back and
// forth also in these cases.
- lastDenotation = d
- lastSymbol = d.symbol
+ setDenot(d)
checkedPeriod = ctx.period
}
d
@@ -1256,9 +1255,14 @@ object Types {
private def checkSymAssign(sym: Symbol)(implicit ctx: Context) =
assert(
(lastSymbol eq sym) ||
- (lastSymbol eq null) ||
- (lastSymbol.defRunId != sym.defRunId) ||
- (lastSymbol.defRunId == NoRunId) ||
+ (lastSymbol eq null) || {
+ val lastDefRunId = lastDenotation match {
+ case d: SymDenotation => d.validFor.runId
+ case _ => lastSymbol.defRunId
+ }
+ (lastDefRunId != sym.defRunId) ||
+ (lastDefRunId == NoRunId)
+ } ||
(lastSymbol.infoOrCompleter == ErrorType ||
defn.overriddenBySynthetic.contains(lastSymbol)
// for overriddenBySynthetic symbols a TermRef such as SomeCaseClass.this.hashCode
@@ -1280,6 +1284,9 @@ object Types {
if (Config.checkNoDoubleBindings)
if (ctx.settings.YnoDoubleBindings.value)
checkSymAssign(denot.symbol)
+
+ // additional checks that intercept `denot` can be added here
+
lastDenotation = denot
lastSymbol = denot.symbol
}
diff --git a/src/dotty/tools/dotc/core/pickling/NameBuffer.scala b/src/dotty/tools/dotc/core/pickling/NameBuffer.scala
index be557f0b1..a60767fe6 100644
--- a/src/dotty/tools/dotc/core/pickling/NameBuffer.scala
+++ b/src/dotty/tools/dotc/core/pickling/NameBuffer.scala
@@ -65,9 +65,9 @@ class NameBuffer extends TastyBuffer(100000) {
case Signed(original, params, result) =>
writeByte(SIGNED)
withLength { writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) }
- case Expanded(original) =>
+ case Expanded(prefix, original) =>
writeByte(EXPANDED)
- withLength { writeNameRef(original) }
+ withLength { writeNameRef(prefix); writeNameRef(original) }
case ModuleClass(module) =>
writeByte(OBJECTCLASS)
withLength { writeNameRef(module) }
diff --git a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
index d37a3673d..872265e2d 100644
--- a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
+++ b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
@@ -269,7 +269,7 @@ object PickleFormat {
final val DOUBLEconst = 76
final val STRINGconst = 77
final val IMPORTED = 78
-
+
final val THIS = 96
final val CLASSconst = 97
final val ENUMconst = 98
diff --git a/src/dotty/tools/dotc/core/pickling/TastyName.scala b/src/dotty/tools/dotc/core/pickling/TastyName.scala
index 8508d7ffa..e8f30a234 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyName.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyName.scala
@@ -15,7 +15,7 @@ object TastyName {
case class Simple(name: TermName) extends TastyName
case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName
case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
- case class Expanded(original: NameRef) extends TastyName
+ case class Expanded(prefix: NameRef, original: NameRef) extends TastyName
case class ModuleClass(module: NameRef) extends TastyName
case class SuperAccessor(accessed: NameRef) extends TastyName
case class DefaultGetter(method: NameRef, num: Int) extends TastyName
diff --git a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
index 91cc168ea..a3d30b9b2 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
@@ -5,6 +5,7 @@ package pickling
import Contexts._, Decorators._
import printing.Texts._
import TastyName._
+import StdNames._
import TastyUnpickler._
import TastyBuffer.Addr
import util.Positions.{Position, offsetToInt}
@@ -20,7 +21,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
case Qualified(qual, name) => nameRefToString(qual) + "." + nameRefToString(name)
case Signed(original, params, result) =>
i"${nameRefToString(original)}@${params.map(nameRefToString)}%,%:${nameRefToString(result)}"
- case Expanded(original) => nameRefToString(original) + "/EXPANDED"
+ case Expanded(prefix, original) => s"$prefix${nme.EXPAND_SEPARATOR}$original"
case ModuleClass(original) => nameRefToString(original) + "/MODULECLASS"
case SuperAccessor(accessed) => nameRefToString(accessed) + "/SUPERACCESSOR"
case DefaultGetter(meth, num) => nameRefToString(meth) + "/DEFAULTGETTER" + num
diff --git a/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala
index e5eabaf36..b5e978afa 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala
@@ -51,7 +51,7 @@ class TastyUnpickler(reader: TastyReader) {
val params = until(end)(readNameRef())
Signed(original, params, result)
case EXPANDED =>
- Expanded(readNameRef())
+ Expanded(readNameRef(), readNameRef())
case OBJECTCLASS =>
ModuleClass(readNameRef())
case SUPERACCESSOR =>
diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
index c5e07ffa9..85addc563 100644
--- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
@@ -8,6 +8,7 @@ import PickleFormat._
import core._
import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._, StdNames.tpnme, NameOps._
import collection.mutable
+import NameOps._
import TastyBuffer._
class TreePickler(pickler: TastyPickler) {
@@ -31,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
@@ -61,13 +48,19 @@ class TreePickler(pickler: TastyPickler) {
}
}
- private def pickleName(name: Name) = writeNat(nameIndex(name).index)
- private def pickleName(name: TastyName) = writeNat(nameIndex(name).index)
+ private def pickleName(name: Name): Unit = writeNat(nameIndex(name).index)
+ private def pickleName(name: TastyName): Unit = writeNat(nameIndex(name).index)
private def pickleNameAndSig(name: Name, sig: Signature) = {
val Signature(params, result) = sig
pickleName(TastyName.Signed(nameIndex(name), params.map(fullNameIndex), fullNameIndex(result)))
}
-
+
+ private def pickleName(sym: Symbol)(implicit ctx: Context): Unit =
+ if (sym is Flags.ExpandedName)
+ pickleName(TastyName.Expanded(
+ nameIndex(sym.name.expandedPrefix), nameIndex(sym.name.unexpandedName)))
+ else pickleName(sym.name)
+
private def pickleSymRef(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match {
case Some(label) =>
if (label != NoAddr) writeRef(label) else pickleForwardSymRef(sym)
@@ -81,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) = {
@@ -155,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)
@@ -171,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)
@@ -183,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)
@@ -425,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
}
}
}
@@ -464,7 +458,7 @@ class TreePickler(pickler: TastyPickler) {
registerDef(sym)
writeByte(tag)
withLength {
- pickleName(sym.name)
+ pickleName(sym)
pickleParams
tpt match {
case tpt: TypeTree => pickleTpt(tpt)
diff --git a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
index 7d80065cf..c46ff8d6f 100644
--- a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
@@ -70,7 +70,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case Qualified(qual, name) => toTermName(qual) ++ "." ++ toTermName(name)
case Signed(original, params, result) => toTermName(original)
case Shadowed(original) => toTermName(original).shadowedName
- case Expanded(original) => ???
+ case Expanded(prefix, original) => toTermName(original).expandedName(toTermName(prefix))
case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
case SuperAccessor(accessed) => ???
case DefaultGetter(meth, num) => ???
@@ -102,6 +102,17 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
def skipParams(): Unit =
while (nextByte == PARAMS || nextByte == TYPEPARAM) skipTree()
+ /** The next tag, following through SHARED tags */
+ def nextUnsharedTag: Int = {
+ val tag = nextByte
+ if (tag == SHARED) {
+ val lookAhead = fork
+ lookAhead.reader.readByte()
+ forkAt(lookAhead.reader.readAddr()).nextUnsharedTag
+ }
+ else tag
+ }
+
def readName(): TermName = toTermName(readNameRef())
def readNameSplitSig()(implicit ctx: Context): Any /* TermName | (TermName, Signature) */ =
@@ -172,17 +183,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case REFINEDtype =>
val parent = readType()
var name: Name = readName()
- if (nextByte == SHARED) {
- val refinedInfo = readType()
- if (refinedInfo.isInstanceOf[TypeBounds]) name = name.toTypeName
- RefinedType(parent, name, refinedInfo)
- }
- else {
- if (nextByte == TYPEBOUNDS || nextByte == TYPEALIAS) name = name.toTypeName
- RefinedType(parent, name, rt => registeringType(rt, readType()))
- // Note that the lambda is not equivalent to a wildcard closure!
- // Eta expansion of the latter puts readType() out of the expression.
- }
+ val ttag = nextUnsharedTag
+ if (ttag == TYPEBOUNDS || ttag == TYPEALIAS) name = name.toTypeName
+ RefinedType(parent, name, rt => registeringType(rt, readType()))
+ // Note that the lambda "rt => ..." is not equivalent to a wildcard closure!
+ // Eta expansion of the latter puts readType() out of the expression.
case APPLIEDtype =>
readType().appliedTo(until(end)(readType()))
case TYPEBOUNDS =>
@@ -235,26 +240,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case TYPEREFdirect | TERMREFdirect =>
NamedType.withFixedSym(NoPrefix, readSymRef())
case TYPEREFsymbol | TERMREFsymbol =>
- val sym = readSymRef()
- val prefix = readType()
- val res = NamedType.withFixedSym(prefix, sym)
- if (prefix.isInstanceOf[ThisType]) res.withDenot(sym.denot) else res
- // 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.
+ readSymNameRef()
case TYPEREFpkg =>
- val name = readName()
- val pkg =
- if (name == nme.ROOT) defn.RootClass
- else if (name == nme.EMPTY_PACKAGE) defn.EmptyPackageClass
- else ctx.requiredPackage(name).moduleClass
- pkg.typeRef
+ readPackageRef().moduleClass.typeRef
case TERMREFpkg =>
- val name = readName()
- val pkg =
- if (name == nme.ROOT) defn.RootPackage
- else if (name == nme.EMPTY_PACKAGE) defn.EmptyPackageVal
- else ctx.requiredPackage(name)
- pkg.termRef
+ readPackageRef().termRef
case TYPEREF =>
val name = readName().toTypeName
TypeRef(readType(), name)
@@ -301,6 +291,25 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
if (tag < firstLengthTreeTag) readSimpleType() else readLengthType()
}
+ private def readSymNameRef()(implicit ctx: Context): Type = {
+ val sym = readSymRef()
+ val prefix = readType()
+ val res = NamedType.withSymAndName(prefix, sym, sym.name)
+ prefix match {
+ case prefix: ThisType if prefix.cls eq sym.owner => res.withDenot(sym.denot)
+ // 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.
+ case _ => res
+ }
+ }
+
+ private def readPackageRef()(implicit ctx: Context): TermSymbol = {
+ val name = readName()
+ if (name == nme.ROOT) defn.RootPackage
+ else if (name == nme.EMPTY_PACKAGE) defn.EmptyPackageVal
+ else ctx.requiredPackage(name)
+ }
+
def readTypeRef(): Type =
typeAtAddr(readAddr())
@@ -325,16 +334,16 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
private def normalizeFlags(tag: Int, givenFlags: FlagSet, name: Name, isAbstractType: Boolean, rhsIsEmpty: Boolean)(implicit ctx: Context): FlagSet = {
val lacksDefinition =
- rhsIsEmpty && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) ||
+ rhsIsEmpty &&
+ name.isTermName && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) ||
isAbstractType
var flags = givenFlags
if (lacksDefinition) flags |= Deferred
if (tag == DEFDEF) flags |= Method
if (givenFlags is Module)
flags = flags | (if (tag == VALDEF) ModuleCreationFlags else ModuleClassCreationFlags)
- if (ctx.mode.is(Mode.InSuperCall) && !flags.is(ParamOrAccessor)) flags |= InSuperCall
if (ctx.owner.isClass) {
- if (tag == TYPEPARAM) flags |= Param | ExpandedName // TODO check name to determine ExpandedName
+ if (tag == TYPEPARAM) flags |= Param
else if (tag == PARAM) flags |= ParamAccessor
}
else if (isParamTag(tag)) flags |= Param
@@ -348,52 +357,56 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
val start = currentAddr
val tag = readByte()
val end = readEnd()
- val name = if (tag == TYPEDEF || tag == TYPEPARAM) readName().toTypeName else readName()
+ val rawName = tastyName(readNameRef())
+ var name: Name = toTermName(rawName)
+ if (tag == TYPEDEF || tag == TYPEPARAM) name = name.toTypeName
skipParams()
- val isAbstractType = nextByte == TYPEBOUNDS
- val isClass = nextByte == TEMPLATE
+ val ttag = nextUnsharedTag
+ val isAbstractType = ttag == TYPEBOUNDS
+ val isClass = ttag == TEMPLATE
val templateStart = currentAddr
skipTree() // tpt
val rhsIsEmpty = noRhs(end)
if (!rhsIsEmpty) skipTree()
val (givenFlags, annots, privateWithin) = readModifiers(end)
+ val expandedFlag = if (rawName.isInstanceOf[TastyName.Expanded]) ExpandedName else EmptyFlags
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
- val flags = normalizeFlags(tag, givenFlags, name, isAbstractType, rhsIsEmpty)
- val nameMatches = (_: Denotation).symbol.name == name
- val prevDenot: SymDenotation =
- if (ctx.owner.is(Package)) ctx.effectiveScope.lookup(name)
- else NoDenotation // TODO check for double reads
- var completer: LazyType =
- if (prevDenot.exists) new Completer(subReader(start, end)) with SymbolLoaders.SecondCompleter
- else new Completer(subReader(start, end))
- if (flags is Module) completer = ctx.adjustModuleCompleter(completer, name)
+ val flags = normalizeFlags(tag, givenFlags | expandedFlag, name, isAbstractType, rhsIsEmpty)
+ def adjustIfModule(completer: LazyType) =
+ if (flags is Module) ctx.adjustModuleCompleter(completer, name) else completer
val sym =
- if (roots contains prevDenot) {
- pickling.println(i"overwriting ${prevDenot.symbol} # ${prevDenot.hashCode}")
- prevDenot.info = completer
- prevDenot.flags = flags &~ Touched // allow one more completion
- prevDenot.privateWithin = privateWithin
- prevDenot.symbol
- } else if (isClass)
- ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord = start.index)
- else {
- val sym = symAtAddr.get(start) match {
- case Some(preExisting) =>
- assert(stubs contains preExisting)
- stubs -= preExisting
- preExisting
- case none =>
- ctx.newNakedSymbol(start.index)
- }
- val denot = ctx.SymDenotation(symbol = sym, owner = ctx.owner, name, flags, completer, privateWithin)
- sym.denot = denot
- sym
+ roots.find(root => (root.owner eq ctx.owner) && root.name == name) match {
+ case Some(rootd) =>
+ pickling.println(i"overwriting ${rootd.symbol} # ${rootd.hashCode}")
+ rootd.info = adjustIfModule(
+ new Completer(subReader(start, end)) with SymbolLoaders.SecondCompleter)
+ rootd.flags = flags &~ Touched // allow one more completion
+ rootd.privateWithin = privateWithin
+ rootd.symbol
+ case _ =>
+ val completer = adjustIfModule(new Completer(subReader(start, end)))
+ if (isClass)
+ ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer,
+ privateWithin, coord = start.index)
+ else {
+ val sym = symAtAddr.get(start) match {
+ case Some(preExisting) =>
+ assert(stubs contains preExisting)
+ stubs -= preExisting
+ preExisting
+ case none =>
+ ctx.newNakedSymbol(start.index)
+ }
+ val denot = ctx.SymDenotation(symbol = sym, owner = ctx.owner, name, flags, completer, privateWithin)
+ sym.denot = denot
+ sym
+ }
} // TODO set position
sym.annotations = annots
ctx.enter(sym)
symAtAddr(start) = sym
if (isClass) {
- completer.withDecls(newScope)
+ sym.completer.withDecls(newScope)
forkAt(templateStart).indexTemplateParams()(localContext(sym))
}
tag != VALDEF || rhsIsEmpty
@@ -567,17 +580,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
sym.info = readType()
ValDef(sym.asTerm, readRhs(localCtx))
case TYPEDEF | TYPEPARAM =>
- if (sym.isClass) {
- val cls = sym.asClass
- def setClsInfo(parents: List[TypeRef], selfType: Type) =
- cls.info = ClassInfo(cls.owner.thisType, cls, parents, cls.unforcedDecls, selfType)
- setClsInfo(Nil, NoType)
- val impl = readTemplate(localCtx)
- setClsInfo(
- ctx.normalizeToClassRefs(impl.parents.map(_.tpe), cls, cls.unforcedDecls),
- if (impl.self.isEmpty) NoType else impl.self.tpt.tpe)
- ta.assignType(untpd.TypeDef(sym.name.asTypeName, impl), sym)
- }
+ if (sym.isClass)
+ ta.assignType(untpd.TypeDef(sym.name.asTypeName, readTemplate(localCtx)), sym)
else {
sym.info = readType()
TypeDef(sym.asType)
@@ -606,6 +610,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
private def readTemplate(implicit ctx: Context): Template = {
val start = currentAddr
val cls = ctx.owner.asClass
+ def setClsInfo(parents: List[TypeRef], selfType: Type) =
+ cls.info = ClassInfo(cls.owner.thisType, cls, parents, cls.unforcedDecls, selfType)
+ setClsInfo(Nil, NoType)
val localDummy = ctx.newLocalDummy(cls)
assert(readByte() == TEMPLATE)
val end = readEnd()
@@ -617,12 +624,14 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case _ => readTpt()
}
}
- val self =
+ val parentRefs = ctx.normalizeToClassRefs(parents.map(_.tpe), cls, cls.unforcedDecls)
+ val self =
if (nextByte == SELFDEF) {
readByte()
untpd.ValDef(readName(), readTpt(), EmptyTree).withType(NoType)
}
else EmptyValDef
+ setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe)
val noInits = fork.indexStats(end)
if (noInits) cls.setFlag(NoInits)
val constr = readIndexedDef().asInstanceOf[DefDef]
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 0fd862afb..ce33132ab 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -37,10 +37,17 @@ class PlainPrinter(_ctx: Context) extends Printer {
/** If true, tweak output so it is the same before and after pickling */
protected def homogenizedView: Boolean = ctx.settings.YtestPickler.value
- def homogenize(tp: Type): Type = tp match {
- case tp: TypeVar if homogenizedView && tp.isInstantiated => homogenize(tp.instanceOpt)
- case _ => tp
- }
+ def homogenize(tp: Type): Type =
+ if (homogenizedView)
+ tp match {
+ case tp: TypeVar if tp.isInstantiated => homogenize(tp.instanceOpt)
+ case AndType(tp1, tp2) => homogenize(tp1) & homogenize(tp2)
+ case OrType(tp1, tp2) => homogenize(tp1) | homogenize(tp2)
+ case _ =>
+ val tp1 = tp.simplifyApply
+ if (tp1 eq tp) tp else homogenize(tp1)
+ }
+ else tp
/** Render elements alternating with `sep` string */
protected def toText(elems: Traversable[Showable], sep: String) =
diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala
index e238f21ef..626a75139 100644
--- a/src/dotty/tools/dotc/transform/Pickler.scala
+++ b/src/dotty/tools/dotc/transform/Pickler.scala
@@ -65,6 +65,7 @@ class Pickler extends Phase {
unpickler.enter(roots = Set())
unpickler
}
+ pickling.println("************* entered toplevel ***********")
for ((unpickler, unit) <- unpicklers zip units) {
val unpickled = unpickler.body(readPositions = false)
testSame(i"$unpickled%\n%", beforePickling(unit), unit)