| // RUN: %target-typecheck-verify-swift -enable-objc-interop |
| |
| // ----------------------------------------------------------------------- |
| // Declaring optional requirements |
| // ----------------------------------------------------------------------- |
| @objc class ObjCClass { } |
| |
| @objc protocol P1 { |
| @objc optional func method(_ x: Int) // expected-note {{requirement 'method' declared here}} |
| |
| @objc optional var prop: Int { get } |
| |
| @objc optional subscript (i: Int) -> ObjCClass? { get } |
| } |
| |
| @objc protocol P2 { |
| @objc(objcMethodWithInt:) |
| optional func method(y: Int) // expected-note 1{{requirement 'method(y:)' declared here}} |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Providing witnesses for optional requirements |
| // ----------------------------------------------------------------------- |
| |
| // One does not have provide a witness for an optional requirement |
| class C1 : P1 { } |
| |
| // ... but it's okay to do so. |
| class C2 : P1 { |
| @objc func method(_ x: Int) { } |
| |
| @objc var prop: Int = 0 |
| |
| @objc subscript (i: Int) -> ObjCClass? { |
| get { |
| return nil |
| } |
| set {} |
| } |
| } |
| |
| class C3 : P1 { |
| func method(_ x: Int) { } |
| |
| var prop: Int = 0 |
| |
| subscript (i: Int) -> ObjCClass? { |
| get { |
| return nil |
| } |
| set {} |
| } |
| } |
| |
| class C4 { } |
| |
| extension C4 : P1 { |
| func method(_ x: Int) { } |
| |
| var prop: Int { return 5 } |
| |
| subscript (i: Int) -> ObjCClass? { |
| get { |
| return nil |
| } |
| set {} |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Okay to match via extensions. |
| // ----------------------------------------------------------------------- |
| |
| class C5 : P1 { } |
| |
| extension C5 { |
| func method(_ x: Int) { } |
| |
| var prop: Int { return 5 } |
| |
| subscript (i: Int) -> ObjCClass? { |
| get { |
| return nil |
| } |
| set {} |
| } |
| } |
| |
| // Note: @nonobjc suppresses witness match. |
| class C6 { } |
| |
| extension C6 : P1 { |
| @nonobjc func method(_ x: Int) { } |
| |
| @nonobjc var prop: Int { return 5 } |
| |
| @nonobjc subscript (i: Int) -> ObjCClass? { |
| get { |
| return nil |
| } |
| set {} |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // "Near" matches. |
| // ----------------------------------------------------------------------- |
| |
| // Note: warn about selector matches where the Swift names didn't match. |
| @objc class C7 : P1 { // expected-note{{class 'C7' declares conformance to protocol 'P1' here}} |
| @objc(method:) func otherMethod(x: Int) { } // expected-error{{Objective-C method 'method:' provided by method 'otherMethod(x:)' conflicts with optional requirement method 'method' in protocol 'P1'}} |
| // expected-note@-1{{rename method to match requirement 'method'}}{{23-34=method}}{{35-35=_ }} |
| } |
| |
| @objc class C8 : P2 { // expected-note{{class 'C8' declares conformance to protocol 'P2' here}} |
| @objc func objcMethod(int x: Int) { } // expected-error{{Objective-C method 'objcMethodWithInt:' provided by method 'objcMethod(int:)' conflicts with optional requirement method 'method(y:)' in protocol 'P2'}} |
| // expected-note@-1{{rename method to match requirement 'method(y:)'}}{{14-24=method}}{{25-28=y}}{{none}} |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| // Using optional requirements |
| // ----------------------------------------------------------------------- |
| |
| // Optional method references in generics. |
| func optionalMethodGeneric<T : P1>(_ t: T) { |
| // Infers a value of optional type. |
| var methodRef = t.method |
| |
| // Make sure it's an optional |
| methodRef = .none |
| |
| // ... and that we can call it. |
| methodRef!(5) |
| } |
| |
| // Optional property references in generics. |
| func optionalPropertyGeneric<T : P1>(_ t: T) { |
| // Infers a value of optional type. |
| var propertyRef = t.prop |
| |
| // Make sure it's an optional |
| propertyRef = .none |
| |
| // ... and that we can use it |
| let i = propertyRef! |
| _ = i as Int |
| } |
| |
| // Optional subscript references in generics. |
| func optionalSubscriptGeneric<T : P1>(_ t: T) { |
| // Infers a value of optional type. |
| var subscriptRef = t[5] |
| |
| // Make sure it's an optional |
| subscriptRef = .none |
| |
| // ... and that we can use it |
| let i = subscriptRef! |
| _ = i as ObjCClass? |
| } |
| |
| // Optional method references in existentials. |
| func optionalMethodExistential(_ t: P1) { |
| // Infers a value of optional type. |
| var methodRef = t.method |
| |
| // Make sure it's an optional |
| methodRef = .none |
| |
| // ... and that we can call it. |
| methodRef!(5) |
| } |
| |
| // Optional property references in existentials. |
| func optionalPropertyExistential(_ t: P1) { |
| // Infers a value of optional type. |
| var propertyRef = t.prop |
| |
| // Make sure it's an optional |
| propertyRef = .none |
| |
| // ... and that we can use it |
| let i = propertyRef! |
| _ = i as Int |
| } |
| |
| // Optional subscript references in existentials. |
| func optionalSubscriptExistential(_ t: P1) { |
| // Infers a value of optional type. |
| var subscriptRef = t[5] |
| |
| // Make sure it's an optional |
| subscriptRef = .none |
| |
| // ... and that we can use it |
| let i = subscriptRef! |
| _ = i as ObjCClass? |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Restrictions on the application of optional |
| // ----------------------------------------------------------------------- |
| |
| // optional cannot be used on non-protocol declarations |
| optional var optError: Int = 10 // expected-error{{'optional' can only be applied to protocol members}} {{1-10=}} |
| |
| optional struct optErrorStruct { // expected-error{{'optional' modifier cannot be applied to this declaration}} {{1-10=}} |
| optional var ivar: Int // expected-error{{'optional' can only be applied to protocol members}} {{3-12=}} |
| optional func foo() { } // expected-error{{'optional' can only be applied to protocol members}} {{3-12=}} |
| } |
| |
| optional class optErrorClass { // expected-error{{'optional' modifier cannot be applied to this declaration}} {{1-10=}} |
| optional var ivar: Int = 0 // expected-error{{'optional' can only be applied to protocol members}} {{3-12=}} |
| optional func foo() { } // expected-error{{'optional' can only be applied to protocol members}} {{3-12=}} |
| } |
| |
| protocol optErrorProtocol { |
| optional func foo(_ x: Int) // expected-error{{'optional' can only be applied to members of an @objc protocol}} |
| } |
| |
| @objc protocol optObjcAttributeProtocol { |
| optional func foo(_ x: Int) // expected-error{{'optional' requirements are an Objective-C compatibility feature; add '@objc'}}{{3-3=@objc }} |
| optional var bar: Int { get } // expected-error{{'optional' requirements are an Objective-C compatibility feature; add '@objc'}}{{3-3=@objc }} |
| optional associatedtype Assoc // expected-error{{'optional' modifier cannot be applied to this declaration}} {{3-12=}} |
| // expected-error@-1 {{associated type 'Assoc' cannot be declared inside '@objc' protocol 'optObjcAttributeProtocol'}} |
| } |
| |
| @objc protocol optionalInitProto { |
| @objc optional init() // expected-error{{'optional' cannot be applied to an initializer}} |
| } |