@@ -100,6 +100,32 @@ extension ModuleDependencyGraph {
100
100
}
101
101
}
102
102
103
+ var shouldNewExternalDependenciesTriggerInvalidation : Bool {
104
+ switch self {
105
+ case . buildingWithoutAPrior:
106
+ // Reading graph from a swiftdeps file,
107
+ // so every incremental external dependency found will be new to the
108
+ // graph. Don't invalidate just 'cause it's new.
109
+ return false
110
+
111
+ case . buildingAfterEachCompilation:
112
+ // Will be compiling every file, so no need to invalidate based on
113
+ // found external dependencies.
114
+ return false
115
+
116
+ // Reading a swiftdeps file after a compilation.
117
+ // A new external dependency represents an addition.
118
+ // So must invalidate based on it.
119
+ case . updatingAfterCompilation:
120
+ return true
121
+
122
+ case . updatingFromAPrior:
123
+ // If the graph was read from priors,
124
+ // then any new external dependency must also be an addition.
125
+ return true
126
+ }
127
+ }
128
+
103
129
var isCompilingAllInputsNoMatterWhat : Bool {
104
130
switch self {
105
131
case . buildingAfterEachCompilation:
@@ -240,6 +266,7 @@ extension ModuleDependencyGraph {
240
266
/// As an optimization, only return the nodes that have not been already traced, because the traced nodes
241
267
/// will have already been used to schedule jobs to run.
242
268
/*@_spi(Testing)*/ public func collectUntracedNodesUsing(
269
+ _ why: ExternalDependency . Why ,
243
270
_ fingerprintedExternalDependency: FingerprintedExternalDependency
244
271
) -> DirectlyInvalidatedNodeSet {
245
272
// These nodes will depend on the *interface* of the external Decl.
@@ -252,10 +279,12 @@ extension ModuleDependencyGraph {
252
279
let node = Node ( key: key,
253
280
fingerprint: fingerprintedExternalDependency. fingerprint,
254
281
dependencySource: nil )
255
- return DirectlyInvalidatedNodeSet (
282
+ let untracedUses = DirectlyInvalidatedNodeSet (
256
283
nodeFinder
257
284
. uses ( of: node)
258
285
. filter ( { use in use. isUntraced } ) )
286
+ info. reporter? . reportInvalidated ( untracedUses, by: fingerprintedExternalDependency. externalDependency, why)
287
+ return untracedUses
259
288
}
260
289
261
290
/// Find all the inputs known to need recompilation as a consequence of reading a swiftdeps or swiftmodule
@@ -308,38 +337,32 @@ extension ModuleDependencyGraph {
308
337
isPresentInTheGraph: Bool ? )
309
338
-> DirectlyInvalidatedNodeSet {
310
339
340
+ /// Compute this up front as an optimization.
311
341
let isNewToTheGraph = isPresentInTheGraph != true && fingerprintedExternalDependencies. insert ( fed) . inserted
312
342
313
- // If the graph already includes prior externals, then any new externals are changes
314
- // Short-circuit conjunction may avoid the modTime query
315
- let shouldTryToProcess = info. isCrossModuleIncrementalBuildEnabled &&
316
- ( isNewToTheGraph || hasFileChanged ( of: fed. externalDependency) )
317
-
318
- // Do this no matter what in order to integrate any incremental external dependencies.
319
- let invalidatedNodesFromIncrementalExternal = shouldTryToProcess
320
- ? collectNodesInvalidatedByAttemptingToProcess ( fed, info)
321
- : nil
343
+ let whyIntegrateForClosure = ExternalDependency . Why (
344
+ should: fed,
345
+ whichIsNewToTheGraph: isNewToTheGraph,
346
+ closeOverSwiftModulesIn: self )
322
347
323
- if phase. isCompilingAllInputsNoMatterWhat {
324
- // going to compile every input anyway, less work for callers
325
- return DirectlyInvalidatedNodeSet ( )
348
+ let invalidatedNodesFromIncrementalExternal = whyIntegrateForClosure. flatMap { why in
349
+ collectNodesInvalidatedByAttemptingToProcess ( why, fed)
326
350
}
327
351
328
- /// When building a graph from scratch, an unchanged but new-to-the-graph external dependendcy should be ignored.
329
- /// Otherwise, it represents an added Import
330
- let callerWantsTheseChanges = ( phase. isUpdating && isNewToTheGraph) ||
331
- hasFileChanged ( of: fed. externalDependency)
332
-
333
- guard callerWantsTheseChanges else {
352
+ guard let whyInvalidate = ExternalDependency . Why (
353
+ shouldUsesOf: fed,
354
+ whichIsNewToTheGraph: isNewToTheGraph,
355
+ beInvalidatedIn: self )
356
+ else {
334
357
return DirectlyInvalidatedNodeSet ( )
335
358
}
336
359
337
360
// If there was an error integrating the external dependency, or if it was not an incremental one,
338
361
// return anything that uses that dependency.
339
- return invalidatedNodesFromIncrementalExternal ?? collectUntracedNodesUsing ( fed)
362
+ return invalidatedNodesFromIncrementalExternal ?? collectUntracedNodesUsing ( whyInvalidate , fed)
340
363
}
341
364
342
- private func hasFileChanged( of externalDependency: ExternalDependency
365
+ func hasFileChanged( of externalDependency: ExternalDependency
343
366
) -> Bool {
344
367
if let hasChanged = externalDependencyModTimeCache [ externalDependency] {
345
368
return hasChanged
@@ -356,14 +379,17 @@ extension ModuleDependencyGraph {
356
379
/// Try to read and integrate an external dependency.
357
380
/// Return nil if it's not incremental, or if an error occurs.
358
381
private func collectNodesInvalidatedByAttemptingToProcess(
359
- _ fed: FingerprintedExternalDependency ,
360
- _ info: IncrementalCompilationState . IncrementalDependencyAndInputSetup ) -> DirectlyInvalidatedNodeSet ? {
361
- fed. incrementalDependencySource?
362
- . read ( in: info. fileSystem, reporter: info. reporter)
363
- . map { unserializedDepGraph in
364
- info. reporter? . report ( " Integrating changes from: \( fed. externalDependency) " )
365
- return Integrator . integrate ( from: unserializedDepGraph, into: self )
366
- }
382
+ _ why: ExternalDependency . Why ,
383
+ _ fed: FingerprintedExternalDependency
384
+ ) -> DirectlyInvalidatedNodeSet ? {
385
+ guard let source = fed. incrementalDependencySource,
386
+ let unserializedDepGraph = source. read ( in: info. fileSystem, reporter: info. reporter)
387
+ else {
388
+ return nil
389
+ }
390
+ let invalidatedNodes = Integrator . integrate ( from: unserializedDepGraph, into: self )
391
+ info. reporter? . reportInvalidated ( invalidatedNodes, by: fed. externalDependency, why)
392
+ return invalidatedNodes
367
393
}
368
394
}
369
395
0 commit comments