-
-
Notifications
You must be signed in to change notification settings - Fork 602
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
beIdenticalTo
/ ===
: disallow comparing non-objects
#955
Conversation
Equality comparisons don't make sense for anything other than objects, and they will always fail. Using `===` with `struct`s for example is likely a programmer error, so to avoid it, a compile time error is better. This is potentially a breaking change.
@@ -41,7 +41,6 @@ final class BeIdenticalToTest: XCTestCase { | |||
let value = NSDate() | |||
expect(value).to(be(value)) | |||
expect(1 as NSNumber).toNot(be("turtles" as NSString)) | |||
expect([1]).toNot(be([1])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is illegal now. The NSArray
equivalent is in the next line.
Any thoughts on this @ikesyo? I was just bitten by it again comparing 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Completely makes sense 👍
These were no longer valid since Quick/Nimble#955
The `Package.resolved` file is not backwards compatible. We only have test SPM dependencies, so by `.gitignore`ing it we can support both Xcode versions. Also fixed invalid Nimble usages of `===` that were no longer valid since Quick/Nimble#955.
Hi 👋 After this change I am experiencing that below code that previously worked fine, now it does not compile: protocol MyProtocol { }
final class MyClass: MyProtocol {
init() { }
}
final class Spec: QuickSpec {
override func spec() {
it("success") {
let object1 = MyClass()
let object2: MyProtocol = object1
expect(object2).to(be(object1))
}
it("fails") {
let object1 = MyClass()
let object2: MyProtocol = MyClass()
expect(object2).to(be(object1))
}
}
} I understand that there are multiple ways to make these tests compile:
But I am not sure any of above solutions are correct:
I would consider above code snippet correct: it should build and run as expected without further modifications. Wdyt? I believe the issue in this case boils down to this: the compiler is not able to tell at compile time that a type (in this case a protocol) is a class |
That's exactly right. And without that, |
The change in this PR is based on an assumption that is false, no? The change modified the code so instead of making a run-time check, it performs a compile-time check, based on the assumption that all valid comparisons can be checked at compile-time
But we are saying that for some valid cases (the one above) the compiler does not know at compile time if a type is a class or not, so the current code does not allow valid comparisons that previously (with the run-time check) were allowed |
@NachoSoto could you please reconsider this. I am considering opening a PR reverting the change here, but would like to hear if you have any alternative for the stated problem before doing so |
If you prefer to do this at runtime you could always add an overload for |
I do not prefer it, but protocol comparisons I believe cannot happen at compile time, as I shown above
@NachoSoto I cannot imagine how. Can you elaborate? |
extension Expectation where T == Any {
public static func === (lhs: Expectation, rhs: Any?) {
lhs.to(beIdenticalTo(rhs as? AnyObject))
}
} |
Thanks for that. But above code does not build, throws the error |
Equality comparisons don't make sense for anything other than objects, and they will always fail.
Using
===
withstruct
s for example is likely a programmer error, so to avoid it, a compile-time error is better.This is potentially a breaking change.