@@ -109,17 +109,27 @@ class TreeUnpickler(reader: TastyReader,
109
109
while (nextByte == PARAMS || nextByte == TYPEPARAM ) skipTree()
110
110
111
111
/** 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.
113
116
*/
114
117
def scanTree (buf : ListBuffer [OwnerTree ], mode : MemberDefMode = AllDefs ): Unit = {
115
118
val start = currentAddr
116
119
val tag = readByte()
117
120
tag match {
118
- case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | TEMPLATE | BIND =>
121
+ case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | TEMPLATE =>
119
122
val end = readEnd()
120
123
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)
123
133
goto(end)
124
134
case tag =>
125
135
if (mode == MemberDefsOnly ) skipTree(tag)
@@ -132,7 +142,11 @@ class TreeUnpickler(reader: TastyReader,
132
142
}
133
143
else {
134
144
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)
136
150
}
137
151
}
138
152
else if (tag >= firstNatASTTreeTag) { readNat(); scanTree(buf) }
@@ -1172,11 +1186,16 @@ class TreeUnpickler(reader: TastyReader,
1172
1186
*/
1173
1187
class OwnerTree (val addr : Addr , tag : Int , reader : TreeReader , val end : Addr ) {
1174
1188
1189
+ private var myChildren : List [OwnerTree ] = null
1190
+
1175
1191
/** All definitions that have the definition at `addr` as closest enclosing definition */
1176
- lazy val children : List [OwnerTree ] = {
1177
- val buf = new ListBuffer [OwnerTree ]
1178
- reader.scanTrees(buf, end, if (tag == TEMPLATE ) NoMemberDefs else AllDefs )
1179
- buf.toList
1192
+ def children : List [OwnerTree ] = {
1193
+ if (myChildren == null ) myChildren = {
1194
+ val buf = new ListBuffer [OwnerTree ]
1195
+ reader.scanTrees(buf, end, if (tag == TEMPLATE ) NoMemberDefs else AllDefs )
1196
+ buf.toList
1197
+ }
1198
+ myChildren
1180
1199
}
1181
1200
1182
1201
/** Find the owner of definition at `addr` */
@@ -1195,13 +1214,19 @@ class TreeUnpickler(reader: TastyReader,
1195
1214
}
1196
1215
catch {
1197
1216
case ex : TreeWithoutOwner =>
1198
- println(i " no owner for $addr among $cs" ) // DEBUG
1217
+ pickling.println(i " no owner for $addr among $cs%, % " )
1218
+ throw ex
1219
+ }
1220
+ try search(children, NoSymbol )
1221
+ catch {
1222
+ case ex : TreeWithoutOwner =>
1223
+ pickling.println(s " ownerTree = $ownerTree" )
1199
1224
throw ex
1200
1225
}
1201
- search(children, NoSymbol )
1202
1226
}
1203
1227
1204
- override def toString = s " OwnerTree( ${addr.index}, ${end.index}"
1228
+ override def toString =
1229
+ s " OwnerTree( ${addr.index}, ${end.index}, ${if (myChildren == null ) " ?" else myChildren.mkString(" " )}) "
1205
1230
}
1206
1231
}
1207
1232
0 commit comments