Skip to content

Commit 70a968a

Browse files
authored
Merge pull request #69515 from hyp/eng/generic-generic-generic-generic
[interop][SwiftToCxx] ensure Swift generic types can be used as template parameters to other Swift generic types in C++
2 parents 22592d2 + ca95860 commit 70a968a

6 files changed

+47
-7
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

+20-7
Original file line numberDiff line numberDiff line change
@@ -581,14 +581,27 @@ void ClangValueTypePrinter::printTypePrecedingGenericTraits(
581581

582582
os << "#pragma clang diagnostic push\n";
583583
os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
584-
if (!typeDecl->isGeneric()) {
585-
// FIXME: generic type support.
584+
585+
if (printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(typeDecl))
586586
os << "template<>\n";
587-
os << "static inline const constexpr bool isUsableInGenericContext<";
588-
printer.printNominalTypeReference(typeDecl,
589-
/*moduleContext=*/nullptr);
590-
os << "> = true;\n";
591-
}
587+
os << "static inline const constexpr bool isUsableInGenericContext<";
588+
printer.printNominalTypeReference(typeDecl,
589+
/*moduleContext=*/nullptr);
590+
os << "> = ";
591+
if (typeDecl->isGeneric()) {
592+
auto signature = typeDecl->getGenericSignature().getCanonicalSignature();
593+
llvm::interleave(
594+
signature.getInnermostGenericParams(), os,
595+
[&](const GenericTypeParamType *genericParamType) {
596+
os << "isUsableInGenericContext<";
597+
printer.printGenericTypeParamTypeName(genericParamType);
598+
os << '>';
599+
},
600+
" && ");
601+
} else
602+
os << "true";
603+
os << ";\n";
604+
592605
os << "#pragma clang diagnostic pop\n";
593606
os << "} // namespace swift\n";
594607
os << "\n";

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

+6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ public func inoutConcreteOpt(_ x: inout GenericOpt<UInt16>) {
9595
// CHECK-NEXT: #endif
9696
// CHECK-NEXT: class SWIFT_SYMBOL("s:8Generics10GenericOptO") GenericOpt;
9797

98+
// CHECK: template<class T_0_0>
99+
// CHECK-NEXT: #ifdef __cpp_concepts
100+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
101+
// CHECK-NEXT: #endif
102+
// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext<Generics::GenericOpt<T_0_0>> = isUsableInGenericContext<T_0_0>;
103+
98104
// CHECK: template<class T_0_0>
99105
// CHECK-NEXT: #ifdef __cpp_concepts
100106
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>

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

+6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ public func inoutConcretePair(_ x: UInt16, _ y: inout GenericPair<UInt16, UInt16
206206
// CHECK-NEXT: #endif
207207
// CHECK-NEXT: class SWIFT_SYMBOL("s:8Generics11GenericPairV") GenericPair;
208208

209+
// CHECK: template<class T_0_0, class T_0_1>
210+
// CHECK-NEXT: #ifdef __cpp_concepts
211+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
212+
// CHECK-NEXT: #endif // __cpp_concepts
213+
// CHECK-NEXT: static inline const constexpr bool isUsableInGenericContext<Generics::GenericPair<T_0_0, T_0_1>> = isUsableInGenericContext<T_0_0> && isUsableInGenericContext<T_0_1>;
214+
209215
// CHECK: template<class T_0_0, class T_0_1>
210216
// CHECK-NEXT: #ifdef __cpp_concepts
211217
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>

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

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
// CHECK-NEXT: #endif
7777
// CHECK-NEXT: class SWIFT_SYMBOL("s:8Generics11GenericPairV") GenericPair;
7878

79+
// CHECK: template<class T_0_0, class T_0_1>
7980
// CHECK: template<class T_0_0, class T_0_1>
8081
// CHECK: template<class T_0_0, class T_0_1>
8182
// CHECK-NEXT: #ifdef __cpp_concepts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -typecheck %s -typecheck -module-name UseOptional -enable-experimental-cxx-interop -emit-clang-header-path %t/stdlib.h
4+
// RUN: %FileCheck %s < %t/stdlib.h
5+
6+
// RUN: %check-interop-cxx-header-in-clang(-DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY %t/stdlib.h -Wno-unused-private-field -Wno-unused-function)
7+
8+
@_expose(Cxx)
9+
public func testOptIntArray() -> [Int]? {
10+
return []
11+
}
12+
13+
// CHECK: SWIFT_INLINE_THUNK swift::Optional<swift::Array<swift::Int>> testOptIntArray()

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

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// CHECK-NEXT: class SWIFT_SYMBOL("s:Sa") Array;
2323
// CHECK: template<class T_0_0>
2424
// CHECK: template<class T_0_0>
25+
// CHECK: template<class T_0_0>
2526
// CHECK-NEXT: #ifdef __cpp_concepts
2627
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
2728
// CHECK-NEXT: #endif

0 commit comments

Comments
 (0)