Skip to content

Commit 957923e

Browse files
committed
Merge pull request #465 from dotty-staging/fix/pickling
Fix/pickling
2 parents e1e0e9a + 9a7a7b8 commit 957923e

File tree

16 files changed

+270
-222
lines changed

16 files changed

+270
-222
lines changed

src/dotty/tools/dotc/config/JavaPlatform.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ package config
44

55
import io.{AbstractFile,ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath}
66
import ClassPath.{ JavaContext, DefaultJavaContext }
7-
import core.Contexts._
8-
import core.SymDenotations._, core.Symbols._, dotty.tools.dotc.core._
9-
import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._
7+
import core._
8+
import Symbols._, Types._, Contexts._, Denotations._, SymDenotations._, StdNames._, Names._
109
import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._
1110

1211
class JavaPlatform extends Platform {

src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -476,12 +476,14 @@ object Denotations {
476476
/** The version of this SingleDenotation that was valid in the first phase
477477
* of this run.
478478
*/
479-
def initial: SingleDenotation = {
480-
var current = nextInRun
481-
while (current.validFor.code > this.myValidFor.code) current = current.nextInRun
482-
current
483-
}
484-
479+
def initial: SingleDenotation =
480+
if (validFor == Nowhere) this
481+
else {
482+
var current = nextInRun
483+
while (current.validFor.code > this.myValidFor.code) current = current.nextInRun
484+
current
485+
}
486+
485487
def history: List[SingleDenotation] = {
486488
val b = new ListBuffer[SingleDenotation]
487489
var current = initial
@@ -493,6 +495,9 @@ object Denotations {
493495
b.toList
494496
}
495497

498+
/** Invalidate all caches and fields that depend on base classes and their contents */
499+
def invalidateInheritedInfo(): Unit = ()
500+
496501
/** Move validity period of this denotation to a new run. Throw a StaleSymbol error
497502
* if denotation is no longer valid.
498503
*/
@@ -502,9 +507,10 @@ object Denotations {
502507
var d: SingleDenotation = denot
503508
do {
504509
d.validFor = Period(ctx.period.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId)
510+
d.invalidateInheritedInfo()
505511
d = d.nextInRun
506512
} while (d ne denot)
507-
syncWithParents
513+
this
508514
case _ =>
509515
if (coveredInterval.containsPhaseId(ctx.phaseId)) staleSymbolError
510516
else NoDenotation
@@ -611,16 +617,13 @@ object Denotations {
611617
val current = symbol.current
612618
// println(s"installing $this after $phase/${phase.id}, valid = ${current.validFor}")
613619
// printPeriods(current)
614-
if (current.nextInRun ne current)
615-
this.nextInRun = current.nextInRun
616-
else
617-
this.nextInRun = this
618620
this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId)
619621
if (current.validFor.firstPhaseId == targetId) {
620622
// replace current with this denotation
621623
var prev = current
622624
while (prev.nextInRun ne current) prev = prev.nextInRun
623625
prev.nextInRun = this
626+
this.nextInRun = current.nextInRun
624627
current.validFor = Nowhere
625628
} else {
626629
// insert this denotation after current

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,26 @@ object NameOps {
147147
/** The superaccessor for method with given name */
148148
def superName: TermName = (nme.SUPER_PREFIX ++ name).toTermName
149149

150-
/** The expanded name of `name` relative to this class `base` with given `separator`
150+
/** The expanded name of `name` relative to given class `base`.
151151
*/
152152
def expandedName(base: Symbol)(implicit ctx: Context): N =
153153
expandedName(if (base is Flags.ExpandedName) base.name else base.fullNameSeparated('$'))
154154

155155
/** The expanded name of `name` relative to `basename` with given `separator`
156156
*/
157-
def expandedName(prefix: Name)(implicit ctx: Context): N =
157+
def expandedName(prefix: Name): N =
158158
name.fromName(prefix ++ nme.EXPAND_SEPARATOR ++ name).asInstanceOf[N]
159159

160160
def unexpandedName: N = {
161161
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
162162
if (idx < 0) name else (name drop (idx + nme.EXPAND_SEPARATOR.length)).asInstanceOf[N]
163163
}
164+
165+
def expandedPrefix: N = {
166+
val idx = name.lastIndexOfSlice(nme.EXPAND_SEPARATOR)
167+
assert(idx >= 0)
168+
name.take(idx).asInstanceOf[N]
169+
}
164170

165171
def shadowedName: N = likeTyped(nme.SHADOWED ++ name)
166172

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,19 @@ trait SymDenotations { this: Context =>
4141

4242
def stillValid(denot: SymDenotation): Boolean =
4343
if (denot is ValidForever) true
44-
else try {
45-
val owner = denot.owner.denot
46-
stillValid(owner) && (
47-
!owner.isClass
48-
|| (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
49-
|| denot.isSelfSym
50-
)
51-
} catch {
52-
case ex: StaleSymbol => false
44+
else {
45+
val initial = denot.initial
46+
if (initial ne denot)
47+
ctx.withPhase(initial.validFor.firstPhaseId).stillValid(initial.asSymDenotation)
48+
else try {
49+
val owner = denot.owner.denot
50+
stillValid(owner) && (
51+
!owner.isClass
52+
|| (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol)
53+
|| denot.isSelfSym)
54+
} catch {
55+
case ex: StaleSymbol => false
56+
}
5357
}
5458
}
5559

@@ -70,6 +74,12 @@ object SymDenotations {
7074

7175
override def hasUniqueSym: Boolean = exists
7276

77+
/** Debug only
78+
override def validFor_=(p: Period) = {
79+
super.validFor_=(p)
80+
}
81+
*/
82+
7383
// ------ Getting and setting fields -----------------------------
7484

7585
private[this] var myFlags: FlagSet = adaptFlags(initFlags)
@@ -171,13 +181,13 @@ object SymDenotations {
171181
myInfo = tp
172182
}
173183

174-
/** The name, except
175-
* - if this is a module class, strip the module class suffix
176-
* - if this is a companion object with a clash-avoiding name, strip the
184+
/** The name, except
185+
* - if this is a module class, strip the module class suffix
186+
* - if this is a companion object with a clash-avoiding name, strip the
177187
* "avoid clash" suffix
178188
*/
179189
def effectiveName(implicit ctx: Context) =
180-
if (this is ModuleClass) name.stripModuleClassSuffix
190+
if (this is ModuleClass) name.stripModuleClassSuffix
181191
else name.stripAvoidClashSuffix
182192

183193
/** The privateWithin boundary, NoSymbol if no boundary is given.
@@ -195,7 +205,7 @@ object SymDenotations {
195205

196206
/** Update the annotations of this denotation */
197207
private[core] final def annotations_=(annots: List[Annotation]): Unit =
198-
myAnnotations = annots
208+
myAnnotations = annots
199209

200210
/** Does this denotation have an annotation matching the given class symbol? */
201211
final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
@@ -241,9 +251,9 @@ object SymDenotations {
241251
/** The symbols defined in this class or object.
242252
* Careful! This does not force the type, so is compilation order dependent.
243253
* This method should be used only in the following circumstances:
244-
*
245-
* 1. When accessing type parameters or type parameter accessors (both are entered before
246-
* completion).
254+
*
255+
* 1. When accessing type parameters or type parameter accessors (both are entered before
256+
* completion).
247257
* 2. When obtaining the current scope in order to enter, rename or delete something there.
248258
* 3. When playing it safe in order not to raise CylicReferences, e.g. for printing things
249259
* or taking more efficient shortcuts (e.g. the stillValid test).
@@ -292,7 +302,6 @@ object SymDenotations {
292302
if (isType) fn.toTypeName else fn.toTermName
293303
}
294304

295-
296305
/** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */
297306
def flatName(separator: Char = '$')(implicit ctx: Context): Name =
298307
if (symbol == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot || (owner is PackageClass)) name
@@ -457,7 +466,7 @@ object SymDenotations {
457466
}
458467

459468
/** Is this a user defined "def" method? Excluded are accessors and anonymous functions. */
460-
final def isSourceMethod(implicit ctx: Context) =
469+
final def isSourceMethod(implicit ctx: Context) =
461470
this.is(Method, butNot = AccessorOrLabel) && !isAnonymousFunction
462471

463472
/** Is this a setter? */
@@ -649,7 +658,7 @@ object SymDenotations {
649658
*/
650659
/** The class implementing this module, NoSymbol if not applicable. */
651660
final def moduleClass(implicit ctx: Context): Symbol = {
652-
def notFound = {println(s"missing module class for $name: $myInfo"); NoSymbol}
661+
def notFound = { println(s"missing module class for $name: $myInfo"); NoSymbol }
653662
if (this is ModuleVal)
654663
myInfo match {
655664
case info: TypeRef => info.symbol
@@ -1002,7 +1011,7 @@ object SymDenotations {
10021011
s"$kindString $name"
10031012
}
10041013

1005-
def debugString = toString+"#"+symbol.id // !!! DEBUG
1014+
def debugString = toString + "#" + symbol.id // !!! DEBUG
10061015

10071016
// ----- copies and transforms ----------------------------------------
10081017

@@ -1097,8 +1106,8 @@ object SymDenotations {
10971106

10981107
private var firstRunId: RunId = initRunId
10991108

1100-
/** If caches influenced by parent classes are still valid, the denotation
1101-
* itself, otherwise a freshly initialized copy.
1109+
/** invalidate caches influenced by parent classes if one of the parents
1110+
* is younger than the denotation itself.
11021111
*/
11031112
override def syncWithParents(implicit ctx: Context): SingleDenotation = {
11041113
def isYounger(tref: TypeRef) = tref.symbol.denot match {
@@ -1124,7 +1133,7 @@ object SymDenotations {
11241133
}
11251134

11261135
/** Invalidate all caches and fields that depend on base classes and their contents */
1127-
private def invalidateInheritedInfo(): Unit = {
1136+
override def invalidateInheritedInfo(): Unit = {
11281137
myBaseClasses = null
11291138
mySuperClassBits = null
11301139
myMemberFingerPrint = FingerPrint.unknown
@@ -1168,7 +1177,7 @@ object SymDenotations {
11681177
private[this] var myBaseClasses: List[ClassSymbol] = null
11691178
private[this] var mySuperClassBits: BitSet = null
11701179

1171-
/** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
1180+
/** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
11721181
private def checkBasesUpToDate()(implicit ctx: Context) =
11731182
if (baseTypeRefValid != ctx.runId) {
11741183
baseTypeRefCache = new java.util.HashMap[CachedType, Type]

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,17 @@ class TypeApplications(val self: Type) extends AnyVal {
191191
if (res.isInstantiatedLambda) res.select(tpnme.Apply) else res
192192
}
193193
}
194+
195+
/** Simplify a fully instantiated type of the form `LambdaX{... type Apply = T } # Apply` to `T`.
196+
*/
197+
def simplifyApply(implicit ctx: Context): Type = self match {
198+
case self @ TypeRef(prefix, tpnme.Apply) if prefix.isInstantiatedLambda =>
199+
prefix.member(tpnme.Apply).info match {
200+
case TypeAlias(alias) => alias
201+
case _ => self
202+
}
203+
case _ => self
204+
}
194205

195206
final def appliedTo(arg: Type)(implicit ctx: Context): Type = appliedTo(arg :: Nil)
196207
final def appliedTo(arg1: Type, arg2: Type)(implicit ctx: Context): Type = appliedTo(arg1 :: arg2 :: Nil)

src/dotty/tools/dotc/core/Types.scala

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ object Types {
480480
case ex: MergeError =>
481481
throw new MergeError(s"${ex.getMessage} as members of type ${pre.show}")
482482
case ex: Throwable =>
483-
println(i"findMember exception for $this: ${this.widen} member $name")
483+
println(s"findMember exception for $this member $name")
484484
throw ex // DEBUG
485485
} finally {
486486
recCount -= 1
@@ -1158,7 +1158,7 @@ object Types {
11581158
private[this] var lastDenotation: Denotation = _
11591159
private[this] var lastSymbol: Symbol = _
11601160
private[this] var checkedPeriod = Nowhere
1161-
1161+
11621162
// Invariants:
11631163
// (1) checkedPeriod != Nowhere => lastDenotation != null
11641164
// (2) lastDenotation != null => lastSymbol != null
@@ -1238,8 +1238,7 @@ object Types {
12381238
// phase but a defined denotation earlier (e.g. a TypeRef to an abstract type
12391239
// is undefined after erasure.) We need to be able to do time travel back and
12401240
// forth also in these cases.
1241-
lastDenotation = d
1242-
lastSymbol = d.symbol
1241+
setDenot(d)
12431242
checkedPeriod = ctx.period
12441243
}
12451244
d
@@ -1256,9 +1255,14 @@ object Types {
12561255
private def checkSymAssign(sym: Symbol)(implicit ctx: Context) =
12571256
assert(
12581257
(lastSymbol eq sym) ||
1259-
(lastSymbol eq null) ||
1260-
(lastSymbol.defRunId != sym.defRunId) ||
1261-
(lastSymbol.defRunId == NoRunId) ||
1258+
(lastSymbol eq null) || {
1259+
val lastDefRunId = lastDenotation match {
1260+
case d: SymDenotation => d.validFor.runId
1261+
case _ => lastSymbol.defRunId
1262+
}
1263+
(lastDefRunId != sym.defRunId) ||
1264+
(lastDefRunId == NoRunId)
1265+
} ||
12621266
(lastSymbol.infoOrCompleter == ErrorType ||
12631267
defn.overriddenBySynthetic.contains(lastSymbol)
12641268
// for overriddenBySynthetic symbols a TermRef such as SomeCaseClass.this.hashCode
@@ -1280,6 +1284,9 @@ object Types {
12801284
if (Config.checkNoDoubleBindings)
12811285
if (ctx.settings.YnoDoubleBindings.value)
12821286
checkSymAssign(denot.symbol)
1287+
1288+
// additional checks that intercept `denot` can be added here
1289+
12831290
lastDenotation = denot
12841291
lastSymbol = denot.symbol
12851292
}

src/dotty/tools/dotc/core/pickling/NameBuffer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ class NameBuffer extends TastyBuffer(100000) {
6565
case Signed(original, params, result) =>
6666
writeByte(SIGNED)
6767
withLength { writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) }
68-
case Expanded(original) =>
68+
case Expanded(prefix, original) =>
6969
writeByte(EXPANDED)
70-
withLength { writeNameRef(original) }
70+
withLength { writeNameRef(prefix); writeNameRef(original) }
7171
case ModuleClass(module) =>
7272
writeByte(OBJECTCLASS)
7373
withLength { writeNameRef(module) }

src/dotty/tools/dotc/core/pickling/PickleFormat.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ object PickleFormat {
269269
final val DOUBLEconst = 76
270270
final val STRINGconst = 77
271271
final val IMPORTED = 78
272-
272+
273273
final val THIS = 96
274274
final val CLASSconst = 97
275275
final val ENUMconst = 98

src/dotty/tools/dotc/core/pickling/TastyName.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ object TastyName {
1515
case class Simple(name: TermName) extends TastyName
1616
case class Qualified(qualified: NameRef, selector: NameRef) extends TastyName
1717
case class Signed(original: NameRef, params: List[NameRef], result: NameRef) extends TastyName
18-
case class Expanded(original: NameRef) extends TastyName
18+
case class Expanded(prefix: NameRef, original: NameRef) extends TastyName
1919
case class ModuleClass(module: NameRef) extends TastyName
2020
case class SuperAccessor(accessed: NameRef) extends TastyName
2121
case class DefaultGetter(method: NameRef, num: Int) extends TastyName

src/dotty/tools/dotc/core/pickling/TastyPrinter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package pickling
55
import Contexts._, Decorators._
66
import printing.Texts._
77
import TastyName._
8+
import StdNames._
89
import TastyUnpickler._
910
import TastyBuffer.Addr
1011
import util.Positions.{Position, offsetToInt}
@@ -20,7 +21,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
2021
case Qualified(qual, name) => nameRefToString(qual) + "." + nameRefToString(name)
2122
case Signed(original, params, result) =>
2223
i"${nameRefToString(original)}@${params.map(nameRefToString)}%,%:${nameRefToString(result)}"
23-
case Expanded(original) => nameRefToString(original) + "/EXPANDED"
24+
case Expanded(prefix, original) => s"$prefix${nme.EXPAND_SEPARATOR}$original"
2425
case ModuleClass(original) => nameRefToString(original) + "/MODULECLASS"
2526
case SuperAccessor(accessed) => nameRefToString(accessed) + "/SUPERACCESSOR"
2627
case DefaultGetter(meth, num) => nameRefToString(meth) + "/DEFAULTGETTER" + num

0 commit comments

Comments
 (0)