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:
Pavel Yaskevich
2025-12-10 06:48:36 -08:00
committed by GitHub
2 changed files with 81 additions and 0 deletions

View File

@@ -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);

View File

@@ -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
}
}