Skip to content

Commit c5c0e06

Browse files
authored
Merge pull request #85686 from clackary/fix/6.3/85020-metatype-resolution
[6.3 🍒][CSOptimizer] Also favor existential metatype candidates in paramType isAny fast path
2 parents 97f8be5 + 9a04d54 commit c5c0e06

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,11 +1427,22 @@ static void determineBestChoicesInContext(
14271427
}
14281428
}
14291429

1430-
// If the parameter is `Any` we assume that all candidates are
1431-
// convertible to it, which makes it a perfect match. The solver
1432-
// would then decide whether erasing to an existential is preferable.
1433-
if (paramType->isAny())
1434-
return 1;
1430+
if (paramType->isAnyExistentialType()) {
1431+
// If the parameter is `Any` we assume that all candidates are
1432+
// convertible to it, which makes it a perfect match. The solver
1433+
// would then decide whether erasing to an existential is preferable.
1434+
if (paramType->isAny())
1435+
return 1;
1436+
1437+
// If the parameter is `Any.Type` we assume that all metatype
1438+
// candidates are convertible to it.
1439+
if (auto *EMT = paramType->getAs<ExistentialMetatypeType>()) {
1440+
if (EMT->getExistentialInstanceType()->isAny() &&
1441+
(candidateType->is<ExistentialMetatypeType>() ||
1442+
candidateType->is<MetatypeType>()))
1443+
return 1;
1444+
}
1445+
}
14351446

14361447
// Check if a candidate could be matched to a parameter by
14371448
// an existential opening.

test/Interpreter/issue-85020.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
3+
// https://github.com/swiftlang/swift/issues/85020
4+
5+
// REQUIRES: executable_test
6+
7+
struct Store {
8+
let theType: Any.Type
9+
10+
init(of theType: Any.Type) {
11+
print("init from TYPE: \(theType)")
12+
self.theType = theType
13+
}
14+
15+
init(of instance: Any) {
16+
print("init from VALUE: \(instance)")
17+
self.init(of: type(of: instance))
18+
}
19+
}
20+
21+
let a: (any Numeric)? = 42
22+
print("a: \(type(of: a))")
23+
// CHECK: a: Optional<Numeric>
24+
25+
let storeA = Store(of: a!)
26+
// CHECK-NEXT: init from VALUE: 42
27+
// CHECK-NEXT: init from TYPE: Int
28+
29+
let b: (any Numeric.Type)? = type(of: 42)
30+
print("b: \(type(of: b))")
31+
// CHECK-NEXT: b: Optional<Numeric.Type>
32+
33+
let storeB = Store(of: b!)
34+
// CHECK-NEXT: init from TYPE: Int
35+

0 commit comments

Comments
 (0)