(114208158) Ensure predicate dictionary subscript default value evaluation is lazy

This commit is contained in:
Jeremy Schonfeld 2023-08-21 13:18:26 -06:00 committed by GitHub
parent 688e32acb5
commit 7ccc700059
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 2 deletions

View File

@ -84,8 +84,10 @@ extension PredicateExpressions {
}
public func evaluate(_ bindings: PredicateBindings) throws -> Output {
let defaultValue = try `default`.evaluate(bindings)
return try wrapped.evaluate(bindings)[try key.evaluate(bindings), default: defaultValue]
guard let value = try wrapped.evaluate(bindings)[try key.evaluate(bindings)] else {
return try `default`.evaluate(bindings)
}
return value
}
}

View File

@ -596,6 +596,34 @@ final class PredicateTests: XCTestCase {
XCTAssertThrowsError(try predicate.evaluate(Object(a: 3, b: "", c: 0.0, d: 0, e: "c", f: true, g: [])))
}
func testLazyDefaultValueSubscript() throws {
struct Foo : Codable, Sendable {
static var num = 1
var property: Int {
defer { Foo.num += 1 }
return Foo.num
}
}
var foo = Foo()
let predicate = Predicate<[String : Int]> {
PredicateExpressions.build_Equal(
lhs: PredicateExpressions.build_subscript(
PredicateExpressions.build_Arg($0),
PredicateExpressions.build_Arg("key"),
default: PredicateExpressions.build_KeyPath(
root: PredicateExpressions.build_Arg(foo),
keyPath: \.property
)
),
rhs: PredicateExpressions.build_Arg(1)
)
}
XCTAssertFalse(try predicate.evaluate(["key" : 2]))
XCTAssertEqual(Foo.num, 1)
}
func testStaticValues() throws {
func assertPredicate<T>(_ pred: Predicate<T>, value: T, expected: Bool) throws {
XCTAssertEqual(try pred.evaluate(value), expected)