mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When comparing two functions for overload resolution, break apart the parameter lists to compare individual parameters rather than comparing the tuples. This allows us to prefer functions with fewer arguments to ones with more, defaulted or variadic arguments. That preference was already encoded in the constraint optimizer, which led to some strange behavior where the preference was expressed for function calls but not for calls to initializers. Fixes rdar://problem/24128153. The standard library change tweaks the anachronistic, unavailable "print" variants somewhat. The only behavior change here is a slight regression for cases like: print(a: 1, b: 2) where we used to produce a diagnostic: Please wrap your tuple argument in parentheses: 'print((...))' but we now get: argument labels '(a:, b:)' do not match any available overloads However, this regression will happen at some point *anyway*, if SE-0029 (or anything else that removes the implicit tuple splat operation) goes through.
164 lines
3.9 KiB
Swift
164 lines
3.9 KiB
Swift
// RUN: %target-parse-verify-swift
|
|
|
|
func markUsed<T>(t: T) {}
|
|
|
|
func f0(_: Float) -> Float {}
|
|
func f0(_: Int) -> Int {}
|
|
|
|
func f1(_: Int) {}
|
|
|
|
func identity<T>(_: T) -> T {}
|
|
|
|
func f2<T>(_: T) -> T {}
|
|
// FIXME: Fun things happen when we make this T, U!
|
|
func f2<T>(_: T, _: T) -> (T, T) { }
|
|
|
|
struct X {}
|
|
var x : X
|
|
var i : Int
|
|
var f : Float
|
|
|
|
f0(i)
|
|
f0(1.0)
|
|
f0(1)
|
|
f1(f0(1))
|
|
f1(identity(1))
|
|
|
|
f0(x) // expected-error{{cannot invoke 'f0' with an argument list of type '(X)'}}
|
|
// expected-note @-1 {{overloads for 'f0' exist with these partially matching parameter lists: (Float), (Int)}}
|
|
|
|
_ = f + 1
|
|
f2(i)
|
|
f2((i, f))
|
|
|
|
class A {
|
|
init() {}
|
|
}
|
|
class B : A {
|
|
override init() { super.init() }
|
|
}
|
|
class C : B {
|
|
override init() { super.init() }
|
|
}
|
|
|
|
func bar(b: B) -> Int {} // #1
|
|
func bar(a: A) -> Float {} // #2
|
|
|
|
var barResult = bar(C()) // selects #1, which is more specialized
|
|
i = barResult // make sure we got #1
|
|
f = bar(C()) // selects #2 because of context
|
|
|
|
// Overload resolution for constructors
|
|
protocol P1 { }
|
|
struct X1a : P1 { }
|
|
|
|
struct X1b {
|
|
init(x : X1a) { }
|
|
init<T : P1>(x : T) { }
|
|
}
|
|
|
|
X1b(x: X1a()) // expected-warning{{unused}}
|
|
|
|
// Overload resolution for subscript operators.
|
|
class X2a { }
|
|
class X2b : X2a { }
|
|
class X2c : X2b { }
|
|
|
|
struct X2d {
|
|
subscript (index : X2a) -> Int {
|
|
return 5
|
|
}
|
|
|
|
subscript (index : X2b) -> Int {
|
|
return 7
|
|
}
|
|
|
|
func foo(x : X2c) -> Int {
|
|
return self[x]
|
|
}
|
|
}
|
|
|
|
// Invalid declarations
|
|
// FIXME: Suppress the diagnostic for the call below, because the invalid
|
|
// declaration would have matched.
|
|
func f3(x: Intthingy) -> Int { } // expected-error{{use of undeclared type 'Intthingy'}}
|
|
|
|
func f3(x: Float) -> Float { }
|
|
f3(i) // expected-error{{cannot convert value of type 'Int' to expected argument type 'Float'}}
|
|
|
|
func f4(i: Wonka) { } // expected-error{{use of undeclared type 'Wonka'}}
|
|
func f4(j: Wibble) { } // expected-error{{use of undeclared type 'Wibble'}}
|
|
f4(5)
|
|
|
|
func f1() {
|
|
var c : Class // expected-error{{use of undeclared type 'Class'}}
|
|
markUsed(c.x) // make sure error does not cascade here
|
|
}
|
|
|
|
// We don't provide return-type sensitivity unless there is context.
|
|
func f5(i: Int) -> A { return A() } // expected-note{{candidate}}
|
|
func f5(i: Int) -> B { return B() } // expected-note{{candidate}}
|
|
|
|
f5(5) // expected-error{{ambiguous use of 'f5'}}
|
|
|
|
struct HasX1aProperty {
|
|
func write(_: X1a) {}
|
|
func write(_: P1) {}
|
|
|
|
var prop = X1a()
|
|
func test() {
|
|
write(prop) // no error, not ambiguous
|
|
}
|
|
}
|
|
|
|
// rdar://problem/16554496
|
|
@available(*, unavailable)
|
|
func availTest(x: Int) {}
|
|
func availTest(x: Any) { markUsed("this one") }
|
|
func doAvailTest(x: Int) {
|
|
availTest(x)
|
|
}
|
|
|
|
// rdar://problem/20886179
|
|
func test20886179(handlers: [(Int) -> Void], buttonIndex: Int) {
|
|
handlers[buttonIndex](buttonIndex)
|
|
}
|
|
|
|
// The problem here is that the call has a contextual result type incompatible
|
|
// with *all* overload set candidates. This is not an ambiguity.
|
|
func overloaded_identity(a : Int) -> Int {}
|
|
func overloaded_identity(b : Float) -> Float {}
|
|
|
|
func test_contextual_result() {
|
|
return overloaded_identity() // expected-error {{no 'overloaded_identity' candidates produce the expected contextual result type '()'}}
|
|
// expected-note @-1 {{overloads for 'overloaded_identity' exist with these result types: Int, Float}}
|
|
}
|
|
|
|
// rdar://problem/24128153
|
|
struct X0 {
|
|
init(_ i: Any.Type) { }
|
|
init?(_ i: Any.Type, _ names: String...) { }
|
|
}
|
|
|
|
let x0 = X0(Int.self)
|
|
let x0check: X0 = x0 // okay: chooses first initializer
|
|
|
|
struct X1 {
|
|
init?(_ i: Any.Type) { }
|
|
init(_ i: Any.Type, _ names: String...) { }
|
|
}
|
|
|
|
let x1 = X1(Int.self)
|
|
let x1check: X1 = x1 // expected-error{{value of optional type 'X1?' not unwrapped; did you mean to use '!' or '?'?}}
|
|
|
|
|
|
struct X2 {
|
|
init?(_ i: Any.Type) { }
|
|
init(_ i: Any.Type, a: Int = 0) { }
|
|
init(_ i: Any.Type, a: Int = 0, b: Int = 0) { }
|
|
init(_ i: Any.Type, a: Int = 0, c: Int = 0) { }
|
|
}
|
|
|
|
let x2 = X2(Int.self)
|
|
let x2check: X2 = x2 // expected-error{{value of optional type 'X2?' not unwrapped; did you mean to use '!' or '?'?}}
|