@@ -70,19 +70,13 @@ class ExtractAPI extends Phase {
70
70
71
71
override def runOn (units : List [CompilationUnit ])(using Context ): List [CompilationUnit ] =
72
72
val doZincCallback = ctx.runZincPhases
73
- val sigWriter : Option [Pickler .EarlyFileWriter ] = ctx.settings.YearlyTastyOutput .value match
74
- case earlyOut if earlyOut.isDirectory && earlyOut.exists =>
75
- Some (Pickler .EarlyFileWriter (earlyOut))
76
- case _ =>
77
- None
78
73
val nonLocalClassSymbols = new mutable.HashSet [Symbol ]
79
74
val units0 =
80
75
if doZincCallback then
81
76
val ctx0 = ctx.withProperty(NonLocalClassSymbolsInCurrentUnits , Some (nonLocalClassSymbols))
82
77
super .runOn(units)(using ctx0)
83
78
else
84
79
units // still run the phase for the side effects (writing TASTy files to -Yearly-tasty-output)
85
- sigWriter.foreach(writeSigFiles(units0, _))
86
80
if doZincCallback then
87
81
ctx.withIncCallback(recordNonLocalClasses(nonLocalClassSymbols, _))
88
82
if ctx.settings.YjavaTasty .value then
@@ -91,57 +85,12 @@ class ExtractAPI extends Phase {
91
85
units0
92
86
end runOn
93
87
94
- // Why we only write to early output in the first run?
95
- // ===================================================
96
- // TL;DR the point of pipeline compilation is to start downstream projects early,
97
- // so we don't want to wait for suspended units to be compiled.
98
- //
99
- // But why is it safe to ignore suspended units?
100
- // If this project contains a transparent macro that is called in the same project,
101
- // the compilation unit of that call will be suspended (if the macro implementation
102
- // is also in this project), causing a second run.
103
- // However before we do that run, we will have already requested sbt to begin
104
- // early downstream compilation. This means that the suspended definitions will not
105
- // be visible in *early* downstream compilation.
106
- //
107
- // However, sbt will by default prevent downstream compilation happening in this scenario,
108
- // due to the existence of macro definitions. So we are protected from failure if user tries
109
- // to use the suspended definitions.
110
- //
111
- // Additionally, it is recommended for the user to move macro implementations to another project
112
- // if they want to force early output. In this scenario the suspensions will no longer occur, so now
113
- // they will become visible in the early-output.
114
- //
115
- // See `sbt-test/pipelining/pipelining-scala-macro` and `sbt-test/pipelining/pipelining-scala-macro-force`
116
- // for examples of this in action.
117
- //
118
- // Therefore we only need to write to early output in the first run. We also provide the option
119
- // to diagnose suspensions with the `-Yno-suspended-units` flag.
120
- private def writeSigFiles (units : List [CompilationUnit ], writer : Pickler .EarlyFileWriter )(using Context ): Unit = {
121
- try
122
- for
123
- unit <- units
124
- (cls, pickled) <- unit.pickled
125
- if cls.isDefinedInCurrentRun
126
- do
127
- val internalName =
128
- if cls.is(Module ) then cls.binaryClassName.stripSuffix(str.MODULE_SUFFIX ).nn
129
- else cls.binaryClassName
130
- val _ = writer.writeTasty(internalName, pickled())
131
- finally
132
- writer.close()
133
- if ctx.settings.verbose.value then
134
- report.echo(" [sig files written]" )
135
- end try
136
- }
137
-
138
88
private def recordNonLocalClasses (nonLocalClassSymbols : mutable.HashSet [Symbol ], cb : interfaces.IncrementalCallback )(using Context ): Unit =
139
89
for cls <- nonLocalClassSymbols do
140
90
val sourceFile = cls.source
141
91
if sourceFile.exists && cls.isDefinedInCurrentRun then
142
92
recordNonLocalClass(cls, sourceFile, cb)
143
- cb.apiPhaseCompleted()
144
- cb.dependencyPhaseCompleted()
93
+ ctx.run.nn.asyncTasty.foreach(_.signalAPIComplete())
145
94
146
95
private def recordNonLocalClass (cls : Symbol , sourceFile : SourceFile , cb : interfaces.IncrementalCallback )(using Context ): Unit =
147
96
def registerProductNames (fullClassName : String , binaryClassName : String ) =
0 commit comments