ClangImporter: Import unbounded NSSets and NSDictionaries using AnyHashable.

This commit is contained in:
Joe Groff
2016-07-25 16:20:27 -07:00
parent e884ab737d
commit 1e8dd0e34b
18 changed files with 100 additions and 51 deletions

View File

@@ -395,6 +395,9 @@ public:
/// Retrieve the declaration of Swift.Dictionary<K, V>. /// Retrieve the declaration of Swift.Dictionary<K, V>.
NominalTypeDecl *getDictionaryDecl() const; NominalTypeDecl *getDictionaryDecl() const;
/// Retrieve the declaration of Swift.AnyHashable.
NominalTypeDecl *getAnyHashableDecl() const;
/// Retrieve the declaration of Swift.Optional or ImplicitlyUnwrappedOptional. /// Retrieve the declaration of Swift.Optional or ImplicitlyUnwrappedOptional.
EnumDecl *getOptionalDecl(OptionalTypeKind kind) const; EnumDecl *getOptionalDecl(OptionalTypeKind kind) const;

View File

@@ -119,6 +119,9 @@ struct ASTContext::Implementation {
/// The declaration of Swift.Dictionary<T>. /// The declaration of Swift.Dictionary<T>.
NominalTypeDecl *DictionaryDecl = nullptr; NominalTypeDecl *DictionaryDecl = nullptr;
/// The declaration of Swift.AnyHashable.
NominalTypeDecl *AnyHashableDecl = nullptr;
/// The declaration of Swift.Optional<T>. /// The declaration of Swift.Optional<T>.
EnumDecl *OptionalDecl = nullptr; EnumDecl *OptionalDecl = nullptr;
@@ -615,6 +618,12 @@ NominalTypeDecl *ASTContext::getDictionaryDecl() const {
return Impl.DictionaryDecl; return Impl.DictionaryDecl;
} }
NominalTypeDecl *ASTContext::getAnyHashableDecl() const {
if (!Impl.AnyHashableDecl)
Impl.AnyHashableDecl = findStdlibType(*this, "AnyHashable", 0);
return Impl.AnyHashableDecl;
}
EnumDecl *ASTContext::getOptionalDecl(OptionalTypeKind kind) const { EnumDecl *ASTContext::getOptionalDecl(OptionalTypeKind kind) const {
switch (kind) { switch (kind) {
case OTK_None: case OTK_None:

View File

@@ -908,12 +908,18 @@ namespace {
return Type(); return Type();
// The first type argument for Dictionary or Set needs // The first type argument for Dictionary or Set needs
// to be NSObject-bound. // to be Hashable. Everything that inherits NSObject has a
// -hash code in ObjC, but if something isn't NSObject, fall back
// to AnyHashable as a key type.
if (unboundDecl == Impl.SwiftContext.getDictionaryDecl() || if (unboundDecl == Impl.SwiftContext.getDictionaryDecl() ||
unboundDecl == Impl.SwiftContext.getSetDecl()) { unboundDecl == Impl.SwiftContext.getSetDecl()) {
auto &keyType = importedTypeArgs[0]; auto &keyType = importedTypeArgs[0];
if (!Impl.matchesNSObjectBound(keyType)) if (!Impl.matchesNSObjectBound(keyType)) {
keyType = Impl.getNSObjectType(); if (auto anyHashable = Impl.SwiftContext.getAnyHashableDecl())
keyType = anyHashable->getDeclaredType();
else
keyType = Type();
}
} }
// Form the specialized type. // Form the specialized type.
@@ -2624,6 +2630,7 @@ bool ClangImporter::Implementation::matchesNSObjectBound(Type type) {
return true; return true;
// Struct or enum type must have been bridged. // Struct or enum type must have been bridged.
// TODO: Check that the bridged type is Hashable?
if (type->getStructOrBoundGenericStruct() || if (type->getStructOrBoundGenericStruct() ||
type->getEnumOrBoundGenericEnum()) type->getEnumOrBoundGenericEnum())
return true; return true;

View File

@@ -1160,7 +1160,7 @@ public:
Type getCFStringRefType(); Type getCFStringRefType();
/// \brief Determines whether the given type matches an implicit type /// \brief Determines whether the given type matches an implicit type
/// bound of "NSObject", which is used to validate NSDictionary/NSSet. /// bound of "Hashable", which is used to validate NSDictionary/NSSet.
bool matchesNSObjectBound(Type type); bool matchesNSObjectBound(Type type);
/// \brief Look up and attempt to import a Clang declaration with /// \brief Look up and attempt to import a Clang declaration with

View File

@@ -50,9 +50,9 @@ extension CIFilter {
extension CISampler { extension CISampler {
// - (id)initWithImage:(CIImage *)im keysAndValues:key0, ...; // - (id)initWithImage:(CIImage *)im keysAndValues:key0, ...;
convenience init(im: CIImage, elements: (String, Any)...) { convenience init(im: CIImage, elements: (String, Any)...) {
var dict: [NSObject : Any] = [:] var dict: [AnyHashable : Any] = [:]
for (key, value) in elements { for (key, value) in elements {
dict[key as NSObject] = value dict[key] = value
} }
// @objc(initWithImage:options:) // @objc(initWithImage:options:)

View File

@@ -1237,7 +1237,8 @@ extension NSSet {
/// receiver. /// receiver.
@objc(_swiftInitWithSet_NSSet:) @objc(_swiftInitWithSet_NSSet:)
public convenience init(set anSet: NSSet) { public convenience init(set anSet: NSSet) {
self.init(set: anSet as Set) // FIXME: This is a bit weird. Maybe there's a better way?
self.init(set: anSet as Set<NSObject> as Set<AnyHashable>)
} }
} }
@@ -1250,7 +1251,9 @@ extension NSDictionary {
/// found in `otherDictionary`. /// found in `otherDictionary`.
@objc(_swiftInitWithDictionary_NSDictionary:) @objc(_swiftInitWithDictionary_NSDictionary:)
public convenience init(dictionary otherDictionary: NSDictionary) { public convenience init(dictionary otherDictionary: NSDictionary) {
self.init(dictionary: otherDictionary as Dictionary) // FIXME: This is a bit weird. Maybe there's a better way?
self.init(dictionary: otherDictionary as [NSObject: AnyObject]
as [AnyHashable: Any])
} }
} }

View File

@@ -389,11 +389,11 @@ public protocol _BridgedStoredNSError :
} }
/// TODO: Better way to do this? /// TODO: Better way to do this?
internal func _stringDictToNSObjectDict(_ input: [String : Any]) internal func _stringDictToAnyHashableDict(_ input: [String : Any])
-> [NSObject : Any] { -> [AnyHashable : Any] {
var result: [NSObject : Any] = [:] var result: [AnyHashable : Any] = [:]
for (k, v) in input { for (k, v) in input {
result[k as NSString] = v result[k] = v
} }
return result return result
} }
@@ -411,7 +411,7 @@ public extension _BridgedStoredNSError
public init(_ code: Code, userInfo: [String : Any] = [:]) { public init(_ code: Code, userInfo: [String : Any] = [:]) {
self.init(_nsError: NSError(domain: Self._nsErrorDomain, self.init(_nsError: NSError(domain: Self._nsErrorDomain,
code: numericCast(code.rawValue), code: numericCast(code.rawValue),
userInfo: _stringDictToNSObjectDict(userInfo))) userInfo: _stringDictToAnyHashableDict(userInfo)))
} }
/// The user-info dictionary for an error that was bridged from /// The user-info dictionary for an error that was bridged from
@@ -432,7 +432,7 @@ public extension _BridgedStoredNSError
public init(_ code: Code, userInfo: [String : Any] = [:]) { public init(_ code: Code, userInfo: [String : Any] = [:]) {
self.init(_nsError: NSError(domain: Self._nsErrorDomain, self.init(_nsError: NSError(domain: Self._nsErrorDomain,
code: numericCast(code.rawValue), code: numericCast(code.rawValue),
userInfo: _stringDictToNSObjectDict(userInfo))) userInfo: _stringDictToAnyHashableDict(userInfo)))
} }
} }
@@ -461,7 +461,7 @@ public extension _BridgedStoredNSError {
var errorUserInfo: [String : Any] { var errorUserInfo: [String : Any] {
var result: [String : Any] = [:] var result: [String : Any] = [:]
for (key, value) in _nsError.userInfo { for (key, value) in _nsError.userInfo {
guard let stringKey = key as? String else { continue } guard let stringKey = key.base as? String else { continue }
result[stringKey] = value result[stringKey] = value
} }
return result return result
@@ -528,7 +528,7 @@ public struct CocoaError : _BridgedStoredNSError {
} }
public extension CocoaError { public extension CocoaError {
private var _nsUserInfo: [NSObject : Any] { private var _nsUserInfo: [AnyHashable : Any] {
return (self as NSError).userInfo return (self as NSError).userInfo
} }
@@ -1329,7 +1329,7 @@ public struct URLError : _BridgedStoredNSError {
} }
public extension URLError { public extension URLError {
private var _nsUserInfo: [NSObject : Any] { private var _nsUserInfo: [AnyHashable : Any] {
return (self as NSError).userInfo return (self as NSError).userInfo
} }

View File

@@ -1180,7 +1180,8 @@ extension String {
/// values found in the `String`. /// values found in the `String`.
public public
func propertyListFromStringsFileFormat() -> [String : String] { func propertyListFromStringsFileFormat() -> [String : String] {
return _ns.propertyListFromStringsFileFormat() as! [String : String] return _ns.propertyListFromStringsFileFormat()! as [NSObject : AnyObject]
as! [String : String]
} }
// - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet // - (NSRange)rangeOfCharacterFromSet:(NSCharacterSet *)aSet

View File

@@ -97,10 +97,10 @@ ErrorBridgingTests.test("NSError-to-enum bridging") {
let ns = NSError(domain: NSCocoaErrorDomain, let ns = NSError(domain: NSCocoaErrorDomain,
code: NSFileNoSuchFileError, code: NSFileNoSuchFileError,
userInfo: [ userInfo: [
NSFilePathErrorKey as NSObject : "/dev/null", AnyHashable(NSFilePathErrorKey): "/dev/null",
NSStringEncodingErrorKey as NSObject: /*ASCII=*/1, AnyHashable(NSStringEncodingErrorKey): /*ASCII=*/1,
NSUnderlyingErrorKey as NSObject: underlyingError, AnyHashable(NSUnderlyingErrorKey): underlyingError,
NSURLErrorKey as NSObject: testURL AnyHashable(NSURLErrorKey): testURL
]) ])
objc_setAssociatedObject(ns, &CanaryHandle, NoisyError(), objc_setAssociatedObject(ns, &CanaryHandle, NoisyError(),
@@ -143,7 +143,7 @@ ErrorBridgingTests.test("NSError-to-enum bridging") {
// URLError domain // URLError domain
let nsURL = NSError(domain: NSURLErrorDomain, let nsURL = NSError(domain: NSURLErrorDomain,
code: NSURLErrorBadURL, code: NSURLErrorBadURL,
userInfo: [NSURLErrorFailingURLErrorKey as NSObject : testURL]) userInfo: [AnyHashable(NSURLErrorFailingURLErrorKey): testURL])
let eURL: Error = nsURL let eURL: Error = nsURL
let isBadURLError: Bool let isBadURLError: Bool
switch eURL { switch eURL {
@@ -162,7 +162,7 @@ ErrorBridgingTests.test("NSError-to-enum bridging") {
// CoreLocation error domain // CoreLocation error domain
let nsCL = NSError(domain: kCLErrorDomain, let nsCL = NSError(domain: kCLErrorDomain,
code: CLError.headingFailure.rawValue, code: CLError.headingFailure.rawValue,
userInfo: [NSURLErrorKey as NSObject: testURL]) userInfo: [AnyHashable(NSURLErrorKey): testURL])
let eCL: Error = nsCL let eCL: Error = nsCL
let isHeadingFailure: Bool let isHeadingFailure: Bool
switch eCL { switch eCL {
@@ -318,7 +318,7 @@ class SomeNSErrorSubclass: NSError {}
ErrorBridgingTests.test("Thrown NSError identity is preserved") { ErrorBridgingTests.test("Thrown NSError identity is preserved") {
do { do {
let e = NSError(domain: "ClericalError", code: 219, let e = NSError(domain: "ClericalError", code: 219,
userInfo: ["yeah": "yeah"]) userInfo: [AnyHashable("yeah"): "yeah"])
do { do {
throw e throw e
} catch let e2 as NSError { } catch let e2 as NSError {
@@ -331,7 +331,7 @@ ErrorBridgingTests.test("Thrown NSError identity is preserved") {
do { do {
let f = SomeNSErrorSubclass(domain: "ClericalError", code: 219, let f = SomeNSErrorSubclass(domain: "ClericalError", code: 219,
userInfo: ["yeah": "yeah"]) userInfo: [AnyHashable("yeah"): "yeah"])
do { do {
throw f throw f
} catch let f2 as NSError { } catch let f2 as NSError {

View File

@@ -18,7 +18,7 @@ NSEnumeratorAPI.test("Sequence") {
NSEnumeratorAPI.test("keyEnumerator") { NSEnumeratorAPI.test("keyEnumerator") {
let result = [1 as NSNumber: "one", 2 as NSNumber: "two"] let result = [1 as NSNumber: "one", 2 as NSNumber: "two"]
expectEqualsUnordered( expectEqualsUnordered(
[1, 2], NSDictionary(dictionary: result).keyEnumerator()) { [1, 2], NSDictionary(dictionary: result as [AnyHashable: Any]).keyEnumerator()) {
switch ($0 as! Int, $1 as! Int) { switch ($0 as! Int, $1 as! Int) {
case let (x, y) where x == y: return .eq case let (x, y) where x == y: return .eq
case let (x, y) where x < y: return .lt case let (x, y) where x < y: return .lt

View File

@@ -16,12 +16,15 @@ tests.test("user info") {
let error = NSError(domain: "MyDomain", code: 1, userInfo: [ let error = NSError(domain: "MyDomain", code: 1, userInfo: [
// CHECK-WARNINGS: warning: 'localizedDescriptionKey' is deprecated: renamed to 'NSLocalizedDescriptionKey' // CHECK-WARNINGS: warning: 'localizedDescriptionKey' is deprecated: renamed to 'NSLocalizedDescriptionKey'
// CHECK-WARNINGS: note: use 'NSLocalizedDescriptionKey' instead // CHECK-WARNINGS: note: use 'NSLocalizedDescriptionKey' instead
ErrorUserInfoKey.localizedDescriptionKey.rawValue as NSString: "description", AnyHashable(ErrorUserInfoKey.localizedDescriptionKey.rawValue): "description",
NSLocalizedFailureReasonErrorKey as NSString: "reason" AnyHashable(NSLocalizedFailureReasonErrorKey): "reason"
]) ])
expectEqual("description", error.userInfo[NSLocalizedDescriptionKey as NSString]! as! String) expectEqual("description", error.userInfo[NSLocalizedDescriptionKey]! as! String)
expectEqual("reason", error.userInfo[ErrorUserInfoKey.localizedFailureReasonErrorKey.rawValue as NSObject]! as! String)
expectEqual("reason", error.userInfo[ErrorUserInfoKey.localizedFailureReasonErrorKey.rawValue]! as! String)
// TODO: Without the 'as NSObject' conversion, this produces nil.
// We may need to forward _CustomAnyHashable through swift_newtypes.
expectEqual("reason", error.userInfo[ErrorUserInfoKey.localizedFailureReasonErrorKey as NSObject]! as! String) expectEqual("reason", error.userInfo[ErrorUserInfoKey.localizedFailureReasonErrorKey as NSObject]! as! String)
} }

View File

@@ -35,11 +35,11 @@ func foo() {
_ = arrayToArray as (Array<Any>!) -> (Array<Any>!) _ = arrayToArray as (Array<Any>!) -> (Array<Any>!)
DummyClass().arrayProperty.onlyOnArray() DummyClass().arrayProperty.onlyOnArray()
_ = dictToDict as (Dictionary<NSObject, Any>!) -> Dictionary<NSObject, Any>! _ = dictToDict as (Dictionary<AnyHashable, Any>!) -> Dictionary<AnyHashable, Any>!
DummyClass().dictProperty.onlyOnDictionary() DummyClass().dictProperty.onlyOnDictionary()
_ = setToSet as (Set<NSObject>!) -> Set<NSObject>! _ = setToSet as (Set<AnyHashable>!) -> Set<AnyHashable>!
DummyClass().setProperty.onlyOnSet() DummyClass().setProperty.onlyOnSet()
} }

View File

@@ -13,7 +13,7 @@ func testNSDictionaryBridging(_ hive: Hive) {
_ = hive.beesByName as [String : Bee] // expected-error{{value of optional type '[String : Bee]?' not unwrapped; did you mean to use '!' or '?'?}} _ = hive.beesByName as [String : Bee] // expected-error{{value of optional type '[String : Bee]?' not unwrapped; did you mean to use '!' or '?'?}}
var dict1 = hive.anythingToBees var dict1 = hive.anythingToBees
let dict2: [NSObject : Bee] = dict1 let dict2: [AnyHashable : Bee] = dict1
dict1 = dict2 dict1 = dict2
} }

View File

@@ -45,7 +45,9 @@ public func err() {
// DWARF-CHECK: DW_AT_name{{.*}}NSError // DWARF-CHECK: DW_AT_name{{.*}}NSError
// DWARF-CHECK: DW_AT_linkage_name{{.*}}_TtCSo7NSError // DWARF-CHECK: DW_AT_linkage_name{{.*}}_TtCSo7NSError
let _ = NSError(domain: "myDomain", code: 4, let _ = NSError(domain: "myDomain", code: 4,
userInfo: ["a":1,"b":2,"c":3]) userInfo: [AnyHashable("a"):1,
AnyHashable("b"):2,
AnyHashable("c"):3])
} }
// LOC-CHECK: define {{.*}}4date // LOC-CHECK: define {{.*}}4date

View File

@@ -30,7 +30,7 @@
// Make sure that we don't qualify 'NSErrorPointer'. // Make sure that we don't qualify 'NSErrorPointer'.
// CHECK_NSSTRING: init(contentsOfFile path: String, encoding enc: UInt) throws // CHECK_NSSTRING: init(contentsOfFile path: String, encoding enc: UInt) throws
// CHECK_DICTIONARY: func propertyListFromStringsFileFormat() -> [NSObject : Any] // CHECK_DICTIONARY: func propertyListFromStringsFileFormat() -> [AnyHashable : Any]
// RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print=Foundation -function-definitions=false > %t/Foundation.printed.txt // RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print=Foundation -function-definitions=false > %t/Foundation.printed.txt
// RUN: FileCheck -input-file %t/Foundation.printed.txt -check-prefix=CHECK_DUP %s // RUN: FileCheck -input-file %t/Foundation.printed.txt -check-prefix=CHECK_DUP %s

View File

@@ -163,7 +163,7 @@
// CHECK-FOUNDATION: func normalizingXMLPreservingComments(_: Bool) // CHECK-FOUNDATION: func normalizingXMLPreservingComments(_: Bool)
// Collection element types. // Collection element types.
// CHECK-FOUNDATION: func adding(_: Any) -> Set<NSObject> // CHECK-FOUNDATION: func adding(_: Any) -> Set<AnyHashable>
// Boolean properties follow the getter. // Boolean properties follow the getter.
// CHECK-FOUNDATION: var empty: Bool { get } // CHECK-FOUNDATION: var empty: Bool { get }
@@ -218,8 +218,8 @@
// CHECK-APPKIT: func draw(in: NSView?) // CHECK-APPKIT: func draw(in: NSView?)
// Note: NSDictionary default arguments for "options" // Note: NSDictionary default arguments for "options"
// CHECK-APPKIT: func drawAnywhere(in: NSView?, options: [NSObject : Any] = [:]) // CHECK-APPKIT: func drawAnywhere(in: NSView?, options: [AnyHashable : Any] = [:])
// CHECK-APPKIT: func drawAnywhere(options: [NSObject : Any] = [:]) // CHECK-APPKIT: func drawAnywhere(options: [AnyHashable : Any] = [:])
// Note: no lowercasing of initialisms when there might be a prefix. // Note: no lowercasing of initialisms when there might be a prefix.
// CHECK-CORECOOLING: func CFBottom() -> // CHECK-CORECOOLING: func CFBottom() ->

View File

@@ -178,3 +178,24 @@ extension NSError : Error {
public var _code: Int { return code } public var _code: Int { return code }
} }
extension AnyHashable : _ObjectiveCBridgeable {
public func _bridgeToObjectiveC() -> NSObject {
fatalError()
}
public static func _forceBridgeFromObjectiveC(
_ x: NSObject,
result: inout AnyHashable?
) {
}
public static func _conditionallyBridgeFromObjectiveC(
_ x: NSObject,
result: inout AnyHashable?
) -> Bool {
fatalError()
}
public static func _unconditionallyBridgeFromObjectiveC(
_ x: NSObject?
) -> AnyHashable {
fatalError()
}
}

View File

@@ -73,27 +73,27 @@ func testNullUnspecified(_ obj: Test) -> [Any]! {
} // CHECK: {{^}$}} } // CHECK: {{^}$}}
// CHECK-LABEL: sil hidden @_TF20objc_bridged_results21testNonnullDictionaryFCSo4TestGVs10DictionaryCSo8NSObjectP__ // CHECK-LABEL: sil hidden @_TF20objc_bridged_results21testNonnullDictionaryFCSo4TestGVs10DictionaryVs11AnyHashableP__
func testNonnullDictionary(_ obj: Test) -> [NSObject: Any] { func testNonnullDictionary(_ obj: Test) -> [AnyHashable: Any] {
// CHECK: [[METHOD:%[0-9]+]] = class_method [volatile] %0 : $Test, #Test.nonnullDictionary!getter.1.foreign : (Test) -> () -> [NSObject : Any] , $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary> // CHECK: [[METHOD:%[0-9]+]] = class_method [volatile] %0 : $Test, #Test.nonnullDictionary!getter.1.foreign : (Test) -> () -> [AnyHashable : Any] , $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary>
// CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]](%0) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary> // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]](%0) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary>
// CHECK: [[CONVERT:%[0-9]+]] = function_ref @_TZFE10FoundationVs10Dictionary36_unconditionallyBridgeFromObjectiveCfGSqCSo12NSDictionary_GS0_xq__ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @_TZFE10FoundationVs10Dictionary36_unconditionallyBridgeFromObjectiveCfGSqCSo12NSDictionary_GS0_xq__
// CHECK: [[DICT_META:%[0-9]+]] = metatype $@thin Dictionary<NSObject, Any>.Type // CHECK: [[DICT_META:%[0-9]+]] = metatype $@thin Dictionary<AnyHashable, Any>.Type
// CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<NSObject, Any>([[COCOA_VAL]], [[DICT_META]]) // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<AnyHashable, Any>([[COCOA_VAL]], [[DICT_META]])
// CHECK: strong_release %0 : $Test // CHECK: strong_release %0 : $Test
// CHECK: return [[RESULT]] : $Dictionary<NSObject, Any> // CHECK: return [[RESULT]] : $Dictionary<AnyHashable, Any>
return obj.nonnullDictionary return obj.nonnullDictionary
} // CHECK: {{^}$}} } // CHECK: {{^}$}}
// CHECK-LABEL: sil hidden @_TF20objc_bridged_results14testNonnullSetFCSo4TestGVs3SetCSo8NSObject_ // CHECK-LABEL: sil hidden @_TF20objc_bridged_results14testNonnullSetFCSo4TestGVs3SetVs11AnyHashable_
func testNonnullSet(_ obj: Test) -> Set<NSObject> { func testNonnullSet(_ obj: Test) -> Set<AnyHashable> {
// CHECK: [[METHOD:%[0-9]+]] = class_method [volatile] %0 : $Test, #Test.nonnullSet!getter.1.foreign : (Test) -> () -> Set<NSObject> , $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet> // CHECK: [[METHOD:%[0-9]+]] = class_method [volatile] %0 : $Test, #Test.nonnullSet!getter.1.foreign : (Test) -> () -> Set<AnyHashable> , $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet>
// CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]](%0) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet> // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]](%0) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet>
// CHECK: [[CONVERT:%[0-9]+]] = function_ref @_TZFE10FoundationVs3Set36_unconditionallyBridgeFromObjectiveCfGSqCSo5NSSet_GS0_x_ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @_TZFE10FoundationVs3Set36_unconditionallyBridgeFromObjectiveCfGSqCSo5NSSet_GS0_x_
// CHECK: [[SET_META:%[0-9]+]] = metatype $@thin Set<NSObject>.Type // CHECK: [[SET_META:%[0-9]+]] = metatype $@thin Set<AnyHashable>.Type
// CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<NSObject>([[COCOA_VAL]], [[SET_META]]) // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<AnyHashable>([[COCOA_VAL]], [[SET_META]])
// CHECK: strong_release %0 : $Test // CHECK: strong_release %0 : $Test
// CHECK: return [[RESULT]] : $Set<NSObject> // CHECK: return [[RESULT]] : $Set<AnyHashable>
return obj.nonnullSet return obj.nonnullSet
} // CHECK: {{^}$}} } // CHECK: {{^}$}}