Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Sources/FoundationEssentials/Predicate/Expressions/Optional.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,22 @@ extension PredicateExpressions {
self.transform = builder(variable)
}

public func evaluate(_ bindings: PredicateBindings) throws -> Output {
// When the transform produces a non-optional Result, wrap it.
public func evaluate(_ bindings: PredicateBindings) throws -> Output where RHS.Output == Result {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate more on the intent of this change? The existing public func evaluate is a witness to a protocol requirement from PredicateExpression. PredicateExpression requires that all expressions must be able to be evaluated without additional constraints, so the two new public APIs that you've added no longer satisfy this protocol requirement and I don't expect that it would build successfully. IIRC the split initializers (not protocol requirements) were necessary to "simulate" the compiler's implicit optional promotion when returning a non-optional value from a function with an optional return type which does not apply to generic signature requirements in the same way. The existing force cast in the evaluate function performs that optional promotion at runtime like the compiler would have inserted if this were a "real" closure.

var mutableBindings = bindings
return try wrapped.evaluate(bindings).flatMap { inner in
mutableBindings[variable] = inner
let value = try transform.evaluate(mutableBindings)
return Optional(value)
}
}

// When the transform already produces an optional Result, propagate it.
public func evaluate(_ bindings: PredicateBindings) throws -> Output where RHS.Output == Optional<Result> {
var mutableBindings = bindings
return try wrapped.evaluate(bindings).flatMap { inner in
mutableBindings[variable] = inner
return try transform.evaluate(mutableBindings) as! Result?
return try transform.evaluate(mutableBindings)
}
}
}
Expand Down