Skip to content

Commit

Permalink
Workaround Swift 6 bug for missing related references to external ove…
Browse files Browse the repository at this point in the history
…rriden declarations. Closes #820
  • Loading branch information
ileitch committed Sep 22, 2024
1 parent e9d0dee commit 8b1af46
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

- Enums with the `@main` attribute are now retained.
- Unused public/exported imports are excluded from the results even if unused in the declaring file as the exported symbols may be referenced in other files, and thus removing the import would result in a build failure.
- Fixed issue in Swift 6 where declarations that override external type members are incorrectly identified as unused.

## 2.21.0 (2024-06-15)

Expand Down
4 changes: 4 additions & 0 deletions Sources/SourceGraph/Elements/Declaration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ public final class Declaration {
functionKinds.union(variableKinds).union(globalKinds)
}

static var overrideKinds: Set<Kind> {
[.functionMethodInstance, .varInstance]
}

public var isAccessorKind: Bool {
rawValue.hasPrefix("function.accessor")
}
Expand Down
46 changes: 46 additions & 0 deletions Sources/SourceGraph/Mutators/ExternalOverrideRetainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Configuration
import Foundation
import Shared

/// Retains instance functions/vars that override external declarations.
///
/// It's not possible to determine if a declaration that overrides an external declaration is used, as the
/// external implementation may call the overridden declaration.
final class ExternalOverrideRetainer: SourceGraphMutator {
private let graph: SourceGraph
private let isSwift6FixEnabled: Bool

required init(graph: SourceGraph, configuration _: Configuration, swiftVersion: SwiftVersion) {
self.graph = graph
isSwift6FixEnabled = swiftVersion.version.isVersion(greaterThanOrEqualTo: "6.0")
}

func mutate() {
for decl in graph.declarations(ofKinds: Declaration.Kind.overrideKinds) {
guard decl.isOverride else { continue }

var didIdentifyRelatedRef = false

for relatedRef in decl.related {
if relatedRef.kind == decl.kind,
relatedRef.name == decl.name,
relatedRef.location == decl.location
{
didIdentifyRelatedRef = true

if graph.explicitDeclaration(withUsr: relatedRef.usr) == nil {
// The related decl is external.
graph.markRetained(decl)
}

break
}
}

// https://github.com/swiftlang/swift/issues/76628
if !didIdentifyRelatedRef, isSwift6FixEnabled {
graph.markRetained(decl)
}
}
}
}
1 change: 1 addition & 0 deletions Sources/SourceGraph/SourceGraphMutatorRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public final class SourceGraphMutatorRunner {
ResultBuilderRetainer.self,
CapitalSelfFunctionCallRetainer.self,
CodablePropertyRetainer.self,
ExternalOverrideRetainer.self,

AncestralReferenceEliminator.self,
AssignOnlyPropertyReferenceEliminator.self,
Expand Down

0 comments on commit 8b1af46

Please sign in to comment.