// RUN: %target-typecheck-verify-swift // RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s protocol P1 { func p1() } protocol P2 : P1 { } struct X1 { func getT() -> T { } } class X2 { func getT() -> T { } } class X3 { } struct X4 { func getT() -> T { } } struct X5 { } // Infer protocol requirements from the parameter type of a generic function. func inferFromParameterType(_ x: X1) { x.getT().p1() } // Infer protocol requirements from the return type of a generic function. func inferFromReturnType(_ x: T) -> X1 { _ = 0 x.p1() } // Infer protocol requirements from the superclass of a generic parameter. func inferFromSuperclass>(_ t: T, u: U) -> T { _ = 0 t.p1() } // Infer protocol requirements from the parameter type of a constructor. struct InferFromConstructor { init (x : X1) { x.getT().p1() } } // Don't infer requirements for outer generic parameters. class Fox : P1 { func p1() {} } class Box { func unpack(_ x: X1) {} func unpackFail(_ X: X1) { } // expected-error{{type 'U' does not conform to protocol 'P1'}} } // ---------------------------------------------------------------------------- // Superclass requirements // ---------------------------------------------------------------------------- // Compute meet of two superclass requirements correctly. class Carnivora {} class Canidae : Carnivora {} struct U {} struct V {} // CHECK-LABEL: .inferSuperclassRequirement1@ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae> func inferSuperclassRequirement1( _ v: V) {} // CHECK-LABEL: .inferSuperclassRequirement2@ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae> func inferSuperclassRequirement2(_ v: U) {} // ---------------------------------------------------------------------------- // Same-type requirements // ---------------------------------------------------------------------------- protocol P3 { associatedtype P3Assoc : P2 // expected-note{{declared here}} } protocol P4 { associatedtype P4Assoc : P1 } protocol PCommonAssoc1 { associatedtype CommonAssoc } protocol PCommonAssoc2 { associatedtype CommonAssoc } protocol PAssoc { associatedtype Assoc } struct Model_P3_P4_Eq where T.P3Assoc == U.P4Assoc {} func inferSameType1(_ x: Model_P3_P4_Eq) { let u: U.P4Assoc? = nil let _: T.P3Assoc? = u! } func inferSameType2(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {} func inferSameType3(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 { } protocol P5 { associatedtype Element } protocol P6 { associatedtype AssocP6 : P5 } protocol P7 : P6 { associatedtype AssocP7: P6 } // CHECK-LABEL: P7@ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P7, τ_0_0.[P6]AssocP6.[P5]Element : P6, τ_0_0.[P6]AssocP6.[P5]Element == τ_0_0.[P7]AssocP7.[P6]AssocP6.[P5]Element> extension P7 where AssocP6.Element : P6, AssocP7.AssocP6.Element : P6, AssocP6.Element == AssocP7.AssocP6.Element { func nestedSameType1() { } } protocol P8 { associatedtype A associatedtype B } protocol P9 : P8 { associatedtype A associatedtype B } protocol P10 { associatedtype A associatedtype C } // CHECK-LABEL: sameTypeConcrete1@ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.[P10]A == X3, τ_0_0.[P8]B == Int, τ_0_0.[P10]C == Int> func sameTypeConcrete1(_: T) where T.A == X3, T.C == T.B, T.C == Int { } // CHECK-LABEL: sameTypeConcrete2@ // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P10, τ_0_0 : P9, τ_0_0.[P8]B == X3, τ_0_0.[P10]C == X3> func sameTypeConcrete2(_: T) where T.B : X3, T.C == T.B, T.C == X3 { } // Note: a standard-library-based stress test to make sure we don't inject // any additional requirements. // CHECK-LABEL: RangeReplaceableCollection // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.[Collection]SubSequence == Slice<τ_0_0>> extension RangeReplaceableCollection where Self: MutableCollection, Self.SubSequence == Slice { func f() { } } // CHECK-LABEL: X14.recursiveConcreteSameType // CHECK: Generic signature: > // CHECK-NEXT: Canonical generic signature: <τ_0_0, τ_1_0 where τ_0_0 == Range> struct X14 where T.Iterator == IndexingIterator { func recursiveConcreteSameType(_: V) where T == Range { } } // rdar://problem/30478915 protocol P11 { associatedtype A } protocol P12 { associatedtype B: P11 } struct X6 { } struct X7 : P11 { typealias A = X6 } struct X8 : P12 { typealias B = X7 } struct X9 where T.B == U.B { // CHECK-LABEL: X9.upperSameTypeConstraint // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_0 == X8, τ_0_1 : P12, τ_0_1.[P12]B == X7> func upperSameTypeConstraint(_: V) where T == X8 { } } protocol P13 { associatedtype C: P11 } struct X10: P11, P12 { typealias A = X10 typealias B = X10 } struct X11 where T.B == U.B.A { // CHECK-LABEL: X11.upperSameTypeConstraint // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_0 : P12, τ_0_1 == X10, τ_0_0.[P12]B == X10> func upperSameTypeConstraint(_: V) where U == X10 { } } protocol P16 { associatedtype A } struct X15 { } struct X16 : P16 { typealias A = (X, Y) } // CHECK-LABEL: .X17.bar@ // CHECK: Generic signature: , T == X3, U == X15> struct X17 where S.A == (T, U) { func bar(_: V) where S == X16 { } } // Same-type constraints that are self-derived via a parent need to be // suppressed in the resulting signature. protocol P17 { } protocol P18 { associatedtype A: P17 } struct X18: P18, P17 { typealias A = X18 } // CHECK-LABEL: .X19.foo@ // CHECK: Generic signature: struct X19 where T == T.A { func foo(_: U) where T == X18 { } } // rdar://problem/31520386 protocol P20 { } struct X20 { } // CHECK-LABEL: .X21.f@ // CHECK: Generic signature: > // CHECK: Canonical generic signature: <τ_0_0, τ_0_1, τ_1_0 where τ_0_0 : P20, τ_0_1 == X20<τ_0_0>> struct X21 { func f(_: V) where U == X20 { } } struct X22 { func g(_: V) where T: P20, U == X20 { } } // CHECK: .P22@ // CHECK-NEXT: Requirement signature: , Self.[P22]B : P20> protocol P22 { associatedtype A associatedtype B: P20 where A == X20 } // CHECK: .P23@ // CHECK-NEXT: Requirement signature: , Self.[P23]B : P20> protocol P23 { associatedtype A associatedtype B: P20 where A == X20 } protocol P24 { associatedtype C: P20 } struct X24 : P24 { typealias C = T } protocol P25c { associatedtype A: P24 associatedtype B where A == X // expected-error{{cannot find type 'X' in scope}} } protocol P25d { associatedtype A associatedtype B where A == X24 // expected-error{{type 'Self.B' does not conform to protocol 'P20'}} } // ---------------------------------------------------------------------------- // Inference of associated type relationships within a protocol hierarchy // ---------------------------------------------------------------------------- struct X28 : P2 { func p1() { } } // CHECK-LABEL: .P28@ // CHECK: Requirement signature: protocol P28: P3 { typealias P3Assoc = X28 // expected-warning{{typealias overriding associated type}} } // ---------------------------------------------------------------------------- // Inference of associated types by name match // ---------------------------------------------------------------------------- protocol P29 { associatedtype X } protocol P30 { associatedtype X } protocol P31 { } // CHECK-LABEL: .sameTypeNameMatch1@ // CHECK: Generic signature: func sameTypeNameMatch1(_: T) where T.X: P31 { } // ---------------------------------------------------------------------------- // Infer requirements from conditional conformances // ---------------------------------------------------------------------------- protocol P32 {} protocol P33 { associatedtype A: P32 } protocol P34 {} struct Foo {} extension Foo: P32 where T: P34 {} // Inference chain: U.A: P32 => Foo: P32 => V: P34 // CHECK-LABEL: conditionalConformance1@ // CHECK: Generic signature: > // CHECK: Canonical generic signature: <τ_0_0, τ_0_1 where τ_0_0 : P33, τ_0_1 : P34, τ_0_0.[P33]A == Foo<τ_0_1>> func conditionalConformance1(_: U) where U.A == Foo {} struct Bar {} // CHECK-LABEL: conditionalConformance2@ // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P34> func conditionalConformance2(_: Bar>) {} // https://github.com/apple/swift/issues/49399 // Mentioning a nested type that is conditional should infer that requirement. protocol P35 {} protocol P36 { func foo() } struct ConditionalNested {} extension ConditionalNested where T: P35 { struct Inner {} } // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P35, τ_0_0 : P36> extension ConditionalNested.Inner: P36 where T: P36 { func foo() {} struct Inner2 {} } // CHECK-LABEL: conditionalNested1@ // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P35> func conditionalNested1(_: [ConditionalNested.Inner?]) {} // CHECK-LABEL: conditionalNested2@ // CHECK: Generic signature: // CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : P35, τ_0_0 : P36> func conditionalNested2(_: [ConditionalNested.Inner.Inner2?]) {} // // Generate typalias adds requirements that can be inferred // typealias X1WithP2 = X1 // Inferred requirement T: P2 from the typealias func testX1WithP2(_: X1WithP2) { _ = X5() // requires P2 } // Overload based on the inferred requirement. func testX1WithP2Overloading(_: X1) { _ = X5() // expected-error{{type 'T' does not conform to protocol 'P2'}} } func testX1WithP2Overloading(_: X1WithP2) { _ = X5() // requires P2 } // Extend using the inferred requirement. extension X1WithP2 { func f() { _ = X5() // okay: inferred T: P2 from generic typealias } } extension X1: P1 { func p1() { } } typealias X1WithP2Changed = X1> typealias X1WithP2MoreArgs = X1 extension X1WithP2Changed { func bad1() { _ = X5() // expected-error{{type 'T' does not conform to protocol 'P2'}} } } extension X1WithP2MoreArgs { func bad2() { _ = X5() // expected-error{{type 'T' does not conform to protocol 'P2'}} } } // Inference from protocol inheritance clauses is not allowed. typealias ExistentialP4WithP2Assoc = P4 where T.P4Assoc : P2 protocol P37 : ExistentialP4WithP2Assoc { } // expected-error@-1 {{type 'Self.P4Assoc' does not conform to protocol 'P2'}} extension P37 { func f() { _ = X5() // expected-error@-1 {{type 'Self.P4Assoc' does not conform to protocol 'P2'}} } }