From 629314d04bfd61c39c7f54baed97bdbac4123939 Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Tue, 16 Jul 2024 13:42:08 -0700 Subject: [PATCH] Avoid warning when embedding `Never` cases (#179) Sendability meant losing the `Enum.case` shorthand for `{ Enum.case($0) }`, which meant introducing a warning when `type(of: $0) == Never.self`. Looks like we can suppress this warning, though, and it also luckily looks like this _only_ affects embedding `Never` directly (embedding enums that only contain `Never` does not trigger a warning). --- Package.resolved | 2 +- .../CasePathsMacros/CasePathableMacro.swift | 5 +- .../CasePathableMacroTests.swift | 46 +++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index bf31e06..007eb44 100644 --- a/Package.resolved +++ b/Package.resolved @@ -39,7 +39,7 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax", + "location" : "https://github.com/swiftlang/swift-syntax", "state" : { "revision" : "303e5c5c36d6a558407d364878df131c3546fad8", "version" : "510.0.2" diff --git a/Sources/CasePathsMacros/CasePathableMacro.swift b/Sources/CasePathsMacros/CasePathableMacro.swift index 9f6ce1c..1b88552 100644 --- a/Sources/CasePathsMacros/CasePathableMacro.swift +++ b/Sources/CasePathsMacros/CasePathableMacro.swift @@ -204,11 +204,14 @@ extension CasePathableMacro: MemberMacro { .map { String($0.dropFirst(indent)) } .joined(separator: "\n") .trimmingSuffix(while: { $0.isWhitespace && !$0.isNewline }) + let embed: DeclSyntax = ["Never", "Swift.Never"].contains(associatedValueName) + ? " _ -> \(enumName) in " + : "\(enumName).\(caseName)\(raw: embedNames)" return """ \(raw: leadingTrivia)public var \(caseName): \ \(raw: casePathTypeName.qualified)<\(enumName), \(raw: associatedValueName)> { \(raw: casePathTypeName.qualified)<\(enumName), \(raw: associatedValueName)>( - embed: { \(enumName).\(caseName)\(raw: embedNames) }, + embed: { \(embed) }, extract: { guard case\(raw: hasPayload ? " let" : "").\(caseName)\(raw: bindingNames) = $0 else { \ return nil \ diff --git a/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift b/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift index 46a893f..3d13ce4 100644 --- a/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift +++ b/Tests/CasePathsMacrosTests/CasePathableMacroTests.swift @@ -144,6 +144,52 @@ final class CasePathableMacroTests: XCTestCase { } } + func testCasePathable_NeverCase() { + assertMacro { + """ + @CasePathable enum Foo { + case bar(Never) + } + """ + } expansion: { + #""" + enum Foo { + case bar(Never) + + public struct AllCasePaths: CasePaths.CasePathReflectable, Sendable, Sequence { + public subscript(root: Foo) -> CasePaths.PartialCaseKeyPath { + if root.is(\.bar) { + return \.bar + } + return \.never + } + public var bar: CasePaths.AnyCasePath { + CasePaths.AnyCasePath( + embed: { _ -> Foo in + }, + extract: { + guard case let .bar(v0) = $0 else { + return nil + } + return v0 + } + ) + } + public func makeIterator() -> IndexingIterator<[CasePaths.PartialCaseKeyPath]> { + var allCasePaths: [CasePaths.PartialCaseKeyPath] = [] + allCasePaths.append(\.bar) + return allCasePaths.makeIterator() + } + } + public static var allCasePaths: AllCasePaths { AllCasePaths() } + } + + extension Foo: CasePaths.CasePathable, CasePaths.CasePathIterable { + } + """# + } + } + func testCasePathable_ElementList() { assertMacro { """