diff --git a/Sources/AnyExpression.swift b/Sources/AnyExpression.swift index c88e892..13951b9 100644 --- a/Sources/AnyExpression.swift +++ b/Sources/AnyExpression.swift @@ -747,13 +747,21 @@ extension AnyExpression { // Test if a value is nil static func isNil(_ value: Any) -> Bool { - if let optional = value as? _Optional { + switch value { + case let optional as _Optional: guard let value = optional.value else { return true } return isNil(value) + case is NSNull: + return true + case let string as _String?: + // Avoid treating "nil" as nil + return string == nil + default: + // Workaround for _Optional not working in Xcode 16 + return String(describing: value) == "nil" } - return value is NSNull } // Test if a value supports subscripting diff --git a/Tests/AnyExpressionTests.swift b/Tests/AnyExpressionTests.swift index 5fc1202..8c6750e 100644 --- a/Tests/AnyExpressionTests.swift +++ b/Tests/AnyExpressionTests.swift @@ -1871,6 +1871,21 @@ class AnyExpressionTests: XCTestCase { XCTAssertNil(try expression.evaluate() as String?) } + func testStringNilNotTreatedAsNil() { + let expression = AnyExpression("'nil'") + XCTAssertNotNil(try expression.evaluate() as String?) + } + + func testNSStringNilNotTreatedAsNil() { + let expression = AnyExpression("foo", constants: ["foo": "nil" as NSString]) + XCTAssertNotNil(try expression.evaluate() as String?) + } + + func testSubstringNilNotTreatedAsNil() { + let expression = AnyExpression("foo", constants: ["foo": Substring("nil")]) + XCTAssertNotNil(try expression.evaluate() as String?) + } + // MARK: Errors func testUnknownOperator() {