@@ -1164,37 +1164,38 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
11641164 * in the same way as Typer does. The code addresses additional concerns:
11651165 * - be tail-recursive where possible
11661166 * - don't re-allocate trees where nothing has changed
1167+ * - avoid stack overflows for long statement lists
11671168 */
11681169 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
11821173 case stat :: rest =>
1183- val statCtx = stat match
1174+ def statCtx = stat match
11841175 case _ : DefTree | _ : ImportOrExport => ctx
11851176 case _ => ctx.exprContext(stat, exprOwner)
1186- val restCtx = stat match
1177+ def restCtx = stat match
11871178 case stat : Import => ctx.importContext(stat, stat.symbol)
11881179 case _ => ctx
11891180 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)
11921193 case nil =>
1193- stats
1194+ if mapped == null then unchanged
1195+ else mapped.prependToList(unchanged)
11941196
1195- traverse( stats)
1197+ loop( null , stats, stats)
11961198 end transformStats
1197-
11981199 end TreeMapWithPreciseStatContexts
11991200
12001201 /** Map Inlined nodes, NamedArgs, Blocks with no statements and local references to underlying arguments.
0 commit comments