| // RUN: %target-typecheck-verify-swift |
| |
| //===----------------------------------------------------------------------===// |
| // Deduction of generic arguments |
| //===----------------------------------------------------------------------===// |
| |
| func identity<T>(_ value: T) -> T { return value } |
| |
| func identity2<T>(_ value: T) -> T { return value } |
| func identity2<T>(_ value: T) -> Int { return 0 } |
| |
| struct X { } |
| struct Y { } |
| |
| func useIdentity(_ x: Int, y: Float, i32: Int32) { |
| var x2 = identity(x) |
| var y2 = identity(y) |
| |
| // Deduction that involves the result type |
| x2 = identity(17) |
| var i32_2 : Int32 = identity(17) |
| |
| // Deduction where the result type and input type can get different results |
| var xx : X, yy : Y |
| xx = identity(yy) // expected-error{{cannot assign value of type 'Y' to type 'X'}} |
| xx = identity2(yy) // expected-error{{cannot convert value of type 'Y' to expected argument type 'X'}} |
| } |
| |
| // FIXME: Crummy diagnostic! |
| func twoIdentical<T>(_ x: T, _ y: T) -> T {} |
| |
| func useTwoIdentical(_ xi: Int, yi: Float) { |
| var x = xi, y = yi |
| x = twoIdentical(x, x) |
| y = twoIdentical(y, y) |
| x = twoIdentical(x, 1) |
| x = twoIdentical(1, x) |
| y = twoIdentical(1.0, y) |
| y = twoIdentical(y, 1.0) |
| |
| twoIdentical(x, y) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| } |
| |
| func mySwap<T>(_ x: inout T, |
| _ y: inout T) { |
| let tmp = x |
| x = y |
| y = tmp |
| } |
| |
| func useSwap(_ xi: Int, yi: Float) { |
| var x = xi, y = yi |
| mySwap(&x, &x) |
| mySwap(&y, &y) |
| |
| mySwap(x, x) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{10-10=&}} |
| // expected-error @-1 {{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{13-13=&}} |
| |
| mySwap(&x, &y) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| } |
| |
| func takeTuples<T, U>(_: (T, U), _: (U, T)) { |
| } |
| |
| func useTuples(_ x: Int, y: Float, z: (Float, Int)) { |
| takeTuples((x, y), (y, x)) |
| |
| takeTuples((x, y), (x, y)) // expected-error{{cannot convert value of type 'Int' to expected argument type 'Float'}} |
| |
| // FIXME: Use 'z', which requires us to fix our tuple-conversion |
| // representation. |
| } |
| |
| func acceptFunction<T, U>(_ f: (T) -> U, _ t: T, _ u: U) {} |
| |
| func passFunction(_ f: (Int) -> Float, x: Int, y: Float) { |
| acceptFunction(f, x, y) |
| acceptFunction(f, y, y) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| } |
| |
| func returnTuple<T, U>(_: T) -> (T, U) { } // expected-note {{in call to function 'returnTuple'}} |
| |
| func testReturnTuple(_ x: Int, y: Float) { |
| returnTuple(x) // expected-error{{generic parameter 'U' could not be inferred}} |
| |
| var _ : (Int, Float) = returnTuple(x) |
| var _ : (Float, Float) = returnTuple(y) |
| |
| // <rdar://problem/22333090> QoI: Propagate contextual information in a call to operands |
| var _ : (Int, Float) = returnTuple(y) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| } |
| |
| |
| func confusingArgAndParam<T, U>(_ f: (T) -> U, _ g: (U) -> T) { |
| confusingArgAndParam(g, f) |
| confusingArgAndParam(f, g) |
| } |
| |
| func acceptUnaryFn<T, U>(_ f: (T) -> U) { } |
| func acceptUnaryFnSame<T>(_ f: (T) -> T) { } |
| |
| func acceptUnaryFnRef<T, U>(_ f: inout (T) -> U) { } |
| func acceptUnaryFnSameRef<T>(_ f: inout (T) -> T) { } |
| |
| func unaryFnIntInt(_: Int) -> Int {} |
| |
| func unaryFnOvl(_: Int) -> Int {} // expected-note{{found this candidate}} |
| func unaryFnOvl(_: Float) -> Int {} // expected-note{{found this candidate}} |
| |
| // Variable forms of the above functions |
| var unaryFnIntIntVar : (Int) -> Int = unaryFnIntInt |
| |
| func passOverloadSet() { |
| // Passing a non-generic function to a generic function |
| acceptUnaryFn(unaryFnIntInt) |
| acceptUnaryFnSame(unaryFnIntInt) |
| |
| // Passing an overloaded function set to a generic function |
| // FIXME: Yet more terrible diagnostics. |
| acceptUnaryFn(unaryFnOvl) // expected-error{{ambiguous use of 'unaryFnOvl'}} |
| acceptUnaryFnSame(unaryFnOvl) |
| |
| // Passing a variable of function type to a generic function |
| acceptUnaryFn(unaryFnIntIntVar) |
| acceptUnaryFnSame(unaryFnIntIntVar) |
| |
| // Passing a variable of function type to a generic function to an inout parameter |
| acceptUnaryFnRef(&unaryFnIntIntVar) |
| acceptUnaryFnSameRef(&unaryFnIntIntVar) |
| |
| acceptUnaryFnRef(unaryFnIntIntVar) // expected-error{{passing value of type '(Int) -> Int' to an inout parameter requires explicit '&'}} {{20-20=&}} |
| } |
| |
| func acceptFnFloatFloat(_ f: (Float) -> Float) {} |
| func acceptFnDoubleDouble(_ f: (Double) -> Double) {} |
| |
| func passGeneric() { |
| acceptFnFloatFloat(identity) |
| acceptFnFloatFloat(identity2) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Simple deduction for generic member functions |
| //===----------------------------------------------------------------------===// |
| struct SomeType { |
| func identity<T>(_ x: T) -> T { return x } |
| |
| func identity2<T>(_ x: T) -> T { return x } // expected-note 2{{found this candidate}} |
| func identity2<T>(_ x: T) -> Float { } // expected-note 2{{found this candidate}} |
| |
| func returnAs<T>() -> T {} |
| } |
| |
| func testMemberDeduction(_ sti: SomeType, ii: Int, fi: Float) { |
| var st = sti, i = ii, f = fi |
| i = st.identity(i) |
| f = st.identity(f) |
| i = st.identity2(i) |
| f = st.identity2(f) // expected-error{{ambiguous use of 'identity2'}} |
| i = st.returnAs() |
| f = st.returnAs() |
| acceptFnFloatFloat(st.identity) |
| acceptFnFloatFloat(st.identity2) // expected-error{{ambiguous use of 'identity2'}} |
| acceptFnDoubleDouble(st.identity2) |
| } |
| |
| struct StaticFuncs { |
| static func chameleon<T>() -> T {} |
| func chameleon2<T>() -> T {} |
| } |
| |
| struct StaticFuncsGeneric<U> { |
| // FIXME: Nested generics are very broken |
| // static func chameleon<T>() -> T {} |
| } |
| |
| func chameleon<T>() -> T {} |
| |
| func testStatic(_ sf: StaticFuncs, sfi: StaticFuncsGeneric<Int>) { |
| var x: Int16 |
| x = StaticFuncs.chameleon() |
| x = sf.chameleon2() |
| // FIXME: Nested generics are very broken |
| // x = sfi.chameleon() |
| // typealias SFI = StaticFuncsGeneric<Int> |
| // x = SFI.chameleon() |
| _ = x |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Deduction checking for constraints |
| //===----------------------------------------------------------------------===// |
| protocol IsBefore { |
| func isBefore(_ other: Self) -> Bool |
| } |
| |
| func min2<T : IsBefore>(_ x: T, _ y: T) -> T { |
| if y.isBefore(x) { return y } |
| return x |
| } |
| |
| extension Int : IsBefore { |
| func isBefore(_ other: Int) -> Bool { return self < other } |
| } |
| |
| func callMin(_ x: Int, y: Int, a: Float, b: Float) { |
| _ = min2(x, y) |
| min2(a, b) // expected-error{{argument type 'Float' does not conform to expected type 'IsBefore'}} |
| } |
| |
| func rangeOfIsBefore<R : IteratorProtocol>(_ range: R) where R.Element : IsBefore {} |
| |
| func callRangeOfIsBefore(_ ia: [Int], da: [Double]) { |
| rangeOfIsBefore(ia.makeIterator()) |
| rangeOfIsBefore(da.makeIterator()) // expected-error{{type 'Double' does not conform to protocol 'IsBefore'}} |
| } |
| |
| func testEqualIterElementTypes<A: IteratorProtocol, B: IteratorProtocol>(_ a: A, _ b: B) where A.Element == B.Element {} |
| // expected-note@-1 {{candidate requires that the types 'Int' and 'Double' be equivalent (requirement specified as 'A.Element' == 'B.Element' [with A = IndexingIterator<[Int]>, B = IndexingIterator<[Double]>])}} |
| func compareIterators() { |
| var a: [Int] = [] |
| var b: [Double] = [] |
| testEqualIterElementTypes(a.makeIterator(), b.makeIterator()) |
| // expected-error@-1 {{cannot invoke 'testEqualIterElementTypes(_:_:)' with an argument list of type '(IndexingIterator<[Int]>, IndexingIterator<[Double]>)'}} |
| } |
| |
| protocol P_GI { |
| associatedtype Y |
| } |
| |
| class C_GI : P_GI { |
| typealias Y = Double |
| } |
| |
| class GI_Diff {} |
| func genericInheritsA<T>(_ x: T) where T : P_GI, T.Y : GI_Diff {} |
| // expected-note@-1 {{candidate requires that 'GI_Diff' inherit from 'T.Y' (requirement specified as 'T.Y' : 'GI_Diff' [with T = C_GI])}} |
| genericInheritsA(C_GI()) |
| // expected-error@-1 {{cannot invoke 'genericInheritsA(_:)' with an argument list of type '(C_GI)'}} |
| |
| //===----------------------------------------------------------------------===// |
| // Deduction for member operators |
| //===----------------------------------------------------------------------===// |
| protocol Addable { |
| static func +(x: Self, y: Self) -> Self |
| } |
| func addAddables<T : Addable, U>(_ x: T, y: T, u: U) -> T { |
| u + u // expected-error{{binary operator '+' cannot be applied to two 'U' operands}} |
| // expected-note @-1 {{overloads for '+' exist with these partially matching parameter lists: }} |
| return x+y |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Deduction for bound generic types |
| //===----------------------------------------------------------------------===// |
| struct MyVector<T> { func size() -> Int {} } |
| |
| func getVectorSize<T>(_ v: MyVector<T>) -> Int { |
| return v.size() |
| } |
| |
| func ovlVector<T>(_ v: MyVector<T>) -> X {} |
| func ovlVector<T>(_ v: MyVector<MyVector<T>>) -> Y {} |
| |
| func testGetVectorSize(_ vi: MyVector<Int>, vf: MyVector<Float>) { |
| var i : Int |
| i = getVectorSize(vi) |
| i = getVectorSize(vf) |
| |
| getVectorSize(i) // expected-error{{cannot convert value of type 'Int' to expected argument type 'MyVector<_>'}} |
| |
| var x : X, y : Y |
| x = ovlVector(vi) |
| x = ovlVector(vf) |
| |
| var vvi : MyVector<MyVector<Int>> |
| y = ovlVector(vvi) |
| |
| var yy = ovlVector(vvi) |
| yy = y |
| y = yy |
| } |
| |
| // <rdar://problem/15104554> |
| postfix operator <*> |
| |
| protocol MetaFunction { |
| associatedtype Result |
| static postfix func <*> (_: Self) -> Result? |
| } |
| |
| protocol Bool_ {} |
| struct False : Bool_ {} |
| struct True : Bool_ {} |
| |
| postfix func <*> <B>(_: Test<B>) -> Int? { return .none } |
| postfix func <*> (_: Test<True>) -> String? { return .none } |
| |
| class Test<C: Bool_> : MetaFunction { |
| typealias Result = Int |
| } // picks first <*> |
| typealias Inty = Test<True>.Result |
| var iy : Inty = 5 // okay, because we picked the first <*> |
| var iy2 : Inty = "hello" // expected-error{{cannot convert value of type 'String' to specified type 'Inty' (aka 'Int')}} |
| |
| // rdar://problem/20577950 |
| class DeducePropertyParams { |
| let badSet: Set = ["Hello"] |
| } |
| |
| // SR-69 |
| struct A {} |
| func foo() { |
| for i in min(1,2) { // expected-error{{type 'Int' does not conform to protocol 'Sequence'}} |
| } |
| let j = min(Int(3), Float(2.5)) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}} |
| let k = min(A(), A()) // expected-error{{argument type 'A' does not conform to expected type 'Comparable'}} |
| let oi : Int? = 5 |
| let l = min(3, oi) // expected-error{{value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?}} |
| } |
| |
| infix operator +& |
| func +&<R, S>(lhs: inout R, rhs: S) where R : RangeReplaceableCollection, S : Sequence, R.Element == S.Element {} |
| // expected-note@-1 {{candidate requires that the types 'String' and 'String.Element' (aka 'Character') be equivalent (requirement specified as 'R.Element' == 'S.Element' [with R = [String], S = String])}} |
| |
| func rdar33477726_1() { |
| var arr: [String] = [] |
| arr +& "hello" |
| // expected-error@-1 {{binary operator '+&(_:_:)' cannot be applied to operands of type '[String]' and 'String'}} |
| } |
| |
| func rdar33477726_2<R, S>(_: R, _: S) where R: Sequence, S == R.Element {} |
| // expected-note@-1 {{candidate requires that the types 'Int' and 'String.Element' (aka 'Character') be equivalent (requirement specified as 'S' == 'R.Element' [with R = String, S = Int])}} |
| rdar33477726_2("answer", 42) |
| // expected-error@-1 {{cannot invoke 'rdar33477726_2(_:_:)' with an argument list of type '(String, Int)'}} |
| |
| prefix operator +- |
| prefix func +-<T>(_: T) where T: Sequence, T.Element == Int {} |
| // expected-note@-1 {{candidate requires that the types 'String.Element' (aka 'Character') and 'Int' be equivalent (requirement specified as 'T.Element' == 'Int' [with T = String])}} |
| |
| +-"hello" |
| // expected-error@-1 {{unary operator '+-(_:)' cannot be applied to an operand of type 'String'}} |