Skip to content

Commit 6cf36b1

Browse files
authored
Merge pull request #85652 from clackary/fix/85020-metatype-resolution
[CSOptimizer] Also favor existential metatype candidates in paramType isAny fast path
2 parents 83a9913 + a405fff commit 6cf36b1

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

lib/Sema/CSOptimizer.cpp

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

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

14381449
// Check if a candidate could be matched to a parameter by
14391450
// an existential opening.

test/Interpreter/issue-85020.swift

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

0 commit comments

Comments
 (0)