Files
swift-mirror/test/Constraints/overload.swift
Doug Gregor 42bb2528dd [Overload resolution] Prefer functions with fewer defaulted/variadic arguments.
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.
2016-02-05 11:41:01 -08:00

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 '?'?}}