From 64bb14a2cd8ab74fb709effffe4ed5b3b2ecaa36 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:07:46 -0800 Subject: [PATCH] Fix `redundantSendable` incorrectly removing `Sendable` from types inside `public extension` (#2423) Co-authored-by: calda <1811727+calda@users.noreply.github.com> --- Sources/Rules/RedundantSendable.swift | 10 ++++++- Tests/Rules/RedundantSendableTests.swift | 33 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Sources/Rules/RedundantSendable.swift b/Sources/Rules/RedundantSendable.swift index e356cbee..03b7abaf 100644 --- a/Sources/Rules/RedundantSendable.swift +++ b/Sources/Rules/RedundantSendable.swift @@ -21,8 +21,16 @@ public extension FormatRule { switch typeDeclaration.visibility() { case .public, .open: return - case .internal, .package, .fileprivate, .private, nil: + case .internal, .package, .fileprivate, .private: break + case nil: + // A type with no explicit access modifier inside a public extension is effectively public + let isInPublicExtension = typeDeclaration.parentDeclarations.last.map { + $0.keyword == "extension" && $0.visibility() == .public + } ?? false + if isInPublicExtension { + return + } } guard let sendableConformance = typeDeclaration.conformances.first(where: { diff --git a/Tests/Rules/RedundantSendableTests.swift b/Tests/Rules/RedundantSendableTests.swift index 60dca028..7d97bc5e 100644 --- a/Tests/Rules/RedundantSendableTests.swift +++ b/Tests/Rules/RedundantSendableTests.swift @@ -93,6 +93,39 @@ final class RedundantSendableTests: XCTestCase { testFormatting(for: input, [output], rules: [.redundantSendable]) } + func testDoesNotRemoveSendableFromTypeInsidePublicExtension() { + let input = """ + public struct OuterStruct {} + + public extension OuterStruct { + struct InnerStruct: Sendable {} + enum InnerEnum: Sendable {} + } + """ + + testFormatting(for: input, rules: [.redundantSendable]) + } + + func testRemovesSendableFromTypeInsideInternalExtension() { + let input = """ + struct OuterStruct {} + + extension OuterStruct { + struct InnerStruct: Sendable {} + } + """ + + let output = """ + struct OuterStruct {} + + extension OuterStruct { + struct InnerStruct {} + } + """ + + testFormatting(for: input, [output], rules: [.redundantSendable]) + } + func testRemovesSendableFromPackageValueTypes() { let input = """ package struct PackageStruct: Sendable {