mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85905 from xedin/rdar-165862285-6.3
[6.3][CSRanking] Disambiguate static vs. instance method that used to be s…
This commit is contained in:
@@ -746,6 +746,29 @@ bool CompareDeclSpecializationRequest::evaluate(
|
||||
unsigned numParams1 = params1.size();
|
||||
unsigned numParams2 = params2.size();
|
||||
|
||||
// Handle the following situation:
|
||||
//
|
||||
// struct S {
|
||||
// func test() {}
|
||||
// static func test(_: S) {}
|
||||
// }
|
||||
//
|
||||
// Calling `S.test(s)` where `s` has a type `S` without any other context
|
||||
// should prefer a complete call to a static member over a partial
|
||||
// application of an instance once based on the choice of the base type.
|
||||
//
|
||||
// The behavior is consistent for double-applies as well i.e.
|
||||
// `S.test(s)()` if static method produced a function type it would be
|
||||
// preferred.
|
||||
if (decl1->isInstanceMember() != decl2->isInstanceMember() &&
|
||||
isa<FuncDecl>(decl1) && isa<FuncDecl>(decl2)) {
|
||||
auto selfTy = decl1->isInstanceMember() ? selfTy2 : selfTy1;
|
||||
auto params = decl1->isInstanceMember() ? params2 : params1;
|
||||
if (params.size() == 1 && params[0].getPlainType()->isEqual(selfTy)) {
|
||||
return completeResult(!decl1->isInstanceMember());
|
||||
}
|
||||
}
|
||||
|
||||
if (numParams1 > numParams2)
|
||||
return completeResult(false);
|
||||
|
||||
|
||||
@@ -414,3 +414,61 @@ do {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
struct S {
|
||||
func test() -> Int { 42 }
|
||||
static func test(_: S...) {}
|
||||
|
||||
func doubleApply() {}
|
||||
static func doubleApply(_: S) -> () -> Int { { 42 } }
|
||||
}
|
||||
|
||||
func test(s: S) {
|
||||
let res1 = S.test(s)
|
||||
// expected-warning@-1 {{constant 'res1' inferred to have type '()', which may be unexpected}}
|
||||
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
|
||||
_ = res1
|
||||
|
||||
let useInstance = S.test(s)()
|
||||
let _: Int = useInstance
|
||||
|
||||
let res2 = {
|
||||
S.test(s)
|
||||
}
|
||||
let _: () -> Void = res2
|
||||
|
||||
let _ = { () async -> Void in
|
||||
_ = 42
|
||||
return S.test(s)
|
||||
}
|
||||
|
||||
let res3 = S.doubleApply(s)
|
||||
let _: () -> Int = res3
|
||||
|
||||
let res4 = S.doubleApply(s)()
|
||||
let _: Int = res4
|
||||
|
||||
let res5 = { S.doubleApply(s)() }
|
||||
let _: () -> Int = res5
|
||||
|
||||
let res6 = {
|
||||
_ = 42
|
||||
return S.doubleApply(s)
|
||||
}
|
||||
let _: () -> Int = res6()
|
||||
}
|
||||
|
||||
func testAsyncContext(s: S) async {
|
||||
let res1 = S.test(s)
|
||||
// expected-warning@-1 {{constant 'res1' inferred to have type '()', which may be unexpected}}
|
||||
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
|
||||
_ = res1
|
||||
|
||||
let res2 = S.doubleApply(s)
|
||||
let _: () -> Int = res2
|
||||
|
||||
let res3 = S.doubleApply(s)()
|
||||
let _: Int = res3
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user