// RUN: %target-parse-verify-swift //===----------------------------------------------------------------------===// // Type-check function definitions //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Basic type checking //===----------------------------------------------------------------------===// protocol EqualComparable { func isEqual(other: Self) -> Bool } func doCompare(t1: T, t2: T, u: U) -> Bool { var b1 = t1.isEqual(t2) if b1 { return true } return t1.isEqual(u) // expected-error {{cannot invoke 'isEqual' with an argument list of type '(U)'}} expected-note {{expected an argument list of type '(T)'}} } protocol MethodLessComparable { func isLess(other: Self) -> Bool } func min(x: T, y: T) -> T { if (y.isLess(x)) { return y } return x } //===----------------------------------------------------------------------===// // Interaction with existential types //===----------------------------------------------------------------------===// func existential(t1: T, t2: T, u: U) { var eqComp : EqualComparable = t1 // expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} eqComp = u if t1.isEqual(eqComp) {} // expected-error{{cannot invoke 'isEqual' with an argument list of type '(EqualComparable)'}} // expected-note @-1 {{expected an argument list of type '(T)'}} if eqComp.isEqual(t2) {} // expected-error{{member 'isEqual' cannot be used on value of protocol type 'EqualComparable'; use a generic constraint instead}} } protocol OtherEqualComparable { func isEqual(other: Self) -> Bool } func otherExistential(t1: T) { var otherEqComp : OtherEqualComparable = t1 // expected-error{{value of type 'T' does not conform to specified type 'OtherEqualComparable'}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp var otherEqComp2 : OtherEqualComparable // expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} otherEqComp2 = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}} _ = otherEqComp2 _ = t1 as protocol // expected-error{{'T' is not convertible to 'protocol'; did you mean to use 'as!' to force downcast?}} {{10-12=as!}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}} } protocol Runcible { func runce(x: A) func spoon(x: Self) } func testRuncible(x: Runcible) { // expected-error{{protocol 'Runcible' can only be used as a generic constraint}} x.runce(5) } //===----------------------------------------------------------------------===// // Overloading //===----------------------------------------------------------------------===// protocol Overload { associatedtype A associatedtype B func getA() -> A func getB() -> B func f1(_: A) -> A func f1(_: B) -> B func f2(_: Int) -> A // expected-note{{found this candidate}} func f2(_: Int) -> B // expected-note{{found this candidate}} func f3(_: Int) -> Int // expected-note {{found this candidate}} func f3(_: Float) -> Float // expected-note {{found this candidate}} func f3(_: Self) -> Self // expected-note {{found this candidate}} var prop : Self { get } } func testOverload(ovl: Ovl, ovl2: Ovl, other: OtherOvl) { var a = ovl.getA() var b = ovl.getB() // Overloading based on arguments ovl.f1(a) a = ovl.f1(a) ovl.f1(b) b = ovl.f1(b) // Overloading based on return type a = ovl.f2(17) b = ovl.f2(17) ovl.f2(17) // expected-error{{ambiguous use of 'f2'}} // Check associated types from different objects/different types. a = ovl2.f2(17) a = ovl2.f1(a) other.f1(a) // expected-error{{cannot invoke 'f1' with an argument list of type '(Ovl.A)'}} // expected-note @-1 {{overloads for 'f1' exist with these partially matching parameter lists: (Self.A), (Self.B)}} // Overloading based on context var f3i : (Int) -> Int = ovl.f3 var f3f : (Float) -> Float = ovl.f3 var f3ovl_1 : (Ovl) -> Ovl = ovl.f3 var f3ovl_2 : (Ovl) -> Ovl = ovl2.f3 var f3ovl_3 : (Ovl) -> Ovl = other.f3 // expected-error{{ambiguous reference to member 'f3'}} var f3i_unbound : (Ovl) -> (Int) -> Int = Ovl.f3 var f3f_unbound : (Ovl) -> (Float) -> Float = Ovl.f3 var f3f_unbound2 : (OtherOvl) -> (Float) -> Float = OtherOvl.f3 var f3ovl_unbound_1 : (Ovl) -> (Ovl) -> Ovl = Ovl.f3 var f3ovl_unbound_2 : (OtherOvl) -> (OtherOvl) -> OtherOvl = OtherOvl.f3 } //===----------------------------------------------------------------------===// // Subscripting //===----------------------------------------------------------------------===// protocol Subscriptable { associatedtype Index associatedtype Value func getIndex() -> Index func getValue() -> Value subscript (index : Index) -> Value { get set } } protocol IntSubscriptable { associatedtype ElementType func getElement() -> ElementType subscript (index : Int) -> ElementType { get } } func subscripting>(t: T) { var index = t.getIndex() var value = t.getValue() var element = t.getElement() value = t[index] t[index] = value // expected-error{{cannot assign through subscript: 't' is a 'let' constant}} element = t[17] t[42] = element // expected-error{{cannot assign through subscript: subscript is get-only}} // Suggests the Int form because we prefer concrete matches to generic matches in diagnosis. t[value] = 17 // expected-error{{cannot convert value of type 'T.Value' to expected argument type 'Int'}} } //===----------------------------------------------------------------------===// // Static functions //===----------------------------------------------------------------------===// protocol StaticEq { static func isEqual(x: Self, y: Self) -> Bool } func staticEqCheck(t: T, u: U) { if t.isEqual(t, t) { return } // expected-error{{static member 'isEqual' cannot be used on instance of type 'T'}} if T.isEqual(t, y: t) { return } if U.isEqual(u, y: u) { return } T.isEqual(t, y: u) // expected-error{{cannot invoke 'isEqual' with an argument list of type '(T, y: U)'}} expected-note {{expected an argument list of type '(T, y: T)'}} } //===----------------------------------------------------------------------===// // Operators //===----------------------------------------------------------------------===// protocol Ordered { func <(lhs: Self, rhs: Self) -> Bool } func testOrdered(x: T, y: Int) { if y < 100 || 500 < y { return } if x < x { return } } //===----------------------------------------------------------------------===// // Requires clauses //===----------------------------------------------------------------------===// func conformanceViaRequires(t1: T, t2: T) -> Bool { let b1 = t1.isEqual(t2) if b1 || t1.isLess(t2) { return true } } protocol GeneratesAnElement { associatedtype Element : EqualComparable func makeIterator() -> Element } protocol AcceptsAnElement { associatedtype Element : MethodLessComparable func accept(e : Element) } func impliedSameType(t: T) { t.accept(t.makeIterator()) let e = t.makeIterator(), e2 = t.makeIterator() if e.isEqual(e2) || e.isLess(e2) { return } } protocol GeneratesAssoc1 { associatedtype Assoc1 : EqualComparable func get() -> Assoc1 } protocol GeneratesAssoc2 { associatedtype Assoc2 : MethodLessComparable func get() -> Assoc2 } func simpleSameType (t: T, u: U) -> Bool { return t.get().isEqual(u.get()) || u.get().isLess(t.get()) } protocol GeneratesMetaAssoc1 { associatedtype MetaAssoc1 : GeneratesAnElement func get() -> MetaAssoc1 } protocol GeneratesMetaAssoc2 { associatedtype MetaAssoc2 : AcceptsAnElement func get() -> MetaAssoc2 } func recursiveSameType (t: T, u: U) { t.get().accept(t.get().makeIterator()) let e = t.get().makeIterator(), e2 = t.get().makeIterator() if e.isEqual(e2) || e.isLess(e2) { return } } // protocol P1 { associatedtype Element } protocol P2 { associatedtype AssocP1 : P1 func getAssocP1() -> AssocP1 } func beginsWith2< E0: P1, E1: P1 where E0.Element == E1.Element, E0.Element : EqualComparable >(e0: E0, _ e1: E1) -> Bool { } func beginsWith3< S0: P2, S1: P2 where S0.AssocP1.Element == S1.AssocP1.Element, S1.AssocP1.Element : EqualComparable >(seq1: S0, _ seq2: S1) -> Bool { return beginsWith2(seq1.getAssocP1(), seq2.getAssocP1()) } // FIXME: Test same-type constraints that try to equate things we // don't want to equate, e.g., T == U. //===----------------------------------------------------------------------===// // Bogus requirements //===----------------------------------------------------------------------===// func nonTypeReq(_: T) {} // expected-error{{use of undeclared type 'Wibble'}} func badProtocolReq(_: T) {} // expected-error{{type 'T' constrained to non-protocol type 'Int'}} func nonTypeSameType(_: T) {} // expected-error{{use of undeclared type 'Wibble'}} func nonTypeSameType2(_: T) {} // expected-error{{use of undeclared type 'Wibble'}} func sameTypeEq(_: T) {} // expected-error{{use '==' for same-type requirements rather than '='}} {{27-28===}} func badTypeConformance1(_: T) {} // expected-error{{type 'Int' in conformance requirement does not refer to a generic parameter or associated type}} func badTypeConformance2(_: T) { } // expected-error{{'Blarg' is not a member type of 'T'}} func badSameType(_: T) {}