@@ -109,7 +109,10 @@ class TreeUnpickler(reader: TastyReader,
109109 while (nextByte == PARAMS || nextByte == TYPEPARAM ) skipTree()
110110
111111 /** Record all directly nested definitions and templates in current tree
112- * as `OwnerTree`s in `buf`
112+ * as `OwnerTree`s in `buf`.
113+ * A complication concerns member definitions. These are lexically nested in a
114+ * Template node, but need to be listed separately in the OwnerTree of the enclosing class
115+ * in order not to confuse owner chains.
113116 */
114117 def scanTree (buf : ListBuffer [OwnerTree ], mode : MemberDefMode = AllDefs ): Unit = {
115118 val start = currentAddr
@@ -118,8 +121,15 @@ class TreeUnpickler(reader: TastyReader,
118121 case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | TEMPLATE =>
119122 val end = readEnd()
120123 for (i <- 0 until numRefs(tag)) readNat()
121- if (tag == TEMPLATE ) scanTrees(buf, end, MemberDefsOnly )
122- if (mode != NoMemberDefs ) buf += new OwnerTree (start, tag, fork, end)
124+ if (tag == TEMPLATE ) {
125+ // Read all member definitions now, whereas non-members are children of
126+ // template's owner tree.
127+ val nonMemberReader = fork
128+ scanTrees(buf, end, MemberDefsOnly )
129+ buf += new OwnerTree (start, tag, nonMemberReader, end)
130+ }
131+ else if (mode != NoMemberDefs )
132+ buf += new OwnerTree (start, tag, fork, end)
123133 goto(end)
124134 case tag =>
125135 if (mode == MemberDefsOnly ) skipTree(tag)
@@ -132,7 +142,11 @@ class TreeUnpickler(reader: TastyReader,
132142 }
133143 else {
134144 for (i <- 0 until nrefs) readNat()
135- scanTrees(buf, end)
145+ if (tag == BIND ) {
146+ buf += new OwnerTree (start, tag, fork, end)
147+ goto(end)
148+ }
149+ else scanTrees(buf, end)
136150 }
137151 }
138152 else if (tag >= firstNatASTTreeTag) { readNat(); scanTree(buf) }
@@ -267,12 +281,6 @@ class TreeUnpickler(reader: TastyReader,
267281 OrType (readType(), readType())
268282 case SUPERtype =>
269283 SuperType (readType(), readType())
270- case BIND =>
271- val sym = ctx.newSymbol(ctx.owner, readName().toTypeName, BindDefinedType , readType(),
272- coord = coordAt(start))
273- registerSym(start, sym)
274- if (currentAddr != end) readType()
275- TypeRef (NoPrefix , sym)
276284 case POLYtype =>
277285 readMethodic(PolyType , _.toTypeName)
278286 case METHODtype =>
@@ -431,6 +439,8 @@ class TreeUnpickler(reader: TastyReader,
431439 def createSymbol ()(implicit ctx : Context ): Symbol = nextByte match {
432440 case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM =>
433441 createMemberSymbol()
442+ case BIND =>
443+ createBindSymbol()
434444 case TEMPLATE =>
435445 val localDummy = ctx.newLocalDummy(ctx.owner)
436446 registerSym(currentAddr, localDummy)
@@ -439,6 +449,25 @@ class TreeUnpickler(reader: TastyReader,
439449 throw new Error (s " illegal createSymbol at $currentAddr, tag = $tag" )
440450 }
441451
452+ private def createBindSymbol ()(implicit ctx : Context ): Symbol = {
453+ val start = currentAddr
454+ val tag = readByte()
455+ val end = readEnd()
456+ var name : Name = readName()
457+ nextUnsharedTag match {
458+ case TYPEBOUNDS | TYPEALIAS => name = name.toTypeName
459+ case _ =>
460+ }
461+ val typeReader = fork
462+ val completer = new LazyType {
463+ def complete (denot : SymDenotation )(implicit ctx : Context ) =
464+ denot.info = typeReader.readType()
465+ }
466+ val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags , completer, coord = coordAt(start))
467+ registerSym(start, sym)
468+ sym
469+ }
470+
442471 /** Create symbol of member definition or parameter node and enter in symAtAddr map
443472 * @return the created symbol
444473 */
@@ -994,10 +1023,9 @@ class TreeUnpickler(reader: TastyReader,
9941023 val elemtpt = readTpt()
9951024 SeqLiteral (until(end)(readTerm()), elemtpt)
9961025 case BIND =>
997- val name = readName()
998- val info = readType()
999- val sym = ctx.newSymbol(ctx.owner, name, EmptyFlags , info, coord = coordAt(start))
1000- registerSym(start, sym)
1026+ val sym = symAtAddr.getOrElse(start, forkAt(start).createSymbol())
1027+ readName()
1028+ readType()
10011029 Bind (sym, readTerm())
10021030 case ALTERNATIVE =>
10031031 Alternative (until(end)(readTerm()))
@@ -1154,11 +1182,16 @@ class TreeUnpickler(reader: TastyReader,
11541182 */
11551183 class OwnerTree (val addr : Addr , tag : Int , reader : TreeReader , val end : Addr ) {
11561184
1185+ private var myChildren : List [OwnerTree ] = null
1186+
11571187 /** All definitions that have the definition at `addr` as closest enclosing definition */
1158- lazy val children : List [OwnerTree ] = {
1159- val buf = new ListBuffer [OwnerTree ]
1160- reader.scanTrees(buf, end, if (tag == TEMPLATE ) NoMemberDefs else AllDefs )
1161- buf.toList
1188+ def children : List [OwnerTree ] = {
1189+ if (myChildren == null ) myChildren = {
1190+ val buf = new ListBuffer [OwnerTree ]
1191+ reader.scanTrees(buf, end, if (tag == TEMPLATE ) NoMemberDefs else AllDefs )
1192+ buf.toList
1193+ }
1194+ myChildren
11621195 }
11631196
11641197 /** Find the owner of definition at `addr` */
@@ -1177,13 +1210,19 @@ class TreeUnpickler(reader: TastyReader,
11771210 }
11781211 catch {
11791212 case ex : TreeWithoutOwner =>
1180- println(i " no owner for $addr among $cs" ) // DEBUG
1213+ pickling.println(i " no owner for $addr among $cs%, % " )
1214+ throw ex
1215+ }
1216+ try search(children, NoSymbol )
1217+ catch {
1218+ case ex : TreeWithoutOwner =>
1219+ pickling.println(s " ownerTree = $ownerTree" )
11811220 throw ex
11821221 }
1183- search(children, NoSymbol )
11841222 }
11851223
1186- override def toString = s " OwnerTree( ${addr.index}, ${end.index}"
1224+ override def toString =
1225+ s " OwnerTree( ${addr.index}, ${end.index}, ${if (myChildren == null ) " ?" else myChildren.mkString(" " )}) "
11871226 }
11881227}
11891228
0 commit comments