Skip to content

Commit a9b2c06

Browse files
committed
embedded: print an error for class existentials where not all protocols of a composition are class bound
We don't support this, yet. Without the error IRGen would crash. rdar://137517212
1 parent c31ed73 commit a9b2c06

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/SIL/InstructionUtils.h"
1515
#include "swift/SIL/MemAccessUtils.h"
1616
#include "swift/AST/SubstitutionMap.h"
17+
#include "swift/AST/ProtocolConformance.h"
1718
#include "swift/Basic/Assertions.h"
1819
#include "swift/Basic/Defer.h"
1920
#include "swift/Basic/NullablePtr.h"
@@ -671,7 +672,20 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
671672
RuntimeEffect::MetaData | RuntimeEffect::Existential;
672673

673674
case SILInstructionKind::InitExistentialRefInst:
674-
impactType = inst->getOperand(0)->getType();
675+
impactType = cast<InitExistentialRefInst>(inst)->getType();
676+
// Make sure to get a diagnostic error in embedded swift for class existentials
677+
// where not all protocols of a composition are class bound. For example:
678+
// let existential: any ClassBound & NotClassBound = MyClass()
679+
// In future we might support this case and then we can remove this check.
680+
for (auto protoRef : cast<InitExistentialRefInst>(inst)->getConformances()) {
681+
if (protoRef.isConcrete()) {
682+
ProtocolConformance *conf = protoRef.getConcrete();
683+
if (isa<NormalProtocolConformance>(conf) &&
684+
!conf->getProtocol()->requiresClass()) {
685+
return RuntimeEffect::MetaData | RuntimeEffect::Existential;
686+
}
687+
}
688+
}
675689
return RuntimeEffect::MetaData | RuntimeEffect::ExistentialClassBound;
676690

677691
case SILInstructionKind::InitExistentialMetatypeInst:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-swift-emit-ir -parse-as-library -module-name main -verify %s -enable-experimental-feature Embedded -wmo
2+
3+
// REQUIRES: OS=macosx || OS=linux-gnu
4+
5+
protocol ClassBound: AnyObject {
6+
func foo()
7+
}
8+
9+
protocol OtherProtocol {
10+
func bar()
11+
}
12+
13+
class MyClass: ClassBound, OtherProtocol {
14+
func foo() { print("MyClass.foo()") }
15+
func bar() { print("MyClass.bar()") }
16+
}
17+
18+
// Currently we don't support this
19+
func test(existential: any ClassBound & OtherProtocol) {
20+
}
21+
22+
@main
23+
struct Main {
24+
static func main() {
25+
test(existential: MyClass()) // expected-error {{cannot use a value of protocol type 'any ClassBound & OtherProtocol' in embedded Swift}}
26+
// expected-note@-4 {{called from here}}
27+
}
28+
}

0 commit comments

Comments
 (0)