Bryan
Bryan

Reputation: 5700

Swift Predicate: Fatal Error Keypaths With Multiple Components

Context

I'm attempting to create a Swift Predicate using the #Predicate macro as shown here:

final class Foo 
{
    var title: String = ""
    var name: String = ""
}


let p = #Predicate<Foo> { $0.title == "test" }

This compiles fine, but at runtime crashes with this:

Foundation/KeyPath+Inspection.swift:65: Fatal error: Predicate does not support keypaths with multiple components

Here's what the macro expands to, according to Xcode:

Foundation.Predicate<Foo>({
    PredicateExpressions.build_Equal(
        lhs: PredicateExpressions.build_KeyPath(
            root: PredicateExpressions.build_Arg($0),
            keyPath: \.title
        ),
        rhs: PredicateExpressions.build_Arg("test")
    )
})

Question

Why? I've seen some discussion threads where this error message pops up when an optional is involved in a KeyPath, but that's not the case here. And there's not multiple components.

(I'm looking to parse Predicate expressions to convert them into custom database query statements, but I can't even get a dead-simple predicate to actually exist without crashing.)

Details

Upvotes: 0

Views: 39

Answers (1)

Bryan
Bryan

Reputation: 5700

The Fix:

Removing final before the class declaration solves the issue.

// Works:
class Foo {
    var title: String = ""
}

// Crashes:
final class Foo {
    var title: String = ""
}

Elaboration:

I noticed that THIS worked just fine:

@Model
final class Foo {
    var title: String = ""
}
let p = #Predicate<Foo> { $0.title == "test" }  // No crash

All the @Model macro really does is rewrite the class into fancy computed properties, so I gave this a shot and found that it also works fine:

final class Foo {
    var title: String {
        return ""
    }
}
let p = #Predicate<Foo> { $0.title == "test" }  // No crash

But if you use the final keyword and attempt to create a KeyPath Predicate to a stored property of that class, it crashes.

Discussion:

That has to be a bug. The docs for Predicate make no mention of limitations for static dispatch. If this is somehow expected behavior, the nonsensical "multiple components in keyPath" error message is entirely misleading. Hopefully this can save someone else the hours I've wasted.

Upvotes: 0

Related Questions