pointfreeco / swift-case-paths

🧰 Case paths extends the key path hierarchy to enum cases.
https://www.pointfree.co/collections/enums-and-structs/case-paths
MIT License
921 stars 108 forks source link

Sendable Case Paths? #89

Closed huwr closed 2 years ago

huwr commented 2 years ago

I've been getting some warnings when I capture a 'non-sendable' case path in a @Sendable closure.

It there any reason CasePath can't be marked Sendable where the Root is already Sendable? I think this will be okay, but would like to make sure

🤔

stephencelis commented 2 years ago

@huwr Good question. It's a bit tricky, since KeyPath sendability has nothing to do with the Root/Value types. Because of this I think we'll just make CasePath: @unchecked Sendable, but will chat about that with @mbrandonw soon!

huwr commented 2 years ago

Thanks @stephencelis ! I'll just add a cheeky extension CasePath: @unchecked Sendable { } to my code for now.

stephencelis commented 2 years ago

@huwr If you can share some examples, that'd also be helpful! It could just be that we don't have enough concurrency warnings enabled throughout our projects, but we haven't hit this issue yet.

huwr commented 2 years ago

Sure. This is a real stupid example, but it's sort of what I've been trying to do.

I've got a value of an enum, and I'm trying to see if it matches a case path in side a sendable closure (represented by the Task's operation).

enum Animal: Sendable {
    case horse
    case bear
    case rabbit
}

@MainActor
final class FunViewModel: ObservableObject {

    @Published var animalMatches: Bool = false

    func matching<Case>(animal: Animal, with casePath: CasePath<Animal, Case>) {
        Task {
            // ⚠️ Capture of 'casePath' with non-sendable type 'CasePath<Animal, Case>' in a `@Sendable` closure
            animalMatches = casePath ~= animal
        }
    }

}

EDIT: This only occurs for me because we have -Xfrontend -warn-concurrency turned on. Without that, there's no warning.