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
This commit is contained in:
Erik Eckstein
2024-10-17 09:46:06 +02:00
parent c31ed73e70
commit a9b2c06f81
2 changed files with 43 additions and 1 deletions

View File

@@ -14,6 +14,7 @@
#include "swift/SIL/InstructionUtils.h"
#include "swift/SIL/MemAccessUtils.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/NullablePtr.h"
@@ -671,7 +672,20 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
RuntimeEffect::MetaData | RuntimeEffect::Existential;
case SILInstructionKind::InitExistentialRefInst:
impactType = inst->getOperand(0)->getType();
impactType = cast<InitExistentialRefInst>(inst)->getType();
// Make sure to get a diagnostic error in embedded swift for class existentials
// where not all protocols of a composition are class bound. For example:
// let existential: any ClassBound & NotClassBound = MyClass()
// In future we might support this case and then we can remove this check.
for (auto protoRef : cast<InitExistentialRefInst>(inst)->getConformances()) {
if (protoRef.isConcrete()) {
ProtocolConformance *conf = protoRef.getConcrete();
if (isa<NormalProtocolConformance>(conf) &&
!conf->getProtocol()->requiresClass()) {
return RuntimeEffect::MetaData | RuntimeEffect::Existential;
}
}
}
return RuntimeEffect::MetaData | RuntimeEffect::ExistentialClassBound;
case SILInstructionKind::InitExistentialMetatypeInst:

View File

@@ -0,0 +1,28 @@
// RUN: %target-swift-emit-ir -parse-as-library -module-name main -verify %s -enable-experimental-feature Embedded -wmo
// REQUIRES: OS=macosx || OS=linux-gnu
protocol ClassBound: AnyObject {
func foo()
}
protocol OtherProtocol {
func bar()
}
class MyClass: ClassBound, OtherProtocol {
func foo() { print("MyClass.foo()") }
func bar() { print("MyClass.bar()") }
}
// Currently we don't support this
func test(existential: any ClassBound & OtherProtocol) {
}
@main
struct Main {
static func main() {
test(existential: MyClass()) // expected-error {{cannot use a value of protocol type 'any ClassBound & OtherProtocol' in embedded Swift}}
// expected-note@-4 {{called from here}}
}
}