Skip to content

Commit 596e017

Browse files
committed
Tasty: Fix unpickling position of SHARED TypeTrees
1 parent a6394e9 commit 596e017

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ class TreePickler(pickler: TastyPickler) {
519519
writeByte(PACKAGE)
520520
withLength { pickleType(pid.tpe); pickleStats(stats) }
521521
case tree: TypeTree =>
522+
// See the comment in TreeUnpickler#readTpt to know why this is required
523+
assert(tree.pos.exists, "Cannot pickle $tree because it doesn't have a position.")
522524
pickleType(tree.tpe)
523525
case SingletonTypeTree(ref) =>
524526
writeByte(SINGLETONtpt)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,30 @@ class TreeUnpickler(reader: TastyReader,
10551055
else {
10561056
val start = currentAddr
10571057
val tp = readType()
1058-
if (tp.exists) setPos(start, TypeTree(tp)) else EmptyTree
1058+
if (tp.exists) {
1059+
val tree = TypeTree(tp)
1060+
var addr = start
1061+
var pos = posAt(addr)
1062+
// This is subtle: when a TypeTree is pickled as just a type, we don't know if SHARED
1063+
// means that just the type is shared, or the full TypeTree is shared. This matter
1064+
// when trying to set the position of a TypeTree:
1065+
// - If just the type is shared, then the SHARED node will have its
1066+
// own pickled position for the TypeTree.
1067+
// - If the full TypeTree is shared then the SHARED node will have no
1068+
// position on its own, and we need to look at the position at the
1069+
// referenced address.
1070+
//
1071+
// To distinguish between the two, we assume that pickled TypeTrees always have
1072+
// a pickled position, this is enforced in TreePickler#pickleTree
1073+
while (pos == NoPosition && bytes(index(addr)) == SHARED) {
1074+
val sharedFork = fork
1075+
sharedFork.reader.readByte()
1076+
addr = sharedFork.reader.readAddr()
1077+
pos = posAt(addr)
1078+
}
1079+
if (pos.exists) tree.setPosUnchecked(pos)
1080+
tree
1081+
} else EmptyTree
10591082
}
10601083

10611084
def readCases(end: Addr)(implicit ctx: Context): List[CaseDef] =

0 commit comments

Comments
 (0)