// RUN: %target-typecheck-verify-swift -typecheck -verify // RUN: %target-typecheck-verify-swift -typecheck -debug-generic-signatures %s > %t.dump 2>&1 // RUN: %FileCheck %s < %t.dump protocol P1 {} protocol P2 {} protocol P3 {} protocol P4: P1 {} protocol P5: P2 {} protocol P6: P2 {} protocol Assoc { associatedtype AT } func takes_P2(_: X) {} // expected-note@-1 {{candidate requires that the types 'U' and 'V' be equivalent (requirement specified as 'U' == 'V')}} // expected-note@-2 {{requirement from conditional conformance of 'SameTypeGeneric' to 'P2'}} // expected-note@-3 {{requirement from conditional conformance of 'SubclassBad' to 'P2'}} // expected-note@-4 {{candidate requires that 'C1' inherit from 'U' (requirement specified as 'U' : 'C1')}} // expected-note@-5 {{requirement from conditional conformance of 'ClassFree' to 'P2'}} // expected-note@-6 {{candidate requires that 'C1' inherit from 'Int' (requirement specified as 'Int' : 'C1')}} func takes_P5(_: X) {} struct Free {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=Free // CHECK-NEXT: (normal_conformance type=Free protocol=P2 // CHECK-NEXT: conforms_to: T P1) extension Free: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'Free' to 'P2'}} func free_good(_: U) { takes_P2(Free()) } func free_bad(_: U) { takes_P2(Free()) // expected-error{{global function 'takes_P2' requires that 'U' conform to 'P1'}} } struct Constrained {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=Constrained // CHECK-NEXT: (normal_conformance type=Constrained protocol=P2 // CHECK-NEXT: conforms_to: T P3) extension Constrained: P2 where T: P3 {} // expected-note {{requirement from conditional conformance of 'Constrained' to 'P2'}} func constrained_good(_: U) { takes_P2(Constrained()) } func constrained_bad(_: U) { takes_P2(Constrained()) // expected-error{{global function 'takes_P2' requires that 'U' conform to 'P3'}} } struct RedundantSame {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame // CHECK-NEXT: (normal_conformance type=RedundantSame protocol=P2) extension RedundantSame: P2 where T: P1 {} struct RedundantSuper {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper // CHECK-NEXT: (normal_conformance type=RedundantSuper protocol=P2) extension RedundantSuper: P2 where T: P1 {} struct OverlappingSub {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub // CHECK-NEXT: (normal_conformance type=OverlappingSub protocol=P2 // CHECK-NEXT: conforms_to: T P4) extension OverlappingSub: P2 where T: P4 {} // expected-note {{requirement from conditional conformance of 'OverlappingSub' to 'P2'}} func overlapping_sub_good(_: U) { takes_P2(OverlappingSub()) } func overlapping_sub_bad(_: U) { takes_P2(OverlappingSub()) // expected-error{{global function 'takes_P2' requires that 'U' conform to 'P4'}} } struct SameType {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=SameType // CHECK-NEXT: (normal_conformance type=SameType protocol=P2 // CHECK-NEXT: same_type: T Int) extension SameType: P2 where T == Int {} // expected-note@-1 {{requirement from conditional conformance of 'SameType' to 'P2'}} // expected-note@-2 {{requirement from conditional conformance of 'SameType' to 'P2'}} func same_type_good() { takes_P2(SameType()) } func same_type_bad(_: U) { takes_P2(SameType()) // expected-error{{global function 'takes_P2' requires the types 'U' and 'Int' be equivalent}} takes_P2(SameType()) // expected-error{{global function 'takes_P2' requires the types 'Float' and 'Int' be equivalent}} } struct SameTypeGeneric {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=SameTypeGeneric // CHECK-NEXT: (normal_conformance type=SameTypeGeneric protocol=P2 // CHECK-NEXT: same_type: T U) extension SameTypeGeneric: P2 where T == U {} // expected-note@-1 {{requirement from conditional conformance of 'SameTypeGeneric' to 'P2'}} // expected-note@-2 {{requirement from conditional conformance of 'SameTypeGeneric' to 'P2'}} func same_type_generic_good(_: U, _: V) where U: Assoc, V: Assoc, U.AT == V.AT { takes_P2(SameTypeGeneric()) takes_P2(SameTypeGeneric()) takes_P2(SameTypeGeneric()) } func same_type_bad(_: U, _: V) { takes_P2(SameTypeGeneric()) // expected-error@-1{{cannot invoke 'takes_P2(_:)' with an argument list of type '(SameTypeGeneric)'}} takes_P2(SameTypeGeneric()) // expected-error@-1{{global function 'takes_P2' requires the types 'U' and 'Int' be equivalent}} takes_P2(SameTypeGeneric()) // expected-error@-1{{global function 'takes_P2' requires the types 'Int' and 'Float' be equivalent}} } struct Infer {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=Infer // CHECK-NEXT: (normal_conformance type=Infer protocol=P2 // CHECK-NEXT: same_type: T Constrained // CHECK-NEXT: conforms_to: U P1) extension Infer: P2 where T == Constrained {} // expected-note@-1 2 {{requirement from conditional conformance of 'Infer, V>' to 'P2'}} func infer_good(_: U) { takes_P2(Infer, U>()) } func infer_bad(_: U, _: V) { takes_P2(Infer, V>()) // expected-error@-1{{global function 'takes_P2' requires the types 'Constrained' and 'Constrained' be equivalent}} // expected-error@-2{{global function 'takes_P2' requires that 'V' conform to 'P1'}} takes_P2(Infer, V>()) // expected-error@-1{{type 'V' does not conform to protocol 'P1'}} } struct InferRedundant {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=InferRedundant // CHECK-NEXT: (normal_conformance type=InferRedundant protocol=P2 // CHECK-NEXT: same_type: T Constrained) extension InferRedundant: P2 where T == Constrained {} func infer_redundant_good(_: U) { takes_P2(InferRedundant, U>()) } func infer_redundant_bad(_: U, _: V) { takes_P2(InferRedundant, V>()) // expected-error@-1{{type 'V' does not conform to protocol 'P1'}} takes_P2(InferRedundant, V>()) // expected-error@-1{{type 'V' does not conform to protocol 'P1'}} } class C1 {} class C2: C1 {} class C3: C2 {} struct ClassFree {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassFree // CHECK-NEXT: (normal_conformance type=ClassFree protocol=P2 // CHECK-NEXT: superclass: T C1) extension ClassFree: P2 where T: C1 {} func class_free_good(_: U) { takes_P2(ClassFree()) } func class_free_bad(_: U) { takes_P2(ClassFree()) // expected-error@-1{{cannot invoke 'takes_P2(_:)' with an argument list of type '(ClassFree)'}} } struct ClassMoreSpecific {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassMoreSpecific // CHECK-NEXT: (normal_conformance type=ClassMoreSpecific protocol=P2 // CHECK-NEXT: superclass: T C3) extension ClassMoreSpecific: P2 where T: C3 {} // expected-note {{requirement from conditional conformance of 'ClassMoreSpecific' to 'P2'}} func class_more_specific_good(_: U) { takes_P2(ClassMoreSpecific()) } func class_more_specific_bad(_: U) { takes_P2(ClassMoreSpecific()) // expected-error@-1{{global function 'takes_P2' requires that 'U' inherit from 'C3'}} } struct ClassLessSpecific {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific // CHECK-NEXT: (normal_conformance type=ClassLessSpecific protocol=P2) extension ClassLessSpecific: P2 where T: C1 {} // Inherited conformances: class Base {} extension Base: P2 where T: C1 {} class SubclassGood: Base {} func subclass_good() { takes_P2(SubclassGood()) } class SubclassBad: Base {} func subclass_bad() { takes_P2(SubclassBad()) // expected-error@-1{{cannot invoke 'takes_P2(_:)' with an argument list of type '(SubclassBad)'}} } // Inheriting conformances: struct InheritEqual {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual // CHECK-NEXT: (normal_conformance type=InheritEqual protocol=P2 // CHECK-NEXT: conforms_to: T P1) extension InheritEqual: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritEqual' to 'P2'}} // CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual // CHECK-NEXT: (normal_conformance type=InheritEqual protocol=P5 // CHECK-NEXT: (normal_conformance type=InheritEqual protocol=P2 // CHECK-NEXT: conforms_to: T P1) // CHECK-NEXT: conforms_to: T P1) extension InheritEqual: P5 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritEqual' to 'P5'}} func inheritequal_good(_: U) { takes_P2(InheritEqual()) takes_P5(InheritEqual()) } func inheritequal_bad(_: U) { takes_P2(InheritEqual()) // expected-error{{global function 'takes_P2' requires that 'U' conform to 'P1'}} takes_P5(InheritEqual()) // expected-error{{global function 'takes_P5' requires that 'U' conform to 'P1'}} } struct InheritLess {} extension InheritLess: P2 where T: P1 {} extension InheritLess: P5 {} // expected-error{{type 'T' does not conform to protocol 'P1'}} // expected-error@-1{{'P5' requires that 'T' conform to 'P1'}} // expected-note@-2{{requirement specified as 'T' : 'P1'}} // expected-note@-3{{requirement from conditional conformance of 'InheritLess' to 'P2'}} struct InheritMore {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore // CHECK-NEXT: (normal_conformance type=InheritMore protocol=P2 // CHECK-NEXT: conforms_to: T P1) extension InheritMore: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritMore' to 'P2'}} // CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore // CHECK-NEXT: (normal_conformance type=InheritMore protocol=P5 // CHECK-NEXT: (normal_conformance type=InheritMore protocol=P2 // CHECK-NEXT: conforms_to: T P1) // CHECK-NEXT: conforms_to: T P4) extension InheritMore: P5 where T: P4 {} // expected-note 2 {{requirement from conditional conformance of 'InheritMore' to 'P5'}} func inheritequal_good_good(_: U) { takes_P2(InheritMore()) takes_P5(InheritMore()) } func inheritequal_good_bad(_: U) { takes_P2(InheritMore()) takes_P5(InheritMore()) // expected-error{{global function 'takes_P5' requires that 'U' conform to 'P4'}} } func inheritequal_bad_bad(_: U) { takes_P2(InheritMore()) // expected-error{{global function 'takes_P2' requires that 'U' conform to 'P1'}} takes_P5(InheritMore()) // expected-error{{global function 'takes_P5' requires that 'U' conform to 'P4'}} } struct InheritImplicitOne {} // This shouldn't give anything implicit since we disallow implication for // conditional conformances (in many cases, the implied bounds are // incorrect/insufficiently general). extension InheritImplicitOne: P5 where T: P1 {} // expected-error@-1{{conditional conformance of type 'InheritImplicitOne' to protocol 'P5' does not imply conformance to inherited protocol 'P2'}} // expected-note@-2{{did you mean to explicitly state the conformance like 'extension InheritImplicitOne: P2 where ...'?}} struct InheritImplicitTwo {} // Even if we relax the rule about implication, this double-up should still be // an error, because either conformance could imply InheritImplicitTwo: P2. extension InheritImplicitTwo: P5 where T: P1 {} // expected-error@-1{{conditional conformance of type 'InheritImplicitTwo' to protocol 'P5' does not imply conformance to inherited protocol 'P2'}} // expected-note@-2{{did you mean to explicitly state the conformance like 'extension InheritImplicitTwo: P2 where ...'?}} extension InheritImplicitTwo: P6 where T: P1 {} // However, if there's a non-conditional conformance that implies something, we // can imply from that one. struct InheritImplicitGood1 {} extension InheritImplicitGood1: P5 {} extension InheritImplicitGood1: P6 where T: P1 {} func inheritimplicitgood1(_ : T) { takes_P2(InheritImplicitGood1()) // unconstrained! takes_P2(InheritImplicitGood1()) } struct InheritImplicitGood2 {} extension InheritImplicitGood2: P6 where T: P1 {} extension InheritImplicitGood2: P5 {} func inheritimplicitgood2(_: T) { takes_P2(InheritImplicitGood2()) // unconstrained! takes_P2(InheritImplicitGood2()) } struct InheritImplicitGood3: P5 {} extension InheritImplicitGood3: P6 where T: P1 {} func inheritimplicitgood3(_: T) { takes_P2(InheritImplicitGood3()) // unconstrained! takes_P2(InheritImplicitGood3()) } // "Multiple conformances" from SE0143 struct TwoConformances {} extension TwoConformances: P2 where T: P1 {} // expected-note@-1{{'TwoConformances' declares conformance to protocol 'P2' here}} extension TwoConformances: P2 where T: P3 {} // expected-error@-1{{conflicting conformance of 'TwoConformances' to protocol 'P2'; there cannot be more than one conformance, even with different conditional bounds}} struct TwoDisjointConformances {} extension TwoDisjointConformances: P2 where T == Int {} // expected-note@-1{{'TwoDisjointConformances' declares conformance to protocol 'P2' here}} extension TwoDisjointConformances: P2 where T == String {} // expected-error@-1{{conflicting conformance of 'TwoDisjointConformances' to protocol 'P2'; there cannot be more than one conformance, even with different conditional bounds}} // FIXME: these cases should be equivalent (and both with the same output as the // first), but the second one choses T as the representative of the // equivalence class containing both T and U in the extension's generic // signature, meaning the stored conditional requirement is T: P1, which isn't // true in the original type's generic signature. struct RedundancyOrderDependenceGood {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceGood // CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceGood protocol=P2 // CHECK-NEXT: same_type: T U) extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {} struct RedundancyOrderDependenceBad {} // CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad // CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceBad protocol=P2 // CHECK-NEXT: conforms_to: T P1 // CHECK-NEXT: same_type: T U) extension RedundancyOrderDependenceBad: P2 where T: P1, T == U {} // Checking of conditional requirements for existential conversions. func existential_good(_: T.Type) { _ = Free() as P2 } func existential_bad(_: T.Type) { // FIXME: Poor diagnostic. _ = Free() as P2 // expected-error{{'Free' is not convertible to 'P2'; did you mean to use 'as!' to force downcast?}} } // rdar://problem/35837054 protocol P7 { } protocol P8 { associatedtype A } struct X0 { } struct X1 { } extension X1: P8 { typealias A = X0 } struct X2 { } extension X2: P7 where T: P8, T.A: P7 { } // expected-note {{requirement from conditional conformance of 'X2' to 'P7'}} func takesF7(_: T) { } func passesConditionallyNotF7(x21: X2) { takesF7(x21) // expected-error{{global function 'takesF7' requires that 'X1.A' (aka 'X0') conform to 'P7'}} } public struct SR6990 {} extension SR6990: Sequence where T == Int { public typealias Element = Float public typealias Iterator = IndexingIterator<[Float]> public func makeIterator() -> Iterator { fatalError() } } // SR-8324 protocol ElementProtocol { associatedtype BaseElement: BaseElementProtocol = Self } protocol BaseElementProtocol: ElementProtocol where BaseElement == Self {} protocol ArrayProtocol { associatedtype Element: ElementProtocol } protocol NestedArrayProtocol: ArrayProtocol where Element: ArrayProtocol, Element.Element.BaseElement == Element.BaseElement { associatedtype BaseElement = Element.BaseElement } extension Array: ArrayProtocol where Element: ElementProtocol {} extension Array: NestedArrayProtocol where Element: ElementProtocol, Element: ArrayProtocol, Element.Element.BaseElement == Element.BaseElement { // with the typealias uncommented you do not get a crash. // typealias BaseElement = Element.BaseElement } // SR-8337 struct Foo {} protocol P { associatedtype A var foo: Foo { get } } extension Foo: P where Bar: P { var foo: Foo { return self } } // rdar://problem/47871590 extension BinaryInteger { var foo: Self { return self <= 1 ? 1 : (2...self).reduce(1, *) // expected-error@-1 {{referencing instance method 'reduce' on 'ClosedRange' requires that 'Self.Stride' conform to 'SignedInteger'}} } }