Skip to content

Commit 0bfe36e

Browse files
committed
cleanup existential type rendering
1 parent 77480ba commit 0bfe36e

6 files changed

Lines changed: 54 additions & 29 deletions

File tree

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extension JNISwift2JavaGenerator {
2626
/// public static class LabeledTuple_fn_x_y<T0, T1>
2727
/// extends org.swift.swiftkit.core.tuple.Tuple2<T0, T1> {
2828
///
29-
/// public LabeledTuple_fn_x_y(T0 $0, T1 $1) { super($0, $1); }
29+
/// public LabeledTuple_fn_x_y(T0 param0, T1 param1) { super(param0, param1); }
3030
/// public T0 x() { return $0; }
3131
/// public T1 y() { return $1; }
3232
/// }
@@ -61,9 +61,12 @@ extension JNISwift2JavaGenerator {
6161
let typeParamsClause = "<\(typeParams.joined(separator: ", "))>"
6262
let baseTupleClass = "org.swift.swiftkit.core.tuple.Tuple\(arity)"
6363

64-
// Constructor parameters: T0 $0, T1 $1, ...
65-
let ctorParams = typeParams.enumerated().map { "\($1) $\($0)" }.joined(separator: ", ")
66-
let superArgs = (0..<arity).map { "$\($0)" }.joined(separator: ", ")
64+
// Constructor parameters: T0 param0, T1 param1, ...
65+
// Use paramN names (not $0, $1) because `$N` is invalid as a Swift parameter name,
66+
// and the wrap-java generator copies parameter names verbatim into Swift wrappers
67+
let paramNames = (0..<arity).map { "param\($0)" }
68+
let ctorParams = zip(typeParams, paramNames).map { "\($0) \($1)" }.joined(separator: ", ")
69+
let superArgs = paramNames.joined(separator: ", ")
6770

6871
printer.printBraceBlock("public static final class \(rawClassName)\(typeParamsClause) extends \(baseTupleClass)\(typeParamsClause)") { printer in
6972
// Constructor

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ extension JNISwift2JavaGenerator {
10821082
indirect case extractSwiftProtocolValue(
10831083
NativeSwiftConversionStep,
10841084
typeMetadataVariableName: NativeSwiftConversionStep,
1085-
protocolNames: [String]
1085+
protocolTypes: [SwiftNominalType]
10861086
)
10871087

10881088
/// Extracts a swift type at a pointer given by a long.
@@ -1228,12 +1228,10 @@ extension JNISwift2JavaGenerator {
12281228
let protocolTypes,
12291229
let allowsJavaImplementations
12301230
):
1231-
let protocolNames = protocolTypes.map { $0.nominalTypeDecl.qualifiedName }
1232-
12331231
let inner = inner.render(&printer, placeholder)
12341232
let variableName = "\(inner)swiftObject$"
1235-
let compositeProtocolName = "(\(protocolNames.joined(separator: " & ")))"
1236-
printer.print("let \(variableName): \(compositeProtocolName)")
1233+
let existentialType = SwiftKitPrinting.renderExistentialType(protocolTypes)
1234+
printer.print("let \(variableName): \(existentialType)")
12371235

12381236
func printStandardJExtractBlock(_ printer: inout CodePrinter) {
12391237
let pointerVariableName = "\(inner)pointer$"
@@ -1247,7 +1245,7 @@ extension JNISwift2JavaGenerator {
12471245
let existentialName = NativeSwiftConversionStep.extractSwiftProtocolValue(
12481246
.constant(pointerVariableName),
12491247
typeMetadataVariableName: .constant(typeMetadataVariableName),
1250-
protocolNames: protocolNames
1248+
protocolTypes: protocolTypes
12511249
).render(&printer, placeholder)
12521250

12531251
printer.print("\(variableName) = \(existentialName)")
@@ -1276,12 +1274,12 @@ extension JNISwift2JavaGenerator {
12761274

12771275
return variableName
12781276

1279-
case .extractSwiftProtocolValue(let inner, let typeMetadataVariableName, let protocolNames):
1277+
case .extractSwiftProtocolValue(let inner, let typeMetadataVariableName, let protocolTypes):
12801278
let inner = inner.render(&printer, placeholder)
12811279
let typeMetadataVariableName = typeMetadataVariableName.render(&printer, placeholder)
12821280
let existentialName = "\(inner)Existential$"
12831281

1284-
let compositeProtocolName = "(\(protocolNames.joined(separator: " & ")))"
1282+
let existentialType = SwiftKitPrinting.renderExistentialType(protocolTypes)
12851283

12861284
// TODO: Remove the _openExistential when we decide to only support language mode v6+
12871285
printer.print(
@@ -1294,10 +1292,10 @@ extension JNISwift2JavaGenerator {
12941292
fatalError("\(inner) memory address was null")
12951293
}
12961294
#if hasFeature(ImplicitOpenExistentials)
1297-
let \(existentialName) = \(inner)RawPointer$.load(as: \(inner)DynamicType$) as! any \(compositeProtocolName)
1295+
let \(existentialName) = \(inner)RawPointer$.load(as: \(inner)DynamicType$) as! \(existentialType)
12981296
#else
1299-
func \(inner)DoLoad<Ty>(_ ty: Ty.Type) -> any \(compositeProtocolName) {
1300-
\(inner)RawPointer$.load(as: ty) as! any \(compositeProtocolName)
1297+
func \(inner)DoLoad<Ty>(_ ty: Ty.Type) -> \(existentialType) {
1298+
\(inner)RawPointer$.load(as: ty) as! \(existentialType)
13011299
}
13021300
let \(existentialName) = _openExistential(\(inner)DynamicType$, do: \(inner)DoLoad)
13031301
#endif

Sources/JExtractSwiftLib/SwiftKit+Printing.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,23 @@ package struct SwiftKitPrinting {
2626
SwiftRuntime.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)")
2727
"""
2828
}
29+
30+
/// Render a parenthesized existential type constraint from nominal protocol types
31+
///
32+
/// For a single protocol: `(any DataProtocol)`
33+
/// For multiple protocols: `(any (DataProtocol & Sendable))`
34+
static func renderExistentialType(_ protocolTypes: [SwiftNominalType]) -> String {
35+
let compositeType: SwiftType
36+
if protocolTypes.count == 1 {
37+
compositeType = .nominal(protocolTypes[0])
38+
} else {
39+
compositeType = .composite(protocolTypes.map { .nominal($0) })
40+
}
41+
return "(\(SwiftType.existential(compositeType)))"
42+
}
2943
}
3044

31-
// ==== ------------------------------------------------------------------------
45+
// ==== -----------------------------------------------------------------------
3246
// Helpers to form names of "well known" SwiftKit generated functions
3347

3448
extension SwiftKitPrinting {

Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,19 @@ extension SwiftType: CustomStringConvertible {
167167
case .tuple(let elements):
168168
return "(\(elements.map(\.description).joined(separator: ", ")))"
169169
case .existential(let constraintType):
170-
return "any \(constraintType)"
170+
switch constraintType {
171+
case .composite:
172+
return "any (\(constraintType))"
173+
default:
174+
return "any \(constraintType)"
175+
}
171176
case .opaque(let constraintType):
172-
return "some \(constraintType)"
177+
switch constraintType {
178+
case .composite:
179+
return "some (\(constraintType))"
180+
default:
181+
return "some \(constraintType)"
182+
}
173183
case .composite(let types):
174184
return types.map(\.description).joined(separator: " & ")
175185
}

Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,18 @@ struct JNIProtocolTests {
133133
"""
134134
@_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2")
135135
public func Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, x: jobject?, y: jobject?) {
136-
let xswiftObject$: (SomeProtocol)
136+
let xswiftObject$: (any SomeProtocol)
137137
if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 {
138138
...
139139
let xpointer$DynamicType$: Any.Type = unsafeBitCast(xpointer$TypeMetadataPointer$, to: Any.Type.self)
140140
guard let xpointer$RawPointer$ = UnsafeMutableRawPointer(bitPattern: Int(Int64(fromJNI: xpointer$, in: environment))) else {
141141
fatalError("xpointer$ memory address was null")
142142
}
143143
#if hasFeature(ImplicitOpenExistentials)
144-
let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol)
144+
let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! (any SomeProtocol)
145145
#else
146-
func xpointer$DoLoad<Ty>(_ ty: Ty.Type) -> any (SomeProtocol) {
147-
xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol)
146+
func xpointer$DoLoad<Ty>(_ ty: Ty.Type) -> (any SomeProtocol) {
147+
xpointer$RawPointer$.load(as: ty) as! (any SomeProtocol)
148148
}
149149
let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad)
150150
#endif
@@ -153,7 +153,7 @@ struct JNIProtocolTests {
153153
else {
154154
xswiftObject$ = _SwiftModule_takeProtocol_x_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: x!, environment: environment))
155155
}
156-
let yswiftObject$: (SomeProtocol)
156+
let yswiftObject$: (any SomeProtocol)
157157
if environment.interface.IsInstanceOf(environment, y, _JNIMethodIDCache.JNISwiftInstance.class) != 0 {
158158
...
159159
yswiftObject$ = ypointer$Existential$
@@ -209,7 +209,7 @@ struct JNIProtocolTests {
209209
"""
210210
@_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2")
211211
public func Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, s: jobject?) {
212-
let sswiftObject$: (SomeProtocol)
212+
let sswiftObject$: (any SomeProtocol)
213213
if environment.interface.IsInstanceOf(environment, s, _JNIMethodIDCache.JNISwiftInstance.class) != 0 {
214214
...
215215
sswiftObject$ = spointer$Existential$
@@ -267,7 +267,7 @@ struct JNIProtocolTests {
267267
"""
268268
@_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2")
269269
public func Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, x: jobject?) {
270-
let xswiftObject$: (SomeProtocol & B)
270+
let xswiftObject$: (any (SomeProtocol & B))
271271
if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 {
272272
let xpointer$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.memoryAddress, [])
273273
let xtypeMetadata$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.typeMetadataAddress, [])
@@ -279,10 +279,10 @@ struct JNIProtocolTests {
279279
fatalError("xpointer$ memory address was null")
280280
}
281281
#if hasFeature(ImplicitOpenExistentials)
282-
let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol & B)
282+
let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! (any (SomeProtocol & B))
283283
#else
284-
func xpointer$DoLoad<Ty>(_ ty: Ty.Type) -> any (SomeProtocol & B) {
285-
xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol & B)
284+
func xpointer$DoLoad<Ty>(_ ty: Ty.Type) -> (any (SomeProtocol & B)) {
285+
xpointer$RawPointer$.load(as: ty) as! (any (SomeProtocol & B))
286286
}
287287
let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad)
288288
#endif

Tests/JExtractSwiftTests/JNI/JNITupleTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct JNITupleTests {
117117
public static final class LabeledTuple_labeledTuple_x_y<T0, T1> extends org.swift.swiftkit.core.tuple.Tuple2<T0, T1> {
118118
""",
119119
"""
120-
public LabeledTuple_labeledTuple_x_y(T0 $0, T1 $1) { super($0, $1); }
120+
public LabeledTuple_labeledTuple_x_y(T0 param0, T1 param1) { super(param0, param1); }
121121
""",
122122
"""
123123
public T0 x() { return $0; }

0 commit comments

Comments
 (0)