@@ -1164,37 +1164,38 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
1164
1164
* in the same way as Typer does. The code addresses additional concerns:
1165
1165
* - be tail-recursive where possible
1166
1166
* - don't re-allocate trees where nothing has changed
1167
+ * - avoid stack overflows for long statement lists
1167
1168
*/
1168
1169
override def transformStats (stats : List [Tree ], exprOwner : Symbol )(using Context ): List [Tree ] =
1169
-
1170
- @ tailrec def traverse (curStats : List [Tree ])(using Context ): List [Tree ] =
1171
-
1172
- def recur (stats : List [Tree ], changed : Tree , rest : List [Tree ])(using Context ): List [Tree ] =
1173
- if stats eq curStats then
1174
- val rest1 = transformStats(rest, exprOwner)
1175
- changed match
1176
- case Thicket (trees) => trees ::: rest1
1177
- case tree => tree :: rest1
1178
- else
1179
- stats.head :: recur(stats.tail, changed, rest)
1180
-
1181
- curStats match
1170
+ @ tailrec
1171
+ def loop (mapped : mutable.ListBuffer [Tree ] | Null , unchanged : List [Tree ], pending : List [Tree ])(using Context ): List [Tree ] =
1172
+ pending match
1182
1173
case stat :: rest =>
1183
- val statCtx = stat match
1174
+ def statCtx = stat match
1184
1175
case _ : DefTree | _ : ImportOrExport => ctx
1185
1176
case _ => ctx.exprContext(stat, exprOwner)
1186
- val restCtx = stat match
1177
+ def restCtx = stat match
1187
1178
case stat : Import => ctx.importContext(stat, stat.symbol)
1188
1179
case _ => ctx
1189
1180
val stat1 = transform(stat)(using statCtx)
1190
- if stat1 ne stat then recur(stats, stat1, rest)(using restCtx)
1191
- else traverse(rest)(using restCtx)
1181
+ if stat1 eq stat then
1182
+ loop(mapped, unchanged, rest)
1183
+ else
1184
+ val buf = if mapped == null then new mutable.ListBuffer [Tree ] else mapped
1185
+ var xc = unchanged
1186
+ while xc ne pending do
1187
+ buf += xc.head
1188
+ xc = xc.tail
1189
+ stat1 match
1190
+ case Thicket (stats1) => buf ++= stats1
1191
+ case _ => buf += stat1
1192
+ loop(buf, rest, rest)(using restCtx)
1192
1193
case nil =>
1193
- stats
1194
+ if mapped == null then unchanged
1195
+ else mapped.prependToList(unchanged)
1194
1196
1195
- traverse( stats)
1197
+ loop( null , stats, stats)
1196
1198
end transformStats
1197
-
1198
1199
end TreeMapWithPreciseStatContexts
1199
1200
1200
1201
/** Map Inlined nodes, NamedArgs, Blocks with no statements and local references to underlying arguments.
0 commit comments