Swift value types are their bridged Objective-C classes can have
different hash values. To address this, AnyHashable's responds to the
_HasCustomAnyHashableRepresentation protocol, which bridge objects of
those class types---NSString, NSNumber, etc---into their Swift
counterparts. That way, we get consistent (Swift) hashing behavior
across platforms.
However, there are cases where multiple Swift value types map to the
same Objective-C class type. In such cases, AnyHashable ends up
converting the object of class type back to some canonical type. For
example, an NS_STRING_ENUM (such as (NS)RunLoopMode) is a Swift
wrapper around a String. If an (NS)RunLoopMode is placed into an
AnyHashable, it maintains it's Swift type identity (which is correct
behavior). If it is bridged to Objective-C, it becomes an NSString; if
that NSString is placed into an AnyHashable, it produces a String. The
hash values still line up, but equality of the AnyHashable values
fails, which breaks when (for example) a dictionary with AnyHashable
keys is used from Objective-C. See SR-2648 / rdar://problem/27992351
for a case where this breaks interoperability.
To address this problem, make AnyHashable's casting and equality
sensitive to the origin of the hashed value: if the AnyHashable was
created through a _HasCustomAnyHashableRepresentation conformance,
treat comparisons/casting from it as "fuzzy":
* For equality, if one of the AnyHashable's comes from a custom
representation (e.g., it originated with an Objective-C type like
NSString) but the other did not, bridge the value of the *other*
AnyHashable to Objective-C, re-wrap it in an AnyHashable, and
compare that. This allows, e.g., an (NS)RunLoopMode created in Swift
to compare to an NSString constant with the same string value.
* For casting, if the AnyHashable we're casting from came from a
custom representation and the cast would fail, bridge to Objective-C
and then initiate the cast again. This allows an NSString to be
casted to (NS)RunLoopMode.
Fixes SR-2648 / rdar://problem/27992351.
[test] Add a timeout to runRaceTest(). Use it to limit test AtomicInt.swift.
This cuts AtomicInt.swift's execution time from several hours to
about ten minutes on slow hardware and slow build configurations.
From the Swift documentation:
"If you define an optional variable without providing a default value,
the variable is automatically set to nil for you."
SE-0032 did not propose a protocol entry point, only a protocol
extension.
Using a pure protocol extension is the right choice here because a
concrete sequence can't provide a more efficient implementation of this
method than the default one.
Now that the previous patches have shaken out implicit assumptions
about the order of generic requirements and substitutions, we can
make a more radical change, dropping redundant protocol requirements
when building the original generic signature.
This means that the canonical ordering and minimization that we
used to only perform when building the mangling signature is done
all of the time, and hence getCanonicalManglingSignature() can go
away.
Usages now either call getCanonicalSignature(), or operate on the
original signature directly.
We could support this in the future but right now it's causing problems.
There's also a potential ambiguity issue here where a protocol and class
could have the same name.
In addition to updating the importer, remove the two entries from the
CryptoTokenKit API notes that were trying to use this feature.
rdar://problem/27990168
This reverts commit dc0ae675bc. The
change here (presumably the change to Foundation) caused a regression
in several of the bridging-related benchmarks, e.g.,
ObjectiveCBridgeFromNSSetAnyObjectToString, DictionaryBridge,
ObjectiveCBridgeFromNSDictionaryAnyObjectToString.
Remove the functions
_(set|dictionary)Bridge(From|To)ObjectiveC(Conditional) from the
standard library. These entrypoints are no longer used by the compiler
(thanks to generalized collection up/downcasting), so stop using them
in Foundation and in tests.
Like NSObject, CFType has primitive operations CFEqual and CFHash,
so Swift should allow those types to show up in Hashable positions
(like dictionaries). The most general way to do this was to
introduce a new protocol, _CFObject, and then have the importer
automatically make all CF types conform to it.
This did require one additional change: the == implementation that
calls through to CFEqual is in a new CoreFoundation overlay, but the
conformance is in the underlying Clang module. Therefore, operator
lookup for conformances has been changed to look in the overlay for
an imported declaration (if there is one).
https://bugs.swift.org/browse/SR-2388
Use that instead of rolling it up in _SwiftTypePreservingNSNumber so that we
get the right behavior when we go to write plists.
https://bugs.swift.org/browse/SR-2381
The Objective-C type encoding of Boolean values in NSNumber is that of
BOOL, which is either signed char or _Bool depending on the
platform. _SwiftTypePreservingNSNumber was using _Bool, which led to
inconsistencies when bridging vs. creating an NSNumber directly. Use
BOOL consistently.
Fixes rdar://problem/27894308.