Skip to content

Commit 005e764

Browse files
author
David Ungar
committed
step1-use type for direct
1 parent 5dabb21 commit 005e764

File tree

7 files changed

+99
-57
lines changed

7 files changed

+99
-57
lines changed

Sources/SwiftDriver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_library(SwiftDriver
4444
"IncrementalCompilation/DependencyGraphDotFileWriter.swift"
4545
"IncrementalCompilation/DependencyKey.swift"
4646
"IncrementalCompilation/DictionaryOfDictionaries.swift"
47+
"IncrementalCompilation/DirectAndTransitiveCollections.swift"
4748
"IncrementalCompilation/ExternalDependencyAndFingerprintEnforcer.swift"
4849
"IncrementalCompilation/IncrementalCompilationState.swift"
4950
"IncrementalCompilation/InitialStateComputer.swift"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===------------------ DirectAndTransitiveCollections.swift --------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// Use the type system to ensure that dependencies are transitively closed
14+
// without doing too much work at the leaves of the call tree
15+
16+
public struct DirectlyInvalidatedNodes {
17+
typealias Node = ModuleDependencyGraph.Node
18+
var contents = Set<Node>()
19+
20+
init(_ s: Set<Node> = Set()) {
21+
self.contents = s
22+
}
23+
24+
init<Nodes: Sequence>(_ nodes: Nodes)
25+
where Nodes.Element == Node
26+
{
27+
self.init(Set(nodes))
28+
}
29+
30+
mutating func insert(_ e: Node) {
31+
contents.insert(e)
32+
}
33+
mutating func formUnion(_ nodes: DirectlyInvalidatedNodes) {
34+
contents.formUnion(nodes.contents)
35+
}
36+
}
37+
38+
//extension Sequence {
39+
// func reduce(into initialResult: DirectlyInvalidatedNodes,
40+
// _ updateAccumulatingResult: (inout: DirectlyInvalidatedNodes, Element) -> Void) {
41+
// var r = initialResult
42+
// reduce(into: r.contents, updateAccumulatingResult)
43+
// return r
44+
// }
45+
// }
46+
//}

Sources/SwiftDriver/IncrementalCompilation/InitialStateComputer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ extension IncrementalCompilationState.InitialStateComputer {
152152

153153
// Any externals not already in graph must be additions which should trigger
154154
// recompilation. Thus, `ChangedOrAdded`.
155-
let nodesDirectlyInvalidatedByExternals = graph.collectNodesDirectlyInvalidatedByChangedOrAddedExternals()
155+
let nodesDirectlyInvalidatedByExternals = graph.collectNodesInvalidatedByChangedOrAddedExternals()
156156
// Wait till the last minute to do the transitive closure as an optimization.
157157
let inputsTransitivelyInvalidatedByExternals = graph.collectInputsUsingTransitivelyInvalidated(
158158
nodes: nodesDirectlyInvalidatedByExternals)

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraph.swift

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,11 @@ extension ModuleDependencyGraph {
106106

107107
// MARK: - Getting a graph read from priors ready to use
108108
extension ModuleDependencyGraph {
109-
func collectNodesDirectlyInvalidatedByChangedOrAddedExternals() -> Set<Node> {
110-
fingerprintedExternalDependencies.reduce(into: Set()) { invalidatedNodes, fed in
109+
func collectNodesInvalidatedByChangedOrAddedExternals() -> DirectlyInvalidatedNodes {
110+
fingerprintedExternalDependencies.reduce(into: DirectlyInvalidatedNodes()) {
111+
invalidatedNodes, fed in
111112
invalidatedNodes.formUnion (
112-
self.collectNodesDirectlyInvalidatedByProcessing(fingerprintedExternalDependency: fed))
113+
self.collectNodesInvalidatedByProcessing(fingerprintedExternalDependency: fed))
113114
}
114115
}
115116
}
@@ -140,7 +141,7 @@ extension ModuleDependencyGraph {
140141
) -> Set<DependencySource> {
141142
let nodes = nodeFinder.findNodes(for: dependencySource) ?? [:]
142143
/// Tests expect this to be reflexive
143-
return collectSwiftDepsUsingTransitivelyInvalidated(nodes: nodes.values)
144+
return collectSwiftDepsUsingTransitivelyInvalidated(nodes: DirectlyInvalidatedNodes(nodes.values))
144145
}
145146

146147
/// Does the graph contain any dependency nodes for a given source-code file?
@@ -188,10 +189,9 @@ extension ModuleDependencyGraph {
188189
/// Given a set of invalidated nodes, find all swiftDeps dependency sources containing defs that transitively use
189190
/// any of the invalidated nodes.
190191
/*@_spi(Testing)*/
191-
public func collectSwiftDepsUsingTransitivelyInvalidated<Nodes: Sequence>(
192-
nodes: Nodes
192+
public func collectSwiftDepsUsingTransitivelyInvalidated(
193+
nodes: DirectlyInvalidatedNodes
193194
) -> Set<DependencySource>
194-
where Nodes.Element == Node
195195
{
196196
// Is this correct for the 1st wave after having read a prior?
197197
// Yes, because
@@ -214,9 +214,9 @@ extension ModuleDependencyGraph {
214214
/// Given an external dependency & its fingerprint, find any nodes directly using that dependency.
215215
/// As an optimization, only return the nodes that have not been already traced, because the traced nodes
216216
/// will have already been used to schedule jobs to run.
217-
/*@_spi(Testing)*/ public func collectUntracedNodesDirectlyUsing(
217+
/*@_spi(Testing)*/ public func collectUntracedNodesUsing(
218218
_ fingerprintedExternalDependency: FingerprintedExternalDependency
219-
) -> Set<Node> {
219+
) -> DirectlyInvalidatedNodes {
220220
// These nodes will depend on the *interface* of the external Decl.
221221
let key = DependencyKey(
222222
aspect: .interface,
@@ -227,9 +227,10 @@ extension ModuleDependencyGraph {
227227
let node = Node(key: key,
228228
fingerprint: fingerprintedExternalDependency.fingerprint,
229229
dependencySource: nil)
230-
return nodeFinder
231-
.uses(of: node)
232-
.filter({ use in use.isUntraced })
230+
return DirectlyInvalidatedNodes(
231+
nodeFinder
232+
.uses(of: node)
233+
.filter({ use in use.isUntraced }))
233234
}
234235

235236
/// Find all the inputs known to need recompilation as a consequence of reading a swiftdeps or swiftmodule
@@ -252,16 +253,16 @@ extension ModuleDependencyGraph {
252253
/// If reading for the first time, the driver is compiling all outdated source files anyway, so only
253254
/// nodes invalidated by external dependencies matter.
254255
/// But when updating, all invalidations matter.
255-
let directlyInvalidatedNodes = phase.isUpdating
256-
? results.allDirectlyInvalidatedNodes
257-
: results.nodesDirectlyInvalidatedByUsingSomeExternal
256+
let invalidatedNodes = phase.isUpdating
257+
? results.all
258+
: results.usesOfSomeExternal
258259

259-
return collectInputsUsingTransitivelyInvalidated(nodes: directlyInvalidatedNodes)
260+
return collectInputsUsingTransitivelyInvalidated(nodes: invalidatedNodes)
260261
}
261262

262263
/// Given nodes that are invalidated, find all the affected inputs that must be recompiled.
263264
func collectInputsUsingTransitivelyInvalidated(
264-
nodes directlyInvalidatedNodes: Set<Node>
265+
nodes directlyInvalidatedNodes: DirectlyInvalidatedNodes
265266
) -> Set<TypedVirtualPath> {
266267
collectSwiftDepsUsingTransitivelyInvalidated(nodes: directlyInvalidatedNodes)
267268
.reduce(into: Set()) { invalidatedInputs, invalidatedSwiftDeps in
@@ -277,9 +278,9 @@ extension ModuleDependencyGraph {
277278
/// Return the nodes thus invalidated.
278279
/// But always integrate, in order to detect future changes.
279280
/// This function does not to the transitive closure; that is left to the callers
280-
func collectNodesDirectlyInvalidatedByProcessing(
281+
func collectNodesInvalidatedByProcessing(
281282
fingerprintedExternalDependency fed: FingerprintedExternalDependency)
282-
-> Set<Node> {
283+
-> DirectlyInvalidatedNodes {
283284

284285
let isNewToTheGraph = fingerprintedExternalDependencies.insert(fed).inserted
285286

@@ -293,13 +294,13 @@ extension ModuleDependencyGraph {
293294
(isNewToTheGraph || lazyModTimer.hasExternalFileChanged)
294295

295296
// Do this no matter what in order to integrate any incremental external dependencies.
296-
let directlyInvalidatedNodesFromIncrementalExternal = shouldTryToProcess
297-
? collectNodesDirectlyInvalidatedByAttemptingToProcess(fed, info)
297+
let invalidatedNodesFromIncrementalExternal = shouldTryToProcess
298+
? collectNodesInvalidatedByAttemptingToProcess(fed, info)
298299
: nil
299300

300301
if phase == .buildingAfterEachCompilation {
301302
// going to compile every input anyway, less work for callers
302-
return Set()
303+
return DirectlyInvalidatedNodes()
303304
}
304305

305306
/// When building a graph from scratch, an unchanged but new-to-the-graph external dependendcy should be ignored.
@@ -308,12 +309,12 @@ extension ModuleDependencyGraph {
308309
lazyModTimer.hasExternalFileChanged
309310

310311
guard callerWantsTheseChanges else {
311-
return Set()
312+
return DirectlyInvalidatedNodes()
312313
}
313314

314315
// If there was an error integrating the external dependency, or if it was not an incremental one,
315316
// return anything that uses that dependency.
316-
return directlyInvalidatedNodesFromIncrementalExternal ?? collectUntracedNodesDirectlyUsing(fed)
317+
return invalidatedNodesFromIncrementalExternal ?? collectUntracedNodesUsing(fed)
317318
}
318319

319320
private struct LazyModTimer {
@@ -326,15 +327,15 @@ extension ModuleDependencyGraph {
326327

327328
/// Try to read and integrate an external dependency.
328329
/// Return nil if it's not incremental, or if an error occurs.
329-
private func collectNodesDirectlyInvalidatedByAttemptingToProcess(
330+
private func collectNodesInvalidatedByAttemptingToProcess(
330331
_ fed: FingerprintedExternalDependency,
331-
_ info: IncrementalCompilationState.InitialStateComputer) -> Set<Node>? {
332+
_ info: IncrementalCompilationState.InitialStateComputer) -> DirectlyInvalidatedNodes? {
332333
fed.incrementalDependencySource?
333334
.read(in: info.fileSystem, reporter: info.reporter)
334335
.map { unserializedDepGraph in
335336
info.reporter?.report("Integrating changes from: \(fed.externalDependency)")
336337
return Integrator.integrate(from: unserializedDepGraph, into: self)
337-
.allDirectlyInvalidatedNodes
338+
.all
338339
}
339340
}
340341

@@ -364,10 +365,8 @@ extension OutputFileMap {
364365
// MARK: - tracking traced nodes
365366
extension ModuleDependencyGraph {
366367

367-
func ensureGraphWillRetrace<Nodes: Sequence>(_ nodes: Nodes)
368-
where Nodes.Element == Node
369-
{
370-
for node in nodes {
368+
func ensureGraphWillRetrace(_ nodes: DirectlyInvalidatedNodes) {
369+
for node in nodes.contents {
371370
node.setUntraced()
372371
}
373372
}

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Integrator.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ extension ModuleDependencyGraph.Integrator {
7676
integrateEachSourceNode()
7777
handleDisappearedNodes()
7878
// Ensure transitive closure will get started.
79-
destination.ensureGraphWillRetrace(results.allDirectlyInvalidatedNodes)
79+
destination.ensureGraphWillRetrace(results.all)
8080
}
8181
private mutating func integrateEachSourceNode() {
8282
sourceGraph.forEachNode { integrate(oneNode: $0) }
@@ -197,9 +197,9 @@ extension ModuleDependencyGraph.Integrator {
197197
externalDependency fingerprintedExternalDependency: FingerprintedExternalDependency,
198198
moduleFileGraphUseNode moduleUseNode: Graph.Node) {
199199

200-
let invalidated = destination.collectNodesDirectlyInvalidatedByProcessing(
200+
let invalidated = destination.collectNodesInvalidatedByProcessing(
201201
fingerprintedExternalDependency: fingerprintedExternalDependency)
202-
results.addNodesDirectlyInvalidatedByUsingSomeExternal(invalidated)
202+
results.addUsesOfSomeExternal(invalidated)
203203
}
204204
}
205205

@@ -209,25 +209,25 @@ extension ModuleDependencyGraph.Integrator {
209209
public struct Results {
210210
typealias Node = ModuleDependencyGraph.Node
211211

212-
private(set) var allDirectlyInvalidatedNodes = Set<Node>()
213-
private(set) var nodesDirectlyInvalidatedByUsingSomeExternal = Set<Node>()
212+
private(set) var all = DirectlyInvalidatedNodes()
213+
private(set) var usesOfSomeExternal = DirectlyInvalidatedNodes()
214214

215-
mutating func addNodesDirectlyInvalidatedByUsingSomeExternal(_ invalidated: Set<Node>)
215+
mutating func addUsesOfSomeExternal(_ invalidated: DirectlyInvalidatedNodes)
216216
{
217-
allDirectlyInvalidatedNodes.formUnion(invalidated)
218-
allDirectlyInvalidatedNodes.formUnion(invalidated)
217+
all.formUnion(invalidated)
218+
usesOfSomeExternal.formUnion(invalidated)
219219
}
220220
mutating func addDisappeared(_ node: Node) {
221-
allDirectlyInvalidatedNodes.insert(node)
221+
all.insert(node)
222222
}
223223
mutating func addChanged(_ node: Node) {
224-
allDirectlyInvalidatedNodes.insert(node)
224+
all.insert(node)
225225
}
226226
mutating func addPatriated(_ node: Node) {
227-
allDirectlyInvalidatedNodes.insert(node)
227+
all.insert(node)
228228
}
229229
mutating func addNew(_ node: Node) {
230-
allDirectlyInvalidatedNodes.insert(node)
230+
all.insert(node)
231231
}
232232
}
233233
}

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Tracer.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,24 @@ extension ModuleDependencyGraph.Tracer {
3737

3838
/// Find all uses of `defs` that have not already been traced.
3939
/// (If already traced, jobs have already been scheduled.)
40-
static func collectPreviouslyUntracedNodesUsing<Nodes: Sequence> (
41-
defNodes: Nodes,
40+
static func collectPreviouslyUntracedNodesUsing(
41+
defNodes: DirectlyInvalidatedNodes,
4242
in graph: ModuleDependencyGraph,
4343
diagnosticEngine: DiagnosticsEngine
44-
) -> Self
45-
where Nodes.Element == ModuleDependencyGraph.Node
46-
{
44+
) -> Self {
4745
var tracer = Self(collectingUsesOf: defNodes,
4846
in: graph,
4947
diagnosticEngine: diagnosticEngine)
5048
tracer.collectPreviouslyUntracedDependents()
5149
return tracer
5250
}
5351

54-
private init<Nodes: Sequence>(collectingUsesOf defs: Nodes,
52+
private init(collectingUsesOf defs: DirectlyInvalidatedNodes,
5553
in graph: ModuleDependencyGraph,
56-
diagnosticEngine: DiagnosticsEngine)
57-
where Nodes.Element == ModuleDependencyGraph.Node
58-
{
54+
diagnosticEngine: DiagnosticsEngine) {
5955
self.graph = graph
6056
// Sort so "Tracing" diagnostics are deterministically ordered
61-
self.startingPoints = defs.sorted()
57+
self.startingPoints = defs.contents.sorted()
6258
self.currentPathIfTracing = graph.info.reporter != nil ? [] : nil
6359
self.diagnosticEngine = diagnosticEngine
6460
}

Tests/SwiftDriverTests/ModuleDependencyGraphTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ extension ModuleDependencyGraph {
984984
_ interfaceHashIfPresent: String? = nil,
985985
includePrivateDeps: Bool = true,
986986
hadCompilationError: Bool = false
987-
) -> Set<Node> {
987+
) -> DirectlyInvalidatedNodes {
988988
let dependencySource = DependencySource(mock: swiftDepsIndex)
989989
// Only needed for serialization testing:
990990
mockMapEntry(TypedVirtualPath.init(mockInput: swiftDepsIndex),
@@ -1001,7 +1001,7 @@ extension ModuleDependencyGraph {
10011001

10021002
let results = Integrator.integrate(from: sfdg, into: self)
10031003

1004-
return results.allDirectlyInvalidatedNodes
1004+
return results.all
10051005
}
10061006

10071007
func findUntracedSwiftDepsDependent(onExternal s: String) -> [Int] {
@@ -1015,7 +1015,7 @@ extension ModuleDependencyGraph {
10151015
on fingerprintedExternalDependency: FingerprintedExternalDependency
10161016
) -> [DependencySource] {
10171017
var foundSources = [DependencySource]()
1018-
for dependent in self.collectUntracedNodesDirectlyUsing(fingerprintedExternalDependency) {
1018+
for dependent in collectUntracedNodesUsing(fingerprintedExternalDependency).contents {
10191019
let dependencySource = dependent.dependencySource!
10201020
foundSources.append(dependencySource)
10211021
// findSwiftDepsToRecompileWhenWholeSwiftDepChanges is reflexive

0 commit comments

Comments
 (0)