Skip to content

Commit 40948d7

Browse files
committed
Sema: Workaround for broken existential opening behavior
This is a narrow workaround for a regression from 9e3d0e0. There is no reason to skip this logic for protocol extension members, except that doing so happens to break existential opening in an expression that involves a call to Array.init elsewhere. However there is an underlying issue here with existential opening, which doesn't seem to work right in the presence of overloading. The test case demonstrates the fixed problem, together with an existing bug that points to the underlying problem. Fixes rdar://160389221.
1 parent 8f7af45 commit 40948d7

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13394,8 +13394,12 @@ bool ConstraintSystem::simplifyAppliedOverloadsImpl(
1339413394
choiceType = objectType;
1339513395
}
1339613396

13397+
// FIXME: The !getSelfProtocolDecl() check is load-bearing, because
13398+
// this optimization interacts poorly with existential opening
13399+
// somehow. It should all be removed.
1339713400
if (auto *choiceFnType = choiceType->getAs<FunctionType>()) {
13398-
if (isa<ConstructorDecl>(choice.getDecl())) {
13401+
if (isa<ConstructorDecl>(choice.getDecl()) &&
13402+
!choice.getDecl()->getDeclContext()->getSelfProtocolDecl()) {
1339913403
auto choiceResultType = choice.getBaseType()
1340013404
->getRValueType()
1340113405
->getMetatypeInstanceType();
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {}
4+
5+
func g(_: some P) {}
6+
// expected-note@-1 {{required by global function 'g' where 'some P' = 'any P'}}
7+
8+
// rdar://problem/160389221
9+
func good(_ x: Array<any P>) {
10+
Array(x).forEach { y in g(y) }
11+
}
12+
13+
extension Array {
14+
var ffirst: Element? { fatalError() }
15+
func ffirst(wwhere: (Element) -> Bool) -> Element { fatalError() }
16+
}
17+
18+
func bad(_ x: Array<any P>) {
19+
let y = x.ffirst!
20+
g(y) // ok
21+
22+
let yy = x.ffirst
23+
g(yy!) // ok
24+
25+
// FIXME: This is broken
26+
27+
g(x.ffirst!)
28+
// expected-error@-1 {{type 'any P' cannot conform to 'P'}}
29+
// expected-note@-2 {{only concrete types such as structs, enums and classes can conform to protocols}}
30+
}

0 commit comments

Comments
 (0)