Skip to content

Commit 7cc61eb

Browse files
authored
Merge pull request #60915 from hyp/eng/generic-method-in-generic-struct
[interop][SwiftToCxx] add support for generic methods in generic structs
2 parents 1e2af9b + 3e4b52c commit 7cc61eb

File tree

3 files changed

+98
-17
lines changed

3 files changed

+98
-17
lines changed

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -248,17 +248,16 @@ void ClangSyntaxPrinter::printGenericTypeParamTypeName(
248248
void ClangSyntaxPrinter::printGenericSignature(
249249
const CanGenericSignature &signature) {
250250
os << "template<";
251-
llvm::interleaveComma(
252-
signature.getGenericParams(), os,
253-
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
254-
os << "class ";
255-
printGenericTypeParamTypeName(genericParamType);
256-
});
251+
llvm::interleaveComma(signature.getInnermostGenericParams(), os,
252+
[&](const GenericTypeParamType *genericParamType) {
253+
os << "class ";
254+
printGenericTypeParamTypeName(genericParamType);
255+
});
257256
os << ">\n";
258257
os << "requires ";
259258
llvm::interleave(
260-
signature.getGenericParams(), os,
261-
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
259+
signature.getInnermostGenericParams(), os,
260+
[&](const GenericTypeParamType *genericParamType) {
262261
os << "swift::isUsableInGenericContext<";
263262
printGenericTypeParamTypeName(genericParamType);
264263
os << ">";
@@ -270,11 +269,10 @@ void ClangSyntaxPrinter::printGenericSignature(
270269
void ClangSyntaxPrinter::printGenericSignatureParams(
271270
const CanGenericSignature &signature) {
272271
os << '<';
273-
llvm::interleaveComma(
274-
signature.getGenericParams(), os,
275-
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
276-
printGenericTypeParamTypeName(genericParamType);
277-
});
272+
llvm::interleaveComma(signature.getInnermostGenericParams(), os,
273+
[&](const GenericTypeParamType *genericParamType) {
274+
printGenericTypeParamTypeName(genericParamType);
275+
});
278276
os << '>';
279277
}
280278

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ int main() {
5151
// CHECK-NEXT: GenericPair<T, T2>::computeVar::set
5252
// CHECK-NEXT: GenericPair<T, T2>::computeVar::get
5353
// CHECK-NEXT: GenericPair<Int32, Int32>(x: -123456, y: 561)
54+
assert(x.genericMethod<float>(2.25f, 4221) == 2.25f);
55+
// CHECK-NEXT: GenericPair<T, T2>::genericMethod<T>::2.25,4221;
5456
}
5557

5658
{
@@ -77,5 +79,27 @@ int main() {
7779
takeConcretePair(xprime);
7880
// CHECK-NEXT: CONCRETE pair of UInt32: 100000 918 ;
7981
}
82+
83+
{
84+
auto x = GenericPair<int, int>::init(11, 234242, 44);
85+
takeGenericPair(x);
86+
x.method();
87+
assert(x.getY() == 44);
88+
// CHECK-NEXT: GenericPair<T, T2>::init::11,44,234242;
89+
// CHECK-NEXT: GenericPair<Int32, Int32>(x: 11, y: 44)
90+
// CHECK-NEXT: GenericPair<T, T2>::testme::11,44;
91+
auto y = GenericPair<uint32_t, uint32_t>::init(0, -987, 3425);
92+
takeConcretePair(y);
93+
y.method();
94+
assert(y.getY() == 3425);
95+
// CHECK-NEXT: GenericPair<T, T2>::init::0,3425,-987;
96+
// CHECK-NEXT: CONCRETE pair of UInt32: 0 3425 ;
97+
// CHECK-NEXT: GenericPair<T, T2>::testme::0,3425;
98+
auto val = PairOfUInt64::init(0xafafa, 0x32443);
99+
auto valprime = x.genericMethod(val, 4221);
100+
assert(valprime.getX() == val.getX());
101+
assert(valprime.getY() == val.getY());
102+
// CHECK-NEXT: GenericPair<T, T2>::genericMethod<T>::PairOfUInt64(x: 719610, y: 205891),4221;
103+
}
80104
return 0;
81105
}

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

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s -typecheck -module-name Generics -clang-header-expose-public-decls -emit-clang-header-path %t/generics.h
33
// RUN: %FileCheck %s < %t/generics.h
4-
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h)
4+
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h -Wno-reserved-identifier)
55

66
// Check that an instantiation compiles too.
77
// RUN: echo "constexpr int x = sizeof(Generics::GenericPair<int, int>);" >> %t/generics.h
8-
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h)
8+
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h -Wno-reserved-identifier)
99

1010
// RUN: %empty-directory(%t)
1111
// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -module-name Generics -clang-header-expose-public-decls -emit-clang-header-path %t/generics.h
1212
// RUN: %FileCheck %s < %t/generics.h
13-
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h)
13+
// RUN: %check-generic-interop-cxx-header-in-clang(%t/generics.h -Wno-reserved-identifier)
14+
15+
// FIXME: remove the need for -Wno-reserved-identifier
16+
17+
@frozen
18+
public struct PairOfUInt64 {
19+
public let x: UInt64
20+
public let y: UInt64
21+
22+
public init(_ x: UInt64,
23+
_ y: UInt64) {
24+
self.x = x
25+
self.y = y
26+
}
27+
}
1428

1529
@frozen
1630
public struct GenericPair<T, T2> {
1731
var x: T
1832
public var y: T2
1933

34+
init(x: T, y: T2) {
35+
self.x = x
36+
self.y = y
37+
}
38+
39+
public init(_ x: T, _ i: Int, _ y: T2) {
40+
self.x = x
41+
self.y = y
42+
print("GenericPair<T, T2>::init::\(x),\(y),\(i);")
43+
}
44+
2045
public func method() {
2146
let copyOfSelf = self
2247
print("GenericPair<T, T2>::testme::\(x),\(copyOfSelf.y);")
@@ -27,6 +52,11 @@ public struct GenericPair<T, T2> {
2752
y = other.x
2853
}
2954

55+
public func genericMethod<T>(_ x: T, _ y: T2) -> T {
56+
print("GenericPair<T, T2>::genericMethod<T>::\(x),\(y);")
57+
return x
58+
}
59+
3060
public var computedProp: Int {
3161
return 42
3262
}
@@ -78,12 +108,15 @@ public func inoutConcretePair(_ x: UInt32, _ y: inout GenericPair<UInt32, UInt32
78108

79109
// CHECK: SWIFT_EXTERN void $s8Generics11GenericPairV1yq_vg(SWIFT_INDIRECT_RESULT void * _Nonnull, void * _Nonnull , SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // _
80110
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV1yq_vs(const void * _Nonnull value, void * _Nonnull , SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // _
111+
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairVyACyxq_Gx_Siq_tcfC(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, ptrdiff_t i, const void * _Nonnull y, void * _Nonnull , void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // init(_:_:_:)
81112
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV6methodyyF(void * _Nonnull , SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // method()
82113
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV14mutatingMethodyyACyq_xGF(const void * _Nonnull other, void * _Nonnull , SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // mutatingMethod(_:)
114+
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV13genericMethodyqd__qd___q_tlF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, const void * _Nonnull y, void * _Nonnull , void * _Nonnull , SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // genericMethod(_:_:)
83115
// CHECK-NEXT: SWIFT_EXTERN ptrdiff_t $s8Generics11GenericPairV12computedPropSivg(void * _Nonnull , SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // _
84116
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV11computedVarxvg(SWIFT_INDIRECT_RESULT void * _Nonnull, void * _Nonnull , SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // _
85117
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics11GenericPairV11computedVarxvs(const void * _Nonnull newValue, void * _Nonnull , SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // _
86-
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics17inoutConcretePairyys6UInt32V_AA07GenericD0VyA2DGztF(uint32_t x, char * _Nonnull y) SWIFT_NOEXCEPT SWIFT_CALL; // inoutConcretePair(_:_:)
118+
119+
// CHECK: SWIFT_EXTERN void $s8Generics17inoutConcretePairyys6UInt32V_AA07GenericD0VyA2DGztF(uint32_t x, char * _Nonnull y) SWIFT_NOEXCEPT SWIFT_CALL; // inoutConcretePair(_:_:)
87120
// CHECK-NEXT: SWIFT_EXTERN void $s8Generics16inoutGenericPairyyAA0cD0Vyxq_Gz_xtr0_lF(void * _Nonnull x, const void * _Nonnull y, void * _Nonnull , void * _Nonnull ) SWIFT_NOEXCEPT SWIFT_CALL; // inoutGenericPair(_:_:)
88121
// CHECK-NEXT: // Stub struct to be used to pass/return values to/from Swift functions.
89122
// CHECK-NEXT: struct swift_interop_stub_Generics_GenericPair_s6UInt32V_s6UInt32V {
@@ -224,6 +257,13 @@ public func inoutConcretePair(_ x: UInt32, _ y: inout GenericPair<UInt32, UInt32
224257
// CHECK-NEXT: }
225258
// CHECK-NEXT: template<class T_0_0, class T_0_1>
226259
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
260+
// CHECK-NEXT: inline GenericPair<T_0_0, T_0_1> GenericPair<T_0_0, T_0_1>::init(const T_0_0& x, swift::Int i, const T_0_1& y) {
261+
// CHECK-NEXT: return _impl::_impl_GenericPair<T_0_0, T_0_1>::returnNewValue([&](void * _Nonnull result) {
262+
// CHECK-NEXT: _impl::$s8Generics11GenericPairVyACyxq_Gx_Siq_tcfC(result, swift::_impl::getOpaquePointer(x), i, swift::_impl::getOpaquePointer(y), swift::TypeMetadataTrait<T_0_0>::getTypeMetadata(), swift::TypeMetadataTrait<T_0_1>::getTypeMetadata());
263+
// CHECK-NEXT: });
264+
// CHECK-NEXT: }
265+
// CHECK-NEXT: template<class T_0_0, class T_0_1>
266+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
227267
// CHECK-NEXT: inline void GenericPair<T_0_0, T_0_1>::method() const {
228268
// CHECK-NEXT: return _impl::$s8Generics11GenericPairV6methodyyF(swift::TypeMetadataTrait<GenericPair<T_0_0, T_0_1>>::getTypeMetadata(), _getOpaquePointer());
229269
// CHECK-NEXT: }
@@ -234,6 +274,25 @@ public func inoutConcretePair(_ x: UInt32, _ y: inout GenericPair<UInt32, UInt32
234274
// CHECK-NEXT: }
235275
// CHECK-NEXT: template<class T_0_0, class T_0_1>
236276
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
277+
// CHECK-NEXT: template<class T_1_0>
278+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_1_0>
279+
// CHECK-NEXT: inline T_1_0 GenericPair<T_0_0, T_0_1>::genericMethod(const T_1_0& x, const T_0_1& y) const {
280+
// CHECK-NEXT: if constexpr (std::is_base_of<::swift::_impl::RefCountedClass, T_1_0>::value) {
281+
// CHECK-NEXT: void *returnValue;
282+
// CHECK-NEXT: _impl::$s8Generics11GenericPairV13genericMethodyqd__qd___q_tlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::TypeMetadataTrait<GenericPair<T_0_0, T_0_1>>::getTypeMetadata(), swift::TypeMetadataTrait<T_1_0>::getTypeMetadata(), _getOpaquePointer());
283+
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_1_0>::type::makeRetained(returnValue);
284+
// CHECK-NEXT: } else if constexpr (::swift::_impl::isValueType<T_1_0>) {
285+
// CHECK-NEXT: return ::swift::_impl::implClassFor<T_1_0>::type::returnNewValue([&](void * _Nonnull returnValue) {
286+
// CHECK-NEXT: _impl::$s8Generics11GenericPairV13genericMethodyqd__qd___q_tlF(returnValue, swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::TypeMetadataTrait<GenericPair<T_0_0, T_0_1>>::getTypeMetadata(), swift::TypeMetadataTrait<T_1_0>::getTypeMetadata(), _getOpaquePointer());
287+
// CHECK-NEXT: });
288+
// CHECK-NEXT: } else {
289+
// CHECK-NEXT: T_1_0 returnValue;
290+
// CHECK-NEXT: _impl::$s8Generics11GenericPairV13genericMethodyqd__qd___q_tlF(reinterpret_cast<void *>(&returnValue), swift::_impl::getOpaquePointer(x), swift::_impl::getOpaquePointer(y), swift::TypeMetadataTrait<GenericPair<T_0_0, T_0_1>>::getTypeMetadata(), swift::TypeMetadataTrait<T_1_0>::getTypeMetadata(), _getOpaquePointer());
291+
// CHECK-NEXT: return returnValue;
292+
// CHECK-NEXT: }
293+
// CHECK-NEXT: }
294+
// CHECK-NEXT: template<class T_0_0, class T_0_1>
295+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
237296
// CHECK-NEXT: inline swift::Int GenericPair<T_0_0, T_0_1>::getComputedProp() const {
238297
// CHECK-NEXT: return _impl::$s8Generics11GenericPairV12computedPropSivg(swift::TypeMetadataTrait<GenericPair<T_0_0, T_0_1>>::getTypeMetadata(), _getOpaquePointer());
239298
// CHECK-NEXT: }

0 commit comments

Comments
 (0)