Skip to content

Commit 439cbe6

Browse files
authored
Merge pull request #75100 from swiftlang/gaborh/support-optional-generic-in-enum
[cxx-interop] Support optional generic cases in enums
2 parents b20db85 + b5384bc commit 439cbe6

File tree

6 files changed

+61
-47
lines changed

6 files changed

+61
-47
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -543,25 +543,29 @@ class DeclAndTypePrinter::Implementation
543543
std::tie(objectType, optKind) = getObjectTypeAndOptionality(
544544
paramType->getNominalOrBoundGenericNominal(), paramType);
545545
auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal();
546+
assert(objectTypeDecl != nullptr || paramType->isOptional());
546547

547-
if (auto knownCxxType =
548-
owningPrinter.typeMapping.getKnownCxxTypeInfo(
549-
objectTypeDecl)) {
548+
if (objectTypeDecl &&
549+
owningPrinter.typeMapping.getKnownCxxTypeInfo(objectTypeDecl)) {
550550
outOfLineOS << " " << types[paramType] << " result;\n";
551551
outOfLineOS << " "
552552
"memcpy(&result, payloadFromDestruction, "
553553
"sizeof(result));\n";
554554
outOfLineOS << " return result;\n ";
555555
} else {
556+
bool isOptional = false;
557+
if (!objectTypeDecl) {
558+
objectTypeDecl = paramType->getNominalOrBoundGenericNominal();
559+
isOptional = true;
560+
}
556561
outOfLineOS << " return swift::";
557562
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
558563
outOfLineOS << "::implClassFor<";
559-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
560-
objectTypeDecl->getModuleContext(),
564+
outOfLineSyntaxPrinter.printNominalTypeReference(
565+
objectTypeDecl,
561566
elementDecl->getParentEnum()->getModuleContext());
562-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
563567
outOfLineOS << ">::type";
564-
if (isa<ClassDecl>(objectTypeDecl)) {
568+
if (!isOptional && isa<ClassDecl>(objectTypeDecl)) {
565569
outOfLineOS << "::makeRetained(*reinterpret_cast<void "
566570
"**>(payloadFromDestruction));\n ";
567571
} else {
@@ -570,10 +574,9 @@ class DeclAndTypePrinter::Implementation
570574
outOfLineOS << " swift::"
571575
<< cxx_synthesis::getCxxImplNamespaceName();
572576
outOfLineOS << "::implClassFor<";
573-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
574-
objectTypeDecl->getModuleContext(),
577+
outOfLineSyntaxPrinter.printNominalTypeReference(
578+
objectTypeDecl,
575579
elementDecl->getParentEnum()->getModuleContext());
576-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
577580
outOfLineOS << ">::type";
578581
outOfLineOS << "::initializeWithTake(result, "
579582
"payloadFromDestruction);\n";
@@ -707,14 +710,15 @@ class DeclAndTypePrinter::Implementation
707710
ED, paramType);
708711
auto objectTypeDecl =
709712
objectType->getNominalOrBoundGenericNominal();
710-
assert(objectTypeDecl != nullptr);
713+
assert(objectTypeDecl != nullptr || paramType->isOptional());
711714

712-
if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
715+
if (objectTypeDecl &&
716+
owningPrinter.typeMapping.getKnownCxxTypeInfo(
713717
objectTypeDecl)) {
714718
outOfLineOS
715719
<< " memcpy(result._getOpaquePointer(), &val, "
716720
"sizeof(val));\n";
717-
} else if (isa<ClassDecl>(objectTypeDecl)) {
721+
} else if (isa_and_nonnull<ClassDecl>(objectTypeDecl)) {
718722
outOfLineOS
719723
<< " auto op = swift::"
720724
<< cxx_synthesis::getCxxImplNamespaceName()
@@ -725,46 +729,31 @@ class DeclAndTypePrinter::Implementation
725729
objectTypeDecl =
726730
paramType->getNominalOrBoundGenericNominal();
727731
outOfLineOS << " alignas(";
728-
outOfLineSyntaxPrinter
729-
.printModuleNamespaceQualifiersIfNeeded(
730-
objectTypeDecl->getModuleContext(),
731-
ED->getModuleContext());
732-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
732+
outOfLineSyntaxPrinter.printNominalTypeReference(
733+
objectTypeDecl, ED->getModuleContext());
733734
outOfLineOS << ") unsigned char buffer[sizeof(";
734-
outOfLineSyntaxPrinter
735-
.printModuleNamespaceQualifiersIfNeeded(
736-
objectTypeDecl->getModuleContext(),
737-
ED->getModuleContext());
738-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
735+
outOfLineSyntaxPrinter.printNominalTypeReference(
736+
objectTypeDecl, ED->getModuleContext());
739737
outOfLineOS << ")];\n";
740738
outOfLineOS << " auto *valCopy = new(buffer) ";
741-
outOfLineSyntaxPrinter
742-
.printModuleNamespaceQualifiersIfNeeded(
743-
objectTypeDecl->getModuleContext(),
744-
ED->getModuleContext());
745-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
739+
outOfLineSyntaxPrinter.printNominalTypeReference(
740+
objectTypeDecl, ED->getModuleContext());
746741
outOfLineOS << "(val);\n";
747742
outOfLineOS << " ";
748743
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
749744
<< "::";
750745
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
751746
outOfLineOS << "::implClassFor<";
752-
outOfLineSyntaxPrinter
753-
.printModuleNamespaceQualifiersIfNeeded(
754-
objectTypeDecl->getModuleContext(),
755-
ED->getModuleContext());
756-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
747+
outOfLineSyntaxPrinter.printNominalTypeReference(
748+
objectTypeDecl, ED->getModuleContext());
757749
outOfLineOS << ">::type::initializeWithTake(result._"
758750
"getOpaquePointer(), ";
759751
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
760752
<< "::";
761753
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
762754
outOfLineOS << "::implClassFor<";
763-
outOfLineSyntaxPrinter
764-
.printModuleNamespaceQualifiersIfNeeded(
765-
objectTypeDecl->getModuleContext(),
766-
ED->getModuleContext());
767-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
755+
outOfLineSyntaxPrinter.printNominalTypeReference(
756+
objectTypeDecl, ED->getModuleContext());
768757
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
769758
outOfLineOS << ");\n";
770759
}
@@ -2912,9 +2901,6 @@ static bool isEnumExposableToCxx(const ValueDecl *VD,
29122901
if (auto *params = elementDecl->getParameterList()) {
29132902
for (const auto *param : *params) {
29142903
auto paramType = param->getInterfaceType();
2915-
// TODO: properly support exporting these optionals. rdar://131112273
2916-
if (paramType->isOptional() && paramType->getOptionalObjectType()->isTypeParameter())
2917-
return false;
29182904
if (DeclAndTypeClangFunctionPrinter::getTypeRepresentation(
29192905
printer.getTypeMapping(), printer.getInteropContext(),
29202906
printer, enumDecl->getModuleContext(), paramType)

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ void ClangValueTypePrinter::printTypeGenericTraits(
622622
os << "namespace swift SWIFT_PRIVATE_ATTR {\n";
623623

624624
if (typeDecl->hasClangNode()) {
625-
/// Print a reference to the type metadata fucntion for a C++ type.
625+
/// Print a reference to the type metadata function for a C++ type.
626626
ClangSyntaxPrinter(os).printNamespace(
627627
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
628628
ClangSyntaxPrinter(os).printCTypeMetadataTypeFunction(
@@ -696,20 +696,23 @@ void ClangValueTypePrinter::printTypeGenericTraits(
696696
os << "> = true;\n";
697697
}
698698

699-
// FIXME: generic support.
700-
if (!typeDecl->hasClangNode() && typeMetadataFuncRequirements.empty()) {
699+
if (!typeDecl->hasClangNode()) {
701700
assert(NTD);
702-
os << "template<>\n";
701+
if (printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(NTD))
702+
os << "template<>\n";
703703
os << "struct";
704704
declAndTypePrinter.printAvailability(os, typeDecl);
705705
os << " implClassFor<";
706706
printer.printBaseName(typeDecl->getModuleContext());
707707
os << "::";
708-
printer.printBaseName(typeDecl);
708+
printer.printNominalTypeReference(NTD, moduleContext);
709709
os << "> { using type = ";
710710
printer.printBaseName(typeDecl->getModuleContext());
711711
os << "::" << cxx_synthesis::getCxxImplNamespaceName() << "::";
712712
printCxxImplClassName(os, NTD);
713+
if (NTD->isGeneric())
714+
printer.printGenericSignatureParams(
715+
NTD->getGenericSignature().getCanonicalSignature());
713716
os << "; };\n";
714717
}
715718
os << "} // namespace\n";

test/Interop/SwiftToCxx/generics/generic-enum-execution.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ int main() {
123123
// CHECK-NEXT: after some
124124
// CHECK-NEXT: destroy-TracksDeinit
125125
}
126+
{
127+
auto opt = swift::Optional<int>::some(14);
128+
auto x = GenericCustomType<int>::success(opt);
129+
auto y = x;
130+
assert(y.isSuccess());
131+
assert(y.getSuccess().getSome() == 14);
132+
}
126133
puts("EOF");
127134
// CHECK-NEXT: EOF
128135
return 0;

test/Interop/SwiftToCxx/generics/generic-enum-in-cxx.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend %s -typecheck -module-name Generics -clang-header-expose-decls=all-public -emit-clang-header-path %t/generics.h
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Generics -enable-experimental-cxx-interop -emit-clang-header-path %t/generics.h
33
// RUN: %FileCheck %s < %t/generics.h
44
// RUN: %check-interop-cxx-header-in-clang(%t/generics.h -Wno-reserved-identifier -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY)
55

@@ -96,6 +96,16 @@ public func inoutConcreteOpt(_ x: inout GenericOpt<UInt16>) {
9696

9797
// CHECK: namespace Generics SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("Generics") {
9898

99+
// CHECK: template<class T_0_0>
100+
// CHECK-NEXT: #ifdef __cpp_concepts
101+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
102+
// CHECK-NEXT: #endif
103+
// CHECK-NEXT: class SWIFT_SYMBOL("s:8Generics17GenericCustomTypeO") GenericCustomType;
104+
105+
// CHECK: static inline const constexpr bool isOpaqueLayout<Generics::GenericCustomType<T_0_0>> = true;
106+
107+
// CHECK: template<class T_0_0>
108+
99109
// CHECK: template<class T_0_0>
100110
// CHECK-NEXT: #ifdef __cpp_concepts
101111
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
@@ -218,6 +228,8 @@ public func inoutConcreteOpt(_ x: inout GenericOpt<UInt16>) {
218228
// CHECK-NEXT: _impl::$s8Generics14takeGenericOptyyAA0cD0OyxGlF(_impl::_impl_GenericOpt<T_0_0>::getOpaquePointer(x), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
219229
// CHECK-NEXT: }
220230

231+
// CHECK: SWIFT_INLINE_THUNK bool GenericCustomType<T_0_0>::isFailure() const {
232+
221233
// CHECK: template<class T_0_0>
222234
// CHECK-NEXT: #ifdef __cpp_concepts
223235
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>

test/Interop/SwiftToCxx/generics/generic-struct-in-cxx.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ public func inoutConcretePair(_ x: UInt16, _ y: inout GenericPair<UInt16, UInt16
285285
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
286286
// CHECK-NEXT: #endif // __cpp_concepts
287287
// CHECK-NEXT: static inline const constexpr bool isOpaqueLayout<Generics::GenericPair<T_0_0, T_0_1>> = true;
288+
// CHECK-NEXT: template<class T_0_0, class T_0_1>
289+
// CHECK-NEXT: #ifdef __cpp_concepts
290+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
291+
// CHECK-NEXT: #endif // __cpp_concepts
292+
// CHECK-NEXT: struct implClassFor<Generics::GenericPair<T_0_0, T_0_1>> { using type = Generics::_impl::_impl_GenericPair<T_0_0, T_0_1>; }
288293
// CHECK-NEXT: } // namespace
289294
// CHECK-NEXT: #pragma clang diagnostic pop
290295
// CHECK-NEXT: } // namespace swift

test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
// CHECK: template<class T_0_0>
4747
// CHECK: template<class T_0_0>
4848

49+
// CHECK: template<class T_0_0>
4950
// CHECK: template<class T_0_0>
5051
// CHECK: template<class T_0_0>
5152
// CHECK-NEXT: #ifdef __cpp_concepts

0 commit comments

Comments
 (0)