Skip to content

Fix #5449: Index class definitions before unpickling parents #5500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,8 @@ object TastyFormat {
case VALDEF | DEFDEF | TYPEDEF | OBJECTDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
SELFDEF | REFINEDtype | TERMREFin | TYPEREFin | HOLE => 1
case RENAMED | PARAMtype => 2
case POLYtype | METHODtype | TYPELAMBDAtype => -1
case POLYtype | METHODtype | IMPLICITMETHODtype | ERASEDMETHODtype | ERASEDIMPLICITMETHODtype |
TYPELAMBDAtype => -1
case _ => 0
}
}
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,14 @@ class TreeUnpickler(reader: TastyReader,
val end = readEnd()
val tparams = readIndexedParams[TypeDef](TYPEPARAM)
val vparams = readIndexedParams[ValDef](PARAM)
// It's important to index the class definitions before unpickling the parents
// (see the parents-cycle test for examples where this matter)
val bodyFlags = {
val bodyIndexer = fork
// The first DEFDEF corresponds to the primary constructor
while (bodyIndexer.reader.nextByte != DEFDEF) bodyIndexer.skipTree()
bodyIndexer.indexStats(end)
}
val parents = collectWhile(nextByte != SELFDEF && nextByte != DEFDEF) {
nextUnsharedTag match {
case APPLY | TYPEAPPLY | BLOCK => readTerm()(parentCtx)
Expand All @@ -884,7 +892,7 @@ class TreeUnpickler(reader: TastyReader,
else EmptyValDef
cls.info = ClassInfo(cls.owner.thisType, cls, parentTypes, cls.unforcedDecls,
if (self.isEmpty) NoType else self.tpt.tpe)
cls.setNoInitsFlags(parentsKind(parents), fork.indexStats(end))
cls.setNoInitsFlags(parentsKind(parents), bodyFlags)
val constr = readIndexedDef().asInstanceOf[DefDef]
val mappedParents = parents.map(_.changeOwner(localDummy, constr.symbol))

Expand Down
15 changes: 15 additions & 0 deletions tests/pos-separate-compilation/parents-cycle/Def_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class A[T]
// Unpickling the parents of B1 will lead to unpickling a call to B1.<init>
class B1 extends A[C1]
class C1 extends B1

// Unpickling the parents of B2 will lead to unpickling a call to the secondary B2.<init>
class B2 extends A[C2] {
def this(x: Int) = this()
}
class C2 extends B2(1)

// Unpickling the parents of B3 will lead to unpickling a call to B3#Hi
class B3 extends A[B3#Hi[Int]] {
type Hi[X] = X
}
5 changes: 5 additions & 0 deletions tests/pos-separate-compilation/parents-cycle/Use_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object Use {
val b1 = new B1
val b2 = new B2
val b3 = new B3
}