最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Swift #Predicate Macro Crashes for Multiple KeyPath Components - Stack Overflow

programmeradmin0浏览0评论

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")
    )
})

Why does this crash? It's not a KeyPath with multiple components.

Update

Here's the relevant code in Foundation. It uses offset(of:) to determine whether a KeyPath to a stored property has multiple components, which is not a reliable check.

Apple is working on a fix:

Details

  • Swift Language Version: 6
  • Xcode Version: 16.2
  • Deployment Target: macOS 15.2

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")
    )
})

Why does this crash? It's not a KeyPath with multiple components.

Update

Here's the relevant code in Foundation. It uses offset(of:) to determine whether a KeyPath to a stored property has multiple components, which is not a reliable check.

Apple is working on a fix: https://github/swiftlang/swift-foundation/issues/1173

Details

  • Swift Language Version: 6
  • Xcode Version: 16.2
  • Deployment Target: macOS 15.2
Share Improve this question edited Feb 15 at 0:46 Bryan asked Jan 3 at 23:33 BryanBryan 5,7794 gold badges46 silver badges79 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

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.

发布评论

评论列表(0)

  1. 暂无评论