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.
SE-0107 states that UnsafePointer.withMemoryRebound(to:capacity:) should produce
a const UnsafePointer, but the implementation that I committed in Whitney
produces an UnsafeMutablePointer.
As a result Swift 3 accepts code, that we would like to reject:
func takesUInt(_: UnsafeMutablePointer<UInt>) {}
func takesConstUInt(_: UnsafePointer<UInt>) {}
func foo(p: UnsafePointer<Int>) {
p.withMemoryRebound(to: UInt.self, capacity: 1) {
takesUInt($0) // <========= implicitly converts to a mutable pointer
takesConstUInt($0)
}
}
We would like to reject this in favor of:
func takesUInt(_: UnsafeMutablePointer<UInt>) {}
func takesConstUInt(_: UnsafePointer<UInt>) {}
func foo(p: UnsafePointer<Int>) {
p.withMemoryRebound(to: UInt.self, capacity: 1) {
takesUInt(UnsafeMutablePointer(mutating: $0))
takesConstUInt($0)
}
}
This looks to me like an experimental change accidentally creeped onto my branch
and it was hard to spot in .gyb code. I needed to write the unit test
in terms of UnsafeMutablePointer in order to use expectType, so didn't
catch this.
rdar://28409842 UnsafePointer.withMemoryRebound(to:capacity:) incorrectly produces a mutable pointer argument
When printing a tuple via print(...), print tuple labels when they are
available. This is possible now that the runtime metadata properly
stores tuple labels. Fixes rdar://problem/23130016.
If the Key is a class, then FunctionSignatureOpts cannot convert it to a @guaranteed parameter.
Using the new EpilogueARCAnalysis in FunctionSignatureOpts should fix that.
Those conditions should not fail with any user code. They just check the internal implementation of the stdlib.
This removes some runtime checks in the generated code with the optimized library.
id-as-Any lets you pass Optional to an ObjC API that takes `nonnull id`, and also lets you bridge containers of `Optional` to `NSArray` etc. When this occurs, we can unwrap the value and bridge it so that inhabited optionals still pass into ObjC in the expected way, but we need something to represent `none` other than the `nil` pointer. Cocoa provides `NSNull` as the canonical "null for containers" object, which is the least bad of many possible answers. If we happen to have the rare nested optional `T??`, there is no precedented analog for these in Cocoa, so just generate a unique sentinel object to preserve the `nil`-ness depth so we at least don't lose information round-tripping across the ObjC-Swift bridge.
Making Optional conform to _ObjectiveCBridgeable is more or less enough to make this all work, though there are a few additional edge case things that need to be fixed up. We don't want to accept `AnyObject??` as an @objc-compatible type, so special-case Optional in `getForeignRepresentable`.
Implements SR-0140 (rdar://problem/27905315).
We need the encode string to be able to construct NSValues using the core valueWithBytes:objCType: API. This builtin only works with concrete, @objc-representable types for now, which should be sufficient for a stdlib-internal API.
From the Swift documentation:
"If you define an optional variable without providing a default value,
the variable is automatically set to nil for you."
This reduces the amount of SIL generated for Set/Dictionary operations significantly.
The generated code should be mostly the same (modulo different inlining decisions).
This reduces the amount of SIL generated for array operations significantly.
The generated code should be mostly the same (modulo different inlining decisions).
Those builtins are: allocWithTailElems_<n>, getTailAddr and projectTailElems
Also rename the "gep" builtin, which indexes raw bytes, to "gepRaw" and add a new "gep" builtin to index in a typed array.
id-as-Any lets you pass Optional to an ObjC API that takes `nonnull id`, and also lets you bridge containers of `Optional` to `NSArray` etc. When this occurs, we can unwrap the value and bridge it so that inhabited optionals still pass into ObjC in the expected way, but we need something to represent `none` other than the `nil` pointer. Cocoa provides `NSNull` as the canonical "null for containers" object, which is the least bad of many possible answers. If we happen to have the rare nested optional `T??`, there is no precedented analog for these in Cocoa, so just generate a unique sentinel object to preserve the `nil`-ness depth so we at least don't lose information round-tripping across the ObjC-Swift bridge.
Making Optional conform to _ObjectiveCBridgeable is more or less enough to make this all work, though there are a few additional edge case things that need to be fixed up. We don't want to accept `AnyObject??` as an @objc-compatible type, so special-case Optional in `getForeignRepresentable`.
Implements SR-0140 (rdar://problem/27905315).
This reduces the amount of SIL generated for Set/Dictionary operations significantly.
The generated code should be mostly the same (modulo different inlining decisions).
This reduces the amount of SIL generated for array operations significantly.
The generated code should be mostly the same (modulo different inlining decisions).
Those builtins are: allocWithTailElems_<n>, getTailAddr and projectTailElems
Also rename the "gep" builtin, which indexes raw bytes, to "gepRaw" and add a new "gep" builtin to index in a typed array.