// RUN: %target-parse-verify-swift // ---------------------------------------------------------------------------- // Using protocol requirements from inside protocol extensions // ---------------------------------------------------------------------------- protocol P1 { func reqP1a() -> Bool } extension P1 { final func extP1a() -> Bool { return !reqP1a() } final var extP1b: Bool { return self.reqP1a() } final var extP1c: Bool { return extP1b && self.extP1a() } } protocol P2 { associatedtype AssocP2 : P1 func reqP2a() -> AssocP2 } extension P2 { final func extP2a() -> AssocP2? { return reqP2a() } final func extP2b() { self.reqP2a().reqP1a() } final func extP2c() -> Self.AssocP2 { return extP2a()! } } protocol P3 { associatedtype AssocP3 : P2 func reqP3a() -> AssocP3 } extension P3 { final func extP3a() -> AssocP3.AssocP2 { return reqP3a().reqP2a() } } protocol P4 { associatedtype AssocP4 func reqP4a() -> AssocP4 } // ---------------------------------------------------------------------------- // Using generics from inside protocol extensions // ---------------------------------------------------------------------------- func acceptsP1(t: T) { } extension P1 { final func extP1d() { acceptsP1(self) } } func acceptsP2(t: T) { } extension P2 { final func extP2acceptsP1() { acceptsP1(reqP2a()) } final func extP2acceptsP2() { acceptsP2(self) } } // Use of 'Self' as a return type within a protocol extension. protocol SelfP1 { associatedtype AssocType } protocol SelfP2 { } func acceptSelfP1(t: T, _ u: U) -> T { return t } extension SelfP1 { final func tryAcceptSelfP1(z: Z) -> Self { return acceptSelfP1(self, z) } } // ---------------------------------------------------------------------------- // Initializers in protocol extensions // ---------------------------------------------------------------------------- protocol InitP1 { init(string: String) } extension InitP1 { init(int: Int) { self.init(string: "integer") } } struct InitS1 : InitP1 { init(string: String) { } } class InitC1 : InitP1 { required init(string: String) { } } func testInitP1() { var is1 = InitS1(int: 5) is1 = InitS1(string: "blah") // check type _ = is1 var ic1 = InitC1(int: 5) ic1 = InitC1(string: "blah") // check type _ = ic1 } // ---------------------------------------------------------------------------- // Subscript in protocol extensions // ---------------------------------------------------------------------------- protocol SubscriptP1 { func readAt(i: Int) -> String func writeAt(i: Int, string: String) } extension SubscriptP1 { final subscript(i: Int) -> String { get { return readAt(i) } set(newValue) { writeAt(i, string: newValue) } } } struct SubscriptS1 : SubscriptP1 { func readAt(i: Int) -> String { return "hello" } func writeAt(i: Int, string: String) { } } struct SubscriptC1 : SubscriptP1 { func readAt(i: Int) -> String { return "hello" } func writeAt(i: Int, string: String) { } } func testSubscriptP1(ss1: SubscriptS1, sc1: SubscriptC1, i: Int, s: String) { var ss1 = ss1 var sc1 = sc1 _ = ss1[i] ss1[i] = s _ = sc1[i] sc1[i] = s } // ---------------------------------------------------------------------------- // Using protocol extensions on types that conform to the protocols. // ---------------------------------------------------------------------------- struct S1 : P1 { func reqP1a() -> Bool { return true } func once() -> Bool { return extP1a() && extP1b } } func useS1(s1: S1) -> Bool { s1.reqP1a() return s1.extP1a() && s1.extP1b } extension S1 { func twice() -> Bool { return extP1a() && extP1b } } // ---------------------------------------------------------------------------- // Protocol extensions with additional requirements // ---------------------------------------------------------------------------- extension P4 where Self.AssocP4 : P1 { final func extP4a() { // expected-note 2 {{found this candidate}} acceptsP1(reqP4a()) } } struct S4aHelper { } struct S4bHelper : P1 { func reqP1a() -> Bool { return true } } struct S4a : P4 { func reqP4a() -> S4aHelper { return S4aHelper() } } struct S4b : P4 { func reqP4a() -> S4bHelper { return S4bHelper() } } struct S4c : P4 { func reqP4a() -> Int { return 0 } } struct S4d : P4 { func reqP4a() -> Bool { return false } } extension P4 where Self.AssocP4 == Int { final func extP4Int() { } } extension P4 where Self.AssocP4 == Bool { final func extP4a() -> Bool { return reqP4a() } // expected-note 2 {{found this candidate}} } func testP4(s4a: S4a, s4b: S4b, s4c: S4c, s4d: S4d) { s4a.extP4a() // expected-error{{ambiguous reference to member 'extP4a()'}} s4b.extP4a() // ok s4c.extP4a() // expected-error{{ambiguous reference to member 'extP4a()'}} s4c.extP4Int() // okay var b1 = s4d.extP4a() // okay, "Bool" version b1 = true // checks type above s4d.extP4Int() // expected-error{{'Int' is not convertible to 'AssocP4' (aka 'Bool')}} _ = b1 } // ---------------------------------------------------------------------------- // Using protocol extensions to satisfy requirements // ---------------------------------------------------------------------------- protocol P5 { func reqP5a() } // extension of P5 provides a witness for P6 extension P5 { final func reqP6a() { reqP5a() } } protocol P6 { func reqP6a() } // S6a uses P5.reqP6a struct S6a : P5 { func reqP5a() { } } extension S6a : P6 { } // S6b uses P5.reqP6a struct S6b : P5, P6 { func reqP5a() { } } // S6c uses P5.reqP6a struct S6c : P6 { } extension S6c : P5 { func reqP5a() { } } // S6d does not use P5.reqP6a struct S6d : P6 { func reqP6a() { } } extension S6d : P5 { func reqP5a() { } } protocol P7 { associatedtype P7Assoc func getP7Assoc() -> P7Assoc } struct P7FromP8 { } protocol P8 { associatedtype P8Assoc func getP8Assoc() -> P8Assoc } // extension of P8 provides conformance to P7Assoc extension P8 { final func getP7Assoc() -> P7FromP8 { return P7FromP8() } } // Okay, P7 requirements satisfied by P8 struct P8a : P8, P7 { func getP8Assoc() -> Bool { return true } } func testP8a(p8a: P8a) { var p7 = p8a.getP7Assoc() p7 = P7FromP8() // okay, check type of above _ = p7 } // Okay, P7 requirements explicitly specified struct P8b : P8, P7 { func getP7Assoc() -> Int { return 5 } func getP8Assoc() -> Bool { return true } } func testP8b(p8b: P8b) { var p7 = p8b.getP7Assoc() p7 = 17 // check type of above _ = p7 } protocol PConforms1 { } extension PConforms1 { final func pc2() { } // expected-note{{candidate exactly matches}} } protocol PConforms2 : PConforms1, MakePC2Ambiguous { func pc2() // expected-note{{multiple matching functions named 'pc2()' with type '() -> ()'}} } protocol MakePC2Ambiguous { } extension MakePC2Ambiguous { final func pc2() { } // expected-note{{candidate exactly matches}} } struct SConforms2a : PConforms2 { } // expected-error{{type 'SConforms2a' does not conform to protocol 'PConforms2'}} struct SConforms2b : PConforms2 { func pc2() { } } // Satisfying requirements via protocol extensions for fun and profit protocol _MySeq { } protocol MySeq : _MySeq { associatedtype Generator : IteratorProtocol func myGenerate() -> Generator } protocol _MyCollection : _MySeq { associatedtype Index : ForwardIndex var myStartIndex : Index { get } var myEndIndex : Index { get } associatedtype _Element subscript (i: Index) -> _Element { get } } protocol MyCollection : _MyCollection { } struct MyIndexedIterator : IteratorProtocol { var container: C var index: C.Index mutating func next() -> C._Element? { if index == container.myEndIndex { return nil } let result = container[index] index = index.successor() return result } } struct OtherIndexedIterator : IteratorProtocol { var container: C var index: C.Index mutating func next() -> C._Element? { if index == container.myEndIndex { return nil } let result = container[index] index = index.successor() return result } } extension _MyCollection { final func myGenerate() -> MyIndexedIterator { return MyIndexedIterator(container: self, index: self.myEndIndex) } } struct SomeCollection1 : MyCollection { var myStartIndex: Int { return 0 } var myEndIndex: Int { return 10 } subscript (i: Int) -> String { return "blah" } } struct SomeCollection2 : MyCollection { var myStartIndex: Int { return 0 } var myEndIndex: Int { return 10 } subscript (i: Int) -> String { return "blah" } func myGenerate() -> OtherIndexedIterator { return OtherIndexedIterator(container: self, index: self.myEndIndex) } } func testSomeCollections(sc1: SomeCollection1, sc2: SomeCollection2) { var mig = sc1.myGenerate() mig = MyIndexedIterator(container: sc1, index: sc1.myStartIndex) _ = mig var ig = sc2.myGenerate() ig = MyIndexedIterator(container: sc2, index: sc2.myStartIndex) // expected-error{{cannot invoke initializer for type 'MyIndexedIterator<_>' with an argument list of type '(container: SomeCollection2, index: Int)'}} // expected-note @-1 {{expected an argument list of type '(container: C, index: C.Index)'}} _ = ig } public protocol PConforms3 {} extension PConforms3 { final public var z: Int { return 0 } } public protocol PConforms4 : PConforms3 { var z: Int { get } } struct PConforms4Impl : PConforms4 {} let pc4z = PConforms4Impl().z // rdar://problem/20608438 protocol PConforms5 { func f() -> Int } protocol PConforms6 : PConforms5 {} extension PConforms6 { final func f() -> Int { return 42 } } func test(x: T) -> Int { return x.f() } struct PConforms6Impl : PConforms6 { } // Extensions of a protocol that directly satisfy requirements (i.e., // default implementations hack N+1). protocol PConforms7 { func method() var property: Int { get } subscript (i: Int) -> Int { get } } extension PConforms7 { final func method() { } final var property: Int { return 5 } final subscript (i: Int) -> Int { return i } } struct SConforms7a : PConforms7 { } protocol PConforms8 { associatedtype Assoc func method() -> Assoc var property: Assoc { get } subscript (i: Assoc) -> Assoc { get } } extension PConforms8 { final func method() -> Int { return 5 } final var property: Int { return 5 } final subscript (i: Int) -> Int { return i } } struct SConforms8a : PConforms8 { } struct SConforms8b : PConforms8 { func method() -> String { return "" } var property: String { return "" } subscript (i: String) -> String { return i } } func testSConforms8b() { let s: SConforms8b.Assoc = "hello" _ = s } struct SConforms8c : PConforms8 { func method() -> String { return "" } } func testSConforms8c() { let s: SConforms8c.Assoc = "hello" // expected-error{{cannot convert value of type 'String' to specified type 'Assoc' (aka 'Int')}} _ = s let i: SConforms8c.Assoc = 5 _ = i } protocol DefaultInitializable { init() } extension String : DefaultInitializable { } extension Int : DefaultInitializable { } protocol PConforms9 { associatedtype Assoc : DefaultInitializable // expected-note{{protocol requires nested type 'Assoc'}} func method() -> Assoc var property: Assoc { get } subscript (i: Assoc) -> Assoc { get } } extension PConforms9 { final func method() -> Self.Assoc { return Assoc() } final var property: Self.Assoc { return Assoc() } final subscript (i: Self.Assoc) -> Self.Assoc { return Assoc() } } struct SConforms9a : PConforms9 { // expected-error{{type 'SConforms9a' does not conform to protocol 'PConforms9'}} } struct SConforms9b : PConforms9 { typealias Assoc = Int } func testSConforms9b(s9b: SConforms9b) { var p = s9b.property p = 5 _ = p } struct SConforms9c : PConforms9 { typealias Assoc = String } func testSConforms9c(s9c: SConforms9c) { var p = s9c.property p = "hello" _ = p } struct SConforms9d : PConforms9 { func method() -> Int { return 5 } } func testSConforms9d(s9d: SConforms9d) { var p = s9d.property p = 6 _ = p } protocol PConforms10 {} extension PConforms10 { final func f() {} } protocol PConforms11 { func f() } struct SConforms11 : PConforms10, PConforms11 {} // ---------------------------------------------------------------------------- // Typealiases in protocol extensions. // ---------------------------------------------------------------------------- // Basic support protocol PTypeAlias1 { associatedtype AssocType1 } extension PTypeAlias1 { typealias ArrayOfAssocType1 = [AssocType1] } struct STypeAlias1a: PTypeAlias1 { typealias AssocType1 = Int } struct STypeAlias1b: PTypeAlias1 { typealias AssocType1 = T } func testPTypeAlias1() { var a: STypeAlias1a.ArrayOfAssocType1 = [] a.append(1) var b: STypeAlias1b.ArrayOfAssocType1 = [] b.append("hello") } // Defaulted implementations to satisfy a requirement. struct TypeAliasHelper { } protocol PTypeAliasSuper2 { } extension PTypeAliasSuper2 { final func foo() -> TypeAliasHelper { return TypeAliasHelper() } } protocol PTypeAliasSub2 : PTypeAliasSuper2 { associatedtype Helper func foo() -> Helper } struct STypeAliasSub2a : PTypeAliasSub2 { } struct STypeAliasSub2b : PTypeAliasSub2 { } // ---------------------------------------------------------------------------- // Partial ordering of protocol extension members // ---------------------------------------------------------------------------- // Partial ordering between members of protocol extensions and members // of concrete types. struct S1b : P1 { func reqP1a() -> Bool { return true } func extP1a() -> Int { return 0 } } func useS1b(s1b: S1b) { var x = s1b.extP1a() // uses S1b.extP1a due to partial ordering x = 5 // checks that "x" deduced to "Int" above _ = x var _: Bool = s1b.extP1a() // still uses P1.ext1Pa due to type annotation } // Partial ordering between members of protocol extensions for // different protocols. protocol PInherit1 { } protocol PInherit2 : PInherit1 { } protocol PInherit3 : PInherit2 { } protocol PInherit4 : PInherit2 { } extension PInherit1 { final func order1() -> Int { return 0 } } extension PInherit2 { final func order1() -> Bool { return true } } extension PInherit3 { final func order1() -> Double { return 1.0 } } extension PInherit4 { final func order1() -> String { return "hello" } } struct SInherit1 : PInherit1 { } struct SInherit2 : PInherit2 { } struct SInherit3 : PInherit3 { } struct SInherit4 : PInherit4 { } func testPInherit(si2 : SInherit2, si3: SInherit3, si4: SInherit4) { var b1 = si2.order1() // PInherit2.order1 b1 = true // check that the above returned Bool _ = b1 var d1 = si3.order1() // PInherit3.order1 d1 = 3.14159 // check that the above returned Double _ = d1 var s1 = si4.order1() // PInherit4.order1 s1 = "hello" // check that the above returned String _ = s1 // Other versions are still visible, since they may have different // types. b1 = si3.order1() // PInherit2.order1 var _: Int = si3.order1() // PInherit1.order1 } protocol PConstrained1 { associatedtype AssocTypePC1 } extension PConstrained1 { final func pc1() -> Int { return 0 } } extension PConstrained1 where AssocTypePC1 : PInherit2 { final func pc1() -> Bool { return true } } extension PConstrained1 where Self.AssocTypePC1 : PInherit3 { final func pc1() -> String { return "hello" } } struct SConstrained1 : PConstrained1 { typealias AssocTypePC1 = SInherit1 } struct SConstrained2 : PConstrained1 { typealias AssocTypePC1 = SInherit2 } struct SConstrained3 : PConstrained1 { typealias AssocTypePC1 = SInherit3 } func testPConstrained1(sc1: SConstrained1, sc2: SConstrained2, sc3: SConstrained3) { var i = sc1.pc1() // PConstrained1.pc1 i = 17 // checks type of above _ = i var b = sc2.pc1() // PConstrained1 (with PInherit2).pc1 b = true // checks type of above _ = b var s = sc3.pc1() // PConstrained1 (with PInherit3).pc1 s = "hello" // checks type of above _ = s } protocol PConstrained2 { associatedtype AssocTypePC2 } protocol PConstrained3 : PConstrained2 { } extension PConstrained2 where Self.AssocTypePC2 : PInherit1 { final func pc2() -> Bool { return true } } extension PConstrained3 { final func pc2() -> String { return "hello" } } struct SConstrained3a : PConstrained3 { typealias AssocTypePC2 = Int } struct SConstrained3b : PConstrained3 { typealias AssocTypePC2 = SInherit3 } func testSConstrained3(sc3a: SConstrained3a, sc3b: SConstrained3b) { var s = sc3a.pc2() // PConstrained3.pc2 s = "hello" _ = s sc3b.pc2() s = sc3b.pc2() var _: Bool = sc3b.pc2() } extension PConstrained3 where AssocTypePC2 : PInherit1 { } // Extending via a superclass constraint. class Superclass { func foo() { } static func bar() { } typealias Foo = Int } protocol PConstrained4 { } extension PConstrained4 where Self : Superclass { final func testFoo() -> Foo { foo() self.foo() return Foo(5) } final static func testBar() { bar() self.bar() } } protocol PConstrained5 { } protocol PConstrained6 { associatedtype Assoc func foo() } protocol PConstrained7 { } extension PConstrained6 { final var prop1: Int { return 0 } final var prop2: Int { return 0 } // expected-note{{'prop2' previously declared here}} final subscript (key: Int) -> Int { return key } final subscript (key: Double) -> Double { return key } // expected-note{{'subscript' previously declared here}} } extension PConstrained6 { final var prop2: Int { return 0 } // expected-error{{invalid redeclaration of 'prop2'}} final subscript (key: Double) -> Double { return key } // expected-error{{invalid redeclaration of 'subscript'}} } extension PConstrained6 where Assoc : PConstrained5 { final var prop1: Int { return 0 } // okay final var prop3: Int { return 0 } // expected-note{{'prop3' previously declared here}} final subscript (key: Int) -> Int { return key } // ok final subscript (key: String) -> String { return key } // expected-note{{'subscript' previously declared here}} final func foo() { } // expected-note{{'foo()' previously declared here}} } extension PConstrained6 where Assoc : PConstrained5 { final var prop3: Int { return 0 } // expected-error{{invalid redeclaration of 'prop3'}} final subscript (key: String) -> String { return key } // expected-error{{invalid redeclaration of 'subscript'}} final func foo() { } // expected-error{{invalid redeclaration of 'foo()'}} } extension PConstrained6 where Assoc : PConstrained7 { final var prop1: Int { return 0 } // okay final subscript (key: Int) -> Int { return key } // okay final func foo() { } // okay } extension PConstrained6 where Assoc == Int { final var prop4: Int { return 0 } final subscript (key: Character) -> Character { return key } final func foo() { } // okay } extension PConstrained6 where Assoc == Double { final var prop4: Int { return 0 } // okay final subscript (key: Character) -> Character { return key } // okay final func foo() { } // okay } // Interaction between RawRepresentable and protocol extensions. public protocol ReallyRaw : RawRepresentable { } public extension ReallyRaw where RawValue: SignedInteger { public init?(rawValue: RawValue) { self = unsafeBitCast(rawValue, to: Self.self) } } enum Foo : Int, ReallyRaw { case a = 0 } // ---------------------------------------------------------------------------- // Semantic restrictions // ---------------------------------------------------------------------------- // Extension cannot have an inheritance clause. protocol BadProto1 { } protocol BadProto2 { } extension BadProto1 : BadProto2 { } // expected-error{{extension of protocol 'BadProto1' cannot have an inheritance clause}} extension BadProto2 { struct S { } // expected-error{{type 'S' cannot be defined within a protocol extension}} class C { } // expected-error{{type 'C' cannot be defined within a protocol extension}} enum E { } // expected-error{{type 'E' cannot be defined within a protocol extension}} } extension BadProto1 { func foo() { } var prop: Int { return 0 } subscript (i: Int) -> String { return "hello" } } protocol BadProto3 { } typealias BadProto4 = BadProto3 extension BadProto4 { } // expected-error{{protocol 'BadProto3' in the module being compiled cannot be extended via a typealias}}{{11-20=BadProto3}} typealias RawRepresentableAlias = RawRepresentable extension RawRepresentableAlias { } // okay extension AnyObject { } // expected-error{{'AnyObject' protocol cannot be extended}} // Members of protocol extensions cannot be overridden. // rdar://problem/21075287 class BadClass1 : BadProto1 { func foo() { } override var prop: Int { return 5 } // expected-error{{property does not override any property from its superclass}} }