@@ -37,6 +37,7 @@ import scala.io.Codec
3737import Run .Progress
3838import scala .compiletime .uninitialized
3939import dotty .tools .dotc .transform .MegaPhase
40+ import dotty .tools .dotc .transform .Pickler .AsyncTastyHolder
4041
4142/** A compiler run. Exports various methods to compile source files */
4243class Run (comp : Compiler , ictx : Context ) extends ImplicitRunInfo with ConstraintRunInfo {
@@ -130,7 +131,10 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
130131 myUnits = us
131132
132133 var suspendedUnits : mutable.ListBuffer [CompilationUnit ] = mutable.ListBuffer ()
133- var suspendedHints : mutable.Map [CompilationUnit , String ] = mutable.HashMap ()
134+ var suspendedHints : mutable.Map [CompilationUnit , (String , Boolean )] = mutable.HashMap ()
135+
136+ /** Were any units suspended in the typer phase? if so then pipeline tasty can not complete. */
137+ var suspendedAtTyperPhase : Boolean = false
134138
135139 def checkSuspendedUnits (newUnits : List [CompilationUnit ])(using Context ): Unit =
136140 if newUnits.isEmpty && suspendedUnits.nonEmpty && ! ctx.reporter.errorsReported then
@@ -231,6 +235,24 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
231235 if ! progress.isCancelled() then
232236 progress.tickSubphase()
233237
238+ /** if true, then we are done writing pipelined TASTy files (i.e. finished in a previous run.) */
239+ private var myAsyncTastyWritten = false
240+
241+ private var _asyncTasty : Option [AsyncTastyHolder ] = None
242+
243+ /** populated when this run needs to write pipeline TASTy files. */
244+ def asyncTasty : Option [AsyncTastyHolder ] = _asyncTasty
245+
246+ private def initializeAsyncTasty ()(using Context ): () => Context ?=> Unit =
247+ // should we provide a custom ExecutionContext?
248+ // currently it is just used to call the `apiPhaseCompleted` and `dependencyPhaseCompleted` callbacks in Zinc
249+ import scala .concurrent .ExecutionContext .Implicits .global
250+ val async = AsyncTastyHolder .init
251+ _asyncTasty = Some (async)
252+ () => ctx ?=>
253+ if ctx.reporter.hasErrors then
254+ async.cancel()
255+
234256 /** Will be set to true if any of the compiled compilation units contains
235257 * a pureFunctions language import.
236258 */
@@ -342,13 +364,22 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
342364
343365 val runCtx = ctx.fresh
344366 runCtx.setProfiler(Profiler ())
367+
368+ val cancelAsyncTasty : () => Context ?=> Unit =
369+ if ! myAsyncTastyWritten && Phases .picklerPhase.exists && ! ctx.settings.YearlyTastyOutput .isDefault then
370+ initializeAsyncTasty()
371+ else () => {}
372+
345373 unfusedPhases.foreach(_.initContext(runCtx))
346374 val fusedPhases = runCtx.base.allPhases
347375 if ctx.settings.explainCyclic.value then
348376 runCtx.setProperty(CyclicReference .Trace , new CyclicReference .Trace ())
349377 runCtx.withProgressCallback: cb =>
350378 _progress = Progress (cb, this , fusedPhases.map(_.traversals).sum)
379+
351380 runPhases(allPhases = fusedPhases)(using runCtx)
381+ cancelAsyncTasty()
382+
352383 ctx.reporter.finalizeReporting()
353384 if (! ctx.reporter.hasErrors)
354385 Rewrites .writeBack()
@@ -365,9 +396,12 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
365396 /** Is this run started via a compilingSuspended? */
366397 def isCompilingSuspended : Boolean = myCompilingSuspended
367398
368- /** Compile units `us` which were suspended in a previous run */
369- def compileSuspendedUnits (us : List [CompilationUnit ]): Unit =
399+ /** Compile units `us` which were suspended in a previous run,
400+ * also signal if all necessary async tasty files were written in a previous run.
401+ */
402+ def compileSuspendedUnits (us : List [CompilationUnit ], asyncTastyWritten : Boolean ): Unit =
370403 myCompilingSuspended = true
404+ myAsyncTastyWritten = asyncTastyWritten
371405 for unit <- us do unit.suspended = false
372406 compileUnits(us)
373407
0 commit comments