For an Equatable type, we need a hash implementation that
is compatible with any possible definition of `==`.
Conservatively, that means `-hash` must return a constant.
For non-Equatable types, we know that `==` is identity based,
so we can get better hash behavior by using the object address.
Caveat: This means that non-Equatable types will do two
protocol conformance checks on every call to `hash`.
If a Swift type implements Equatable and/or Hashable and
we then pass that object into ObjC, we want ObjC
`isEqual:` and `hashValue` to use that. This allows
ObjC code to build ObjC collections of Swift objects.
* Support for Hashable struct/enum types was implemented in #4124
* Support for Equatable struct/enum types was implemented in #68720
* This implements support for Hashable and Equatable _class_ types
Caveats:
1. This does a lot of dynamic lookup work for each operation, so is
inherently rather slow. Unlike the struct/enum case, there is no convenient
place to cache the conformance information, so it's not clear that there is a
viable way to make it significantly faster.
2. This is a behavioral change to low-level support code. There is a
risk of breaking code that may be relying on the old behavior.
remote-run doesn't always preserve the interleaving, but we don't need
stdout at all given what's being checked; it's just used to show how
far the test got before failing. The output being FileChecked is going
through NSLog, which uses stderr.
Part of rdar://problem/44866579
Something has changed with newer versions of LLVM so that the
stdlib/SwiftObjectNSObject.swift test fails on the master-next branch
because the @objc thunk functions all get merged together. That is a good
thing for code size but it breaks some of the checks in this test that
compare the function pointers to verify that overrides are correct.
Make each function different so they cannot be merged.