| // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -verify -swift-version 4 -I %S/Inputs/custom-modules %s |
| |
| // REQUIRES: objc_interop |
| |
| import Foundation |
| import objc_generics |
| import ObjCBridgeNonconforming |
| |
| func testNSArrayBridging(_ hive: Hive) { |
| _ = hive.bees as [Bee] |
| } |
| |
| func testNSDictionaryBridging(_ hive: Hive) { |
| _ = hive.beesByName as [String : Bee] // expected-error{{'[String : Bee]?' is not convertible to '[String : Bee]'; did you mean to use 'as!' to force downcast?}} |
| |
| var dict1 = hive.anythingToBees |
| let dict2: [AnyHashable : Bee] = dict1 |
| dict1 = dict2 |
| } |
| |
| func testNSSetBridging(_ hive: Hive) { |
| _ = hive.allBees as Set<Bee> |
| } |
| |
| public func expectType<T>(_: T.Type, _ x: inout T) {} |
| |
| func testNSMutableDictionarySubscript( |
| _ dict: NSMutableDictionary, key: NSCopying, value: Any) { |
| var oldValue = dict[key] |
| expectType(Optional<Any>.self, &oldValue) |
| |
| dict[key] = value |
| } |
| |
| class C {} |
| struct S {} |
| |
| func f(_ x: GenericClass<NSString>) -> NSString? { return x.thing() } |
| func f1(_ x: GenericClass<NSString>) -> NSString? { return x.otherThing() } |
| func f2(_ x: GenericClass<NSString>) -> Int32 { return x.count() } |
| func f3(_ x: GenericClass<NSString>) -> NSString? { return x.propertyThing } |
| func f4(_ x: GenericClass<NSString>) -> [NSString] { return x.arrayOfThings() } |
| func f5(_ x: GenericClass<C>) -> [C] { return x.arrayOfThings() } |
| func f6(_ x: GenericSubclass<NSString>) -> NSString? { return x.thing() } |
| func f6(_ x: GenericSubclass<C>) -> C? { return x.thing() } |
| |
| func g() -> NSString? { return GenericClass<NSString>.classThing() } |
| func g1() -> NSString? { return GenericClass<NSString>.otherClassThing() } |
| |
| func h(_ s: NSString?) -> GenericClass<NSString> { |
| return GenericClass(thing: s) |
| } |
| |
| func j(_ x: GenericClass<NSString>?) { |
| takeGenericClass(x) |
| } |
| |
| class Desk {} |
| class Rock: NSObject, Pettable { |
| required init(fur: Any) {} |
| func other() -> Self { return self } |
| class func adopt() -> Self { fatalError("") } |
| func pet() {} |
| func pet(with other: Pettable) {} |
| class var needingMostPets: Pettable { |
| get { fatalError("") } |
| set { } |
| } |
| } |
| class Porcupine: Animal { |
| } |
| class Cat: Animal, Pettable { |
| required init(fur: Any) {} |
| func other() -> Self { return self } |
| class func adopt() -> Self { fatalError("") } |
| func pet() {} |
| func pet(with other: Pettable) {} |
| class var needingMostPets: Pettable { |
| get { fatalError("") } |
| set { } |
| } |
| } |
| |
| func testImportedTypeParamRequirements() { |
| let _ = PettableContainer<Desk>() // expected-error{{type 'Desk' does not conform to protocol 'Pettable'}} |
| let _ = PettableContainer<Rock>() |
| let _ = PettableContainer<Porcupine>() // expected-error{{type 'Porcupine' does not conform to protocol 'Pettable'}} |
| let _ = PettableContainer<Cat>() |
| let _ = AnimalContainer<Desk>() // expected-error{{'AnimalContainer' requires that 'Desk' inherit from 'Animal'}} expected-note{{requirement specified as 'T' : 'Animal' [with T = Desk]}} |
| let _ = AnimalContainer<Rock>() // expected-error{{'AnimalContainer' requires that 'Rock' inherit from 'Animal'}} expected-note{{requirement specified as 'T' : 'Animal' [with T = Rock]}} |
| let _ = AnimalContainer<Porcupine>() |
| let _ = AnimalContainer<Cat>() |
| let _ = PettableAnimalContainer<Desk>() // expected-error{{'PettableAnimalContainer' requires that 'Desk' inherit from 'Animal'}} expected-note{{requirement specified as 'T' : 'Animal' [with T = Desk]}} |
| let _ = PettableAnimalContainer<Rock>() // expected-error{{'PettableAnimalContainer' requires that 'Rock' inherit from 'Animal'}} expected-note{{requirement specified as 'T' : 'Animal' [with T = Rock]}} |
| let _ = PettableAnimalContainer<Porcupine>() // expected-error{{type 'Porcupine' does not conform to protocol 'Pettable'}} |
| let _ = PettableAnimalContainer<Cat>() |
| } |
| |
| extension GenericClass { |
| @objc func doesntUseGenericParam() {} |
| @objc func doesntUseGenericParam2() -> Self {} |
| // Doesn't use 'T', since ObjC class type params are type-erased |
| @objc func doesntUseGenericParam3() -> GenericClass<T> {} |
| // Doesn't use 'T', since its metadata isn't necessary to pass around instance |
| @objc func doesntUseGenericParam4(_ x: T, _ y: T.Type) -> T { |
| _ = x |
| _ = y |
| return x |
| } |
| // Doesn't use 'T', since its metadata isn't necessary to erase to AnyObject |
| // or to existential metatype |
| @objc func doesntUseGenericParam5(_ x: T, _ y: T.Type) -> T { |
| _ = y as AnyObject.Type |
| _ = y as Any.Type |
| _ = y as AnyObject |
| _ = x as AnyObject |
| } |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamC(_ x: [(T, T)]?) {} // expected-note{{used here}} |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamD(_ x: Int) { |
| _ = T.self // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamE(_ x: Int) { |
| _ = x as? T // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamF(_ x: Int) { |
| _ = x is T // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamG(_ x: T) { |
| _ = T.self // expected-note{{used here}} |
| } |
| @objc func doesntUseGenericParamH(_ x: T) { |
| _ = x as Any |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamI(_ y: T.Type) { |
| _ = y as Any // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamJ() -> [(T, T)]? {} // expected-note{{used here}} |
| |
| @objc static func doesntUseGenericParam() {} |
| @objc static func doesntUseGenericParam2() -> Self {} |
| // Doesn't technically use 'T', since it's type-erased at runtime |
| @objc static func doesntUseGenericParam3() -> GenericClass<T> {} |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| static func usesGenericParamC(_ x: [(T, T)]?) {} // expected-note{{used here}} |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc static func usesGenericParamD(_ x: Int) { |
| _ = T.self // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc static func usesGenericParamE(_ x: Int) { |
| _ = x as? T // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc static func usesGenericParamF(_ x: Int) { |
| _ = x is T // expected-note{{used here}} |
| } |
| |
| @objc func checkThatMethodsAreObjC() { |
| _ = #selector(GenericClass.doesntUseGenericParam) |
| _ = #selector(GenericClass.doesntUseGenericParam2) |
| _ = #selector(GenericClass.doesntUseGenericParam3) |
| _ = #selector(GenericClass.doesntUseGenericParam4) |
| _ = #selector(GenericClass.doesntUseGenericParam5) |
| } |
| } |
| |
| func swiftFunction<T: Animal>(x: T) {} |
| |
| extension AnimalContainer { |
| @objc func doesntUseGenericParam1(_ x: T, _ y: T.Type) { |
| _ = #selector(x.another) |
| _ = #selector(y.create) |
| } |
| |
| @objc func doesntUseGenericParam2(_ x: T, _ y: T.Type) { |
| let a = x.another() |
| _ = a.another() |
| _ = x.another().another() |
| |
| _ = type(of: x).create().another() |
| _ = type(of: x).init(noise: x).another() |
| _ = y.create().another() |
| _ = y.init(noise: x).another() |
| _ = y.init(noise: x.another()).another() |
| x.eat(a) |
| } |
| |
| @objc func doesntUseGenericParam3(_ x: T, _ y: T.Type) { |
| let sup: Animal = x |
| sup.eat(x) |
| _ = x.buddy |
| _ = x[0] |
| x[0] = x |
| } |
| |
| @objc func doesntUseGenericParam4(_ x: T, _ y: T.Type) { |
| _ = type(of: x).apexPredator.another() |
| type(of: x).apexPredator = x |
| |
| _ = y.apexPredator.another() |
| |
| y.apexPredator = x |
| } |
| |
| @objc func doesntUseGenericParam5(y: T) { |
| var x = y |
| x = y |
| _ = x |
| } |
| @objc func doesntUseGenericParam6(y: T?) { |
| var x = y |
| x = y |
| _ = x |
| } |
| |
| // Doesn't use 'T', since dynamic casting to an ObjC generic class doesn't |
| // check its generic parameters |
| @objc func doesntUseGenericParam7() { |
| _ = (self as AnyObject) as! GenericClass<T> |
| _ = (self as AnyObject) as? GenericClass<T> |
| _ = (self as AnyObject) as! AnimalContainer<T> |
| _ = (self as AnyObject) as? AnimalContainer<T> |
| _ = (self as AnyObject) is AnimalContainer<T> |
| _ = (self as AnyObject) is AnimalContainer<T> |
| } |
| |
| // Dynamic casting to the generic parameter would require its generic params, |
| // though |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamZ1() { |
| _ = (self as AnyObject) as! T //expected-note{{here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamZ2() { |
| _ = (self as AnyObject) as? T //expected-note{{here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamZ3() { |
| _ = (self as AnyObject) is T //expected-note{{here}} |
| } |
| |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamA(_ x: T) { |
| _ = T(noise: x) // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamB() { |
| _ = T.create() // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamC() { |
| _ = T.apexPredator // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamD(_ x: T) { |
| T.apexPredator = x // expected-note{{used here}} |
| } |
| |
| // rdar://problem/27796375 -- allocating init entry points for ObjC |
| // initializers are generated as true Swift generics, so reify type |
| // parameters. |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| func usesGenericParamE(_ x: T) { |
| _ = GenericClass(thing: x) // expected-note{{used here}} |
| } |
| |
| @objc func checkThatMethodsAreObjC() { |
| _ = #selector(AnimalContainer.doesntUseGenericParam1) |
| _ = #selector(AnimalContainer.doesntUseGenericParam2) |
| _ = #selector(AnimalContainer.doesntUseGenericParam3) |
| _ = #selector(AnimalContainer.doesntUseGenericParam4) |
| } |
| |
| // rdar://problem/26283886 |
| @objc func funcWithWrongArgType(x: NSObject) {} |
| |
| @objc func crashWithInvalidSubscript(x: NSArray) { |
| _ = funcWithWrongArgType(x: x[12]) |
| // expected-error@-1{{cannot convert value of type 'Any' to expected argument type 'NSObject'}} |
| } |
| } |
| |
| extension PettableContainer { |
| @objc func doesntUseGenericParam(_ x: T, _ y: T.Type) { |
| // TODO: rdar://problem/27796375--allocating entry points are emitted as |
| // true generics. |
| // _ = type(of: x).init(fur: x).other() |
| _ = type(of: x).adopt().other() |
| // _ = y.init(fur: x).other() |
| _ = y.adopt().other() |
| x.pet() |
| x.pet(with: x) |
| } |
| |
| // TODO: rdar://problem/27796375--allocating entry points are emitted as |
| // true generics. |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamZ1(_ x: T, _ y: T.Type) { |
| _ = type(of: x).init(fur: x).other() // expected-note{{used here}} |
| } |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamZ2(_ x: T, _ y: T.Type) { |
| _ = y.init(fur: x).other() // expected-note{{used here}} |
| } |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamA(_ x: T) { |
| _ = T(fur: x) // expected-note{{used here}} |
| } |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamB(_ x: T) { |
| _ = T.adopt() // expected-note{{used here}} |
| } |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamC(_ x: T) { |
| _ = T.needingMostPets // expected-note{{used here}} |
| } |
| |
| // expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}} |
| @objc func usesGenericParamD(_ x: T) { |
| T.needingMostPets = x // expected-note{{used here}} |
| } |
| |
| @objc func checkThatMethodsAreObjC() { |
| _ = #selector(PettableContainer.doesntUseGenericParam) |
| } |
| } |
| |
| // expected-error@+1{{inheritance from a generic Objective-C class 'GenericClass' must bind type parameters of 'GenericClass' to specific concrete types}} |
| class SwiftGenericSubclassA<X: AnyObject>: GenericClass<X> {} |
| // expected-error@+1{{inheritance from a generic Objective-C class 'GenericClass' must bind type parameters of 'GenericClass' to specific concrete types}} |
| class SwiftGenericSubclassB<X: AnyObject>: GenericClass<GenericClass<X>> {} |
| // expected-error@+1{{inheritance from a generic Objective-C class 'GenericClass' must bind type parameters of 'GenericClass' to specific concrete types}} |
| class SwiftGenericSubclassC<X: NSCopying>: GenericClass<X> {} |
| |
| class SwiftConcreteSubclassA: GenericClass<AnyObject> { |
| override init(thing: AnyObject) { } |
| override func thing() -> AnyObject? { } |
| override func count() -> Int32 { } |
| override class func classThing() -> AnyObject? { } |
| override func arrayOfThings() -> [AnyObject] {} |
| } |
| class SwiftConcreteSubclassB: GenericClass<NSString> { |
| override init(thing: NSString) { } |
| override func thing() -> NSString? { } |
| override func count() -> Int32 { } |
| override class func classThing() -> NSString? { } |
| override func arrayOfThings() -> [NSString] {} |
| } |
| class SwiftConcreteSubclassC<T>: GenericClass<NSString> { |
| override init(thing: NSString) { } |
| override func thing() -> NSString? { } |
| override func count() -> Int32 { } |
| override class func classThing() -> NSString? { } |
| override func arrayOfThings() -> [NSString] {} |
| } |
| |
| // FIXME: Some generic ObjC APIs rely on covariance. We don't handle this well |
| // in Swift yet, but ensure we don't emit spurious warnings when |
| // `as!` is used to force types to line up. |
| func foo(x: GenericClass<NSMutableString>) { |
| let x2 = x as! GenericClass<NSString> |
| takeGenericClass(x2) |
| takeGenericClass(unsafeBitCast(x, to: GenericClass<NSString>.self)) |
| } |
| |
| // Test type-erased bounds |
| |
| func getContainerForPanda() -> AnimalContainer<Animal> { |
| return Panda.getContainer() |
| } |
| |
| func getContainerForFungiblePanda() -> FungibleAnimalContainer<Animal & Fungible> { |
| return Panda.getFungibleContainer() |
| } |
| |
| // rdar://problem/30832766 - Infinite recursion while checking conformance |
| // to AnyObject |
| let third: Third! = Third() |
| |
| func useThird() { |
| _ = third.description |
| } |
| |
| |
| func testNonconforming(bnc: ObjCBridgeNonconforming) { |
| let _: Int = bnc.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}} |
| } |
| |
| func testHashableGenerics( |
| any: ObjCBridgeGeneric<ElementConcrete>, |
| constrained: ObjCBridgeGenericConstrained<ElementConcrete>, |
| insufficient: ObjCBridgeGenericInsufficientlyConstrained<ElementConcrete>, |
| extra: ObjCBridgeGenericConstrainedExtra<ElementConcrete>) { |
| let _: Int = any.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}} |
| let _: Int = constrained.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}} |
| let _: Int = insufficient.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}} |
| let _: Int = extra.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}} |
| } |