From 7c0ec17ab965a94526b187751917d110e9d2750a Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 2 Apr 2026 14:29:07 +0900 Subject: [PATCH 1/4] jextract: LabeledTuple support! We now support passing and returing labelled tuples like (a: Int, b: Stirng) etc. This is important for being able to quickly port over code from swift to Java using the same libraries as we don't have to special case the labelled tuples and move them over to positional use. These ad hoc tuple types are printed per method. They would conflict if you use the same shape twice in a method right now... I'm not seeing much of that use so ignored it for now. The new tuples inherit from TupleN so Java code can just use them as positional when necessary, also for passing them along to other methods. The change is large because I also cleaned up type printing, I think printing full qualified type names is good here, better nor risk clashes. --- .../java/com/example/swift/TupleTest.java | 13 ++- ...t2JavaGenerator+JavaBindingsPrinting.swift | 6 +- ...MSwift2JavaGenerator+JavaTranslation.swift | 11 ++- .../FFM/FFMSwift2JavaGenerator.swift | 2 +- ...t2JavaGenerator+JavaBindingsPrinting.swift | 15 ++++ ...ISwift2JavaGenerator+JavaTranslation.swift | 75 +++++++++++++---- ...NISwift2JavaGenerator+LabelledTuples.swift | 80 +++++++++++++++++++ ...wift2JavaGenerator+NativeTranslation.swift | 26 +++--- .../TranslatedFunctionDecl+NamedTuples.swift | 44 ++++++++++ .../JavaTypes/JavaType+Collections.swift | 28 +++++++ .../JavaTypes/JavaType+Exceptions.swift | 29 +++++++ .../JavaTypes/JavaType+Futures.swift | 23 ++++++ .../JavaTypes/JavaType+SwiftKit.swift | 48 ----------- .../JavaTypes/JavaType+Tuples.swift | 58 ++++++++++++++ Sources/SwiftJavaToolLib/JavaTranslator.swift | 1 - .../org/swift/swiftkit/core/tuple/Tuple1.java | 2 +- .../swift/swiftkit/core/tuple/Tuple10.java | 2 +- .../swift/swiftkit/core/tuple/Tuple11.java | 2 +- .../swift/swiftkit/core/tuple/Tuple12.java | 2 +- .../swift/swiftkit/core/tuple/Tuple13.java | 2 +- .../swift/swiftkit/core/tuple/Tuple14.java | 2 +- .../swift/swiftkit/core/tuple/Tuple15.java | 2 +- .../swift/swiftkit/core/tuple/Tuple16.java | 2 +- .../swift/swiftkit/core/tuple/Tuple17.java | 2 +- .../swift/swiftkit/core/tuple/Tuple18.java | 2 +- .../swift/swiftkit/core/tuple/Tuple19.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple2.java | 2 +- .../swift/swiftkit/core/tuple/Tuple20.java | 2 +- .../swift/swiftkit/core/tuple/Tuple21.java | 2 +- .../swift/swiftkit/core/tuple/Tuple22.java | 2 +- .../swift/swiftkit/core/tuple/Tuple23.java | 2 +- .../swift/swiftkit/core/tuple/Tuple24.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple3.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple4.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple5.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple6.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple7.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple8.java | 2 +- .../org/swift/swiftkit/core/tuple/Tuple9.java | 2 +- .../FFM/FFMTupleTests.swift | 10 +-- .../JNI/JNIGenericCombinationTests.swift | 12 +-- .../JNI/JNITupleTests.swift | 28 +++++-- 42 files changed, 432 insertions(+), 125 deletions(-) create mode 100644 Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift create mode 100644 Sources/JExtractSwiftLib/JNI/TranslatedFunctionDecl+NamedTuples.swift create mode 100644 Sources/JExtractSwiftLib/JavaTypes/JavaType+Collections.swift create mode 100644 Sources/JExtractSwiftLib/JavaTypes/JavaType+Exceptions.swift create mode 100644 Sources/JExtractSwiftLib/JavaTypes/JavaType+Futures.swift create mode 100644 Sources/JExtractSwiftLib/JavaTypes/JavaType+Tuples.swift diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/TupleTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/TupleTest.java index 4b8fa675c..a3ad4b197 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/TupleTest.java +++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/TupleTest.java @@ -14,7 +14,6 @@ package com.example.swift; -import com.example.swift.MySwiftLibrary; import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.tuple.Tuple2; import org.swift.swiftkit.core.tuple.Tuple3; @@ -38,9 +37,19 @@ void takePair() { @Test void labeledTuple() { - Tuple2 result = MySwiftLibrary.labeledTuple(); + var result = MySwiftLibrary.labeledTuple(); + // Access via named accessors + assertEquals(10, result.x()); + assertEquals(20, result.y()); + // Positional access still works (inherited from Tuple2) assertEquals(10, result.$0); assertEquals(20, result.$1); + + // The labelled tuple is a subclass of Tuple2 + assertInstanceOf(Tuple2.class, result); + // And the generic types match positionally as well + @SuppressWarnings("unused") + Tuple2 check = result; } @Test diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index c3b60943a..cb7eac727 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -388,10 +388,10 @@ extension FFMSwift2JavaGenerator { // If a Swift function is 'throws' we throw a checked error for the Java side // TODO: When we support typed throws on Swift side we'll want to throw the right type here instead if translatedSignature.isThrowing { - throwsClauses.append(JavaType.swiftJavaErrorException.simpleClassName) + throwsClauses.append(JavaType.swiftJavaErrorException.className!) } if translatedSignature.canThrowSwiftIntegerOverflowException { - throwsClauses.append(JavaType.swiftIntegerOverflowException.simpleClassName) + throwsClauses.append(JavaType.swiftIntegerOverflowException.className!) } let throwsClause = throwsClauses.isEmpty ? "" : " throws \(throwsClauses.joined(separator: ", "))" @@ -522,7 +522,7 @@ extension FFMSwift2JavaGenerator { func printErrorCheck(_ printer: inout CodePrinter) { guard translatedSignature.isThrowing else { return } printer.printIfBlock("!result$throws.get(ValueLayout.ADDRESS, 0).equals(MemorySegment.NULL)") { printer in - printer.print("throw new \(JavaType.swiftJavaErrorException.simpleClassName)(result$throws.get(ValueLayout.ADDRESS, 0), AllocatingSwiftArena.ofAuto());") + printer.print("throw new \(JavaType.swiftJavaErrorException.className!)(result$throws.get(ValueLayout.ADDRESS, 0), AllocatingSwiftArena.ofAuto());") } } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index bce460f66..c750fdc0a 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -335,7 +335,8 @@ extension FFMSwift2JavaGenerator { // Result. let result = try self.translateResult( swiftResult: swiftSignature.result, - loweredResult: loweredFunctionSignature.result + loweredResult: loweredFunctionSignature.result, + methodName: methodName ) return TranslatedFunctionSignature( @@ -620,8 +621,7 @@ extension FFMSwift2JavaGenerator { case .char: ("Optional", "toOptionalSegmentCharacter") case .short: ("Optional", "toOptionalSegmentShort") case .float: ("Optional", "toOptionalSegmentFloat") - default: - throw JavaTranslationError.unhandledType(known: .optional(swiftType)) + default: throw JavaTranslationError.unhandledType(known: .optional(swiftType)) } return TranslatedParameter( javaParameters: [ @@ -689,7 +689,8 @@ extension FFMSwift2JavaGenerator { /// Translate a Swift API result to the user-facing Java API result. func translateResult( swiftResult: SwiftResult, - loweredResult: LoweredResult + loweredResult: LoweredResult, + methodName: String ) throws -> TranslatedResult { let swiftType = swiftResult.type // If the result type should cause any annotations on the method, include them here. @@ -844,6 +845,7 @@ extension FFMSwift2JavaGenerator { case .tuple(let elements): return try translateTupleResult( + methodName: methodName, elements: elements, resultAnnotations: resultAnnotations ) @@ -856,6 +858,7 @@ extension FFMSwift2JavaGenerator { /// Tuple results: indirect `MemorySegment` per element, then `new TupleN<…>(…)` (mirrors JNI out-arrays). func translateTupleResult( + methodName: String, elements: [SwiftTupleElement], resultAnnotations: [JavaAnnotation] ) throws -> TranslatedResult { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 18dc222e4..6f5f1b8c6 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -151,7 +151,7 @@ extension FFMSwift2JavaGenerator { /// Returns the Java class name for a nominal type, applying known-type overrides func javaClassName(for decl: ImportedNominalType) -> String { if decl.swiftNominal.knownTypeKind == .swiftJavaError { - return JavaType.swiftJavaErrorException.simpleClassName + return JavaType.swiftJavaErrorException.className! } return decl.swiftNominal.name } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 3a46d81d5..8f6d97a67 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -524,6 +524,10 @@ extension JNISwift2JavaGenerator { printJavaBindingWrapperHelperClass(&printer, decl) printJavaBindingWrapperMethod(&printer, decl, skipMethodBody: skipMethodBody) + + // Print any additional types we may need to emit, e.g. named tuples are emitted as static classes + // right next to the func that is using them. + printNecessarySupportTypes(&printer, decl) } /// Print the helper type container for a user-facing Java API. @@ -566,6 +570,17 @@ extension JNISwift2JavaGenerator { ) } + private func printNecessarySupportTypes( + _ printer: inout CodePrinter, + _ decl: ImportedFunc + ) { + let translatedDecl = translatedDecl(for: decl)! + + for labeledTuple in translatedDecl.usedLabeledTuples { + printAdHocLabeledTupleStaticClass(&printer, labeledTuple) + } + } + private func printJavaBindingWrapperMethod( _ printer: inout CodePrinter, _ decl: ImportedFunc, diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 3cd1db3e0..6a72bf6b0 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -115,12 +115,12 @@ extension JNISwift2JavaGenerator { let conversions = try enumCase.parameters.enumerated().map { idx, parameter in let resultName = parameter.name ?? "arg\(idx)" let result = SwiftResult(convention: .direct, type: parameter.type) - var translatedResult = try self.translate(swiftResult: result, resultName: resultName) + var translatedResult = try self.translate(swiftResult: result, methodName: methodName, resultName: resultName) translatedResult.conversion = .replacingPlaceholder( translatedResult.conversion, placeholder: "$nativeParameters.\(resultName)", ) - let nativeResult = try nativeTranslation.translate(swiftResult: result, resultName: resultName) + let nativeResult = try nativeTranslation.translate(swiftResult: result, methodName: methodName, resultName: resultName) return (translated: translatedResult, native: nativeResult) } @@ -319,7 +319,7 @@ extension JNISwift2JavaGenerator { ) } - let translatedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType)) + let translatedResult = try translate(swiftResult: SwiftResult(convention: .direct, type: swiftType.resultType), methodName: name) return TranslatedFunctionType( name: name, @@ -367,6 +367,7 @@ extension JNISwift2JavaGenerator { let resultType = try translate( swiftResult: functionSignature.result, + methodName: methodName, genericParameters: functionSignature.genericParameters, genericRequirements: functionSignature.genericRequirements, ) @@ -628,7 +629,9 @@ extension JNISwift2JavaGenerator { parameterPosition: parameterPosition, ) - case .tuple, .composite: + case .tuple: + throw JavaTranslationError.emptyTuple() + case .composite: throw JavaTranslationError.unsupportedSwiftType(swiftType) } } @@ -885,6 +888,7 @@ extension JNISwift2JavaGenerator { func translate( swiftResult: SwiftResult, + methodName: String, resultName: String = "result", genericParameters: [SwiftGenericParameterDeclaration] = [], genericRequirements: [SwiftGenericRequirement] = [], @@ -1017,6 +1021,7 @@ extension JNISwift2JavaGenerator { case .tuple(let elements) where !elements.isEmpty: return try translateTupleResult( + methodName: methodName, elements: elements, resultName: resultName, genericParameters: genericParameters, @@ -1149,7 +1154,9 @@ extension JNISwift2JavaGenerator { } } + /// - Parameter: methodName is necessary because we may need to form an ad-hoc one off type if e.g. named tuples are used. func translateTupleResult( + methodName: String, elements: [SwiftTupleElement], resultName: String = "result", genericParameters: [SwiftGenericParameterDeclaration], @@ -1167,18 +1174,30 @@ extension JNISwift2JavaGenerator { // Determine the Java type for this element let elementResult = try translate( swiftResult: .init(convention: .indirect, type: element.type), + methodName: methodName, resultName: outParamName, genericParameters: genericParameters, genericRequirements: genericRequirements, ) + // out names are always ...$N, no need to use real named tuple names here, this is just for the thunk elementOutParamNames.append(outParamName) + // FIXME: More accurate determination of whether the result is direct or indirect if elementResult.outParameters.isEmpty { - // Convert direct result to indirect result - let arrayType: JavaType = .array(elementResult.javaType) + // Convert direct result to indirect result. + // For class types (nominal types), the JNI native representation is 'long' + // (a memory address), not the wrapper class type + let nativeElementType: JavaType + switch elementResult.javaType { + case .class: + nativeElementType = .long + default: + nativeElementType = elementResult.javaType + } + let arrayType: JavaType = .array(nativeElementType) outParameters.append( - OutParameter(name: outParamName, type: arrayType, allocation: .newArray(elementResult.javaType, size: 1)) + OutParameter(name: outParamName, type: arrayType, allocation: .newArray(nativeElementType, size: 1)) ) elementConversions.append(elementResult.conversion) } else { @@ -1188,19 +1207,36 @@ extension JNISwift2JavaGenerator { elementJavaTypes.append(elementResult.javaType) } - let javaResultType: JavaType = .tuple(elementTypes: elementJavaTypes) - let fullTupleClassName = "org.swift.swiftkit.core.tuple.Tuple\(arity)" + let isNamedTuple = elements.contains { $0.label != nil } + let names = elements.enumerated().map { idx, element in + if let label = element.label { + label + } else { + "$\(idx)" + } + } let tupleElements: [(outParamName: String, elementConversion: JavaNativeConversionStep)] = zip(elementOutParamNames, elementConversions).map { ($0, $1) } + let javaResultType: JavaType = + if isNamedTuple { + .labeledTuple(methodName, names: names, elementTypes: elementJavaTypes) + } else { + .tuple(elementTypes: elementJavaTypes) + } + + let javaNativeConversionStep: JavaNativeConversionStep = + .tupleFromOutParams( + // try!-safe, because we know the result type is a class here (a Tuple of some form) + tupleClassName: "\(javaResultType)", + elements: tupleElements + ) + return TranslatedResult( javaType: javaResultType, outParameters: outParameters, - conversion: .tupleFromOutParams( - tupleClassName: fullTupleClassName, - elements: tupleElements - ) + conversion: javaNativeConversionStep ) } @@ -1285,6 +1321,7 @@ extension JNISwift2JavaGenerator { let wrappedValueResult = try translate( swiftResult: SwiftResult(convention: .direct, type: swiftType), + methodName: "", resultName: resultName + "Wrapped$", genericParameters: genericParameters, genericRequirements: genericRequirements, @@ -1945,7 +1982,7 @@ extension JNISwift2JavaGenerator { let converted = element.elementConversion.render(&printer, "\(element.outParamName)[0]") args.append(converted) } - return "new \(tupleClassName)<>(\(args.joined(separator: ", ")))" + return "new \(tupleClassName)(\(args.joined(separator: ", ")))" case .placeToVar(let inner, let name): let inner = inner.render(&printer, placeholder) @@ -2025,6 +2062,7 @@ extension JNISwift2JavaGenerator { enum JavaTranslationError: Error { case unsupportedSwiftType(SwiftType, fileID: String, line: Int) + static func unsupportedSwiftType( _ type: SwiftType, _fileID: String = #fileID, @@ -2060,5 +2098,14 @@ extension JNISwift2JavaGenerator { /// Set type requires exactly one generic type argument (element). case setRequiresElementType(SwiftType) + + /// Empty tuples are not supported in lowering, they should be treated as Void + case emptyTuple(file: String, line: Int) + static func emptyTuple( + _file: String = #fileID, + _line: Int = #line + ) -> JavaTranslationError { + .emptyTuple(file: _file, line: _line) + } } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift new file mode 100644 index 000000000..64c4cf3a2 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import CodePrinting +import SwiftJavaJNICore + +extension JNISwift2JavaGenerator { + + /// Print an ad-hoc static inner class for a labeled tuple type. + /// + /// Swift labeled tuples look like this: `(x: Int32, y: Int32)`. + /// + /// We need to produce a Java class that extends the positional `TupleN` and adds named accessor methods: + /// ```java + /// public static class LabeledTuple_fn_x_y + /// extends org.swift.swiftkit.core.tuple.Tuple2 { + /// + /// public LabeledTuple_fn_x_y(T0 $0, T1 $1) { super($0, $1); } + /// public T0 x() { return $0; } + /// public T1 y() { return $1; } + /// } + /// ``` + func printAdHocLabeledTupleStaticClass( + _ printer: inout CodePrinter, + _ labeledTupleType: JavaType + ) { + guard labeledTupleType.isSwiftJavaLabeledTuple else { + return + } + guard case .class(_, let rawClassName, let genericArgs) = labeledTupleType else { + return + } + + let arity = genericArgs.count + let elementNames: [String] + + // Element names are embedded in the class name after "LabeledTuple__" + // We need to extract the last `arity` underscore-separated components + let parts = rawClassName.split(separator: "_") + // parts: ["LabeledTuple", baseName, name0, name1, ...] + // The first part is "LabeledTuple", second is baseName, rest are element names + if parts.count >= 2 + arity { + elementNames = parts.suffix(arity).map(String.init) + } else { + elementNames = (0.." + let baseTupleClass = "org.swift.swiftkit.core.tuple.Tuple\(arity)" + + // Constructor parameters: T0 $0, T1 $1, ... + let ctorParams = typeParams.enumerated().map { "\($1) $\($0)" }.joined(separator: ", ") + let superArgs = (0.. NativeResult { let discriminatorName = "\(resultName)_discriminator$" @@ -592,6 +594,7 @@ extension JNISwift2JavaGenerator { convention: .direct, type: swiftType ), + methodName: methodName, resultName: resultName + "Wrapped" ) @@ -692,6 +695,7 @@ extension JNISwift2JavaGenerator { func translate( swiftResult: SwiftResult, + methodName: String, resultName: String = "result" ) throws -> NativeResult { switch swiftResult.type { @@ -699,7 +703,7 @@ extension JNISwift2JavaGenerator { if let knownType = nominalType.asKnownType { switch knownType { case .optional(let wrapped): - return try translateOptionalResult(wrappedType: wrapped, resultName: resultName) + return try translateOptionalResult(wrappedType: wrapped, methodName: methodName, resultName: resultName) case .array(let elementType): return try translateArrayResult(elementType: elementType, resultName: resultName) @@ -784,7 +788,7 @@ extension JNISwift2JavaGenerator { ) case .tuple(let elements) where !elements.isEmpty: - return try translateTupleResult(elements: elements, resultName: resultName) + return try translateTupleResult(methodName: methodName, elements: elements, resultName: resultName) case .metatype, .tuple, .function, .existential, .opaque, .genericParameter, .composite: throw JavaTranslationError.unsupportedSwiftType(swiftResult.type) @@ -792,6 +796,7 @@ extension JNISwift2JavaGenerator { } func translateTupleResult( + methodName: String, elements: [SwiftTupleElement], resultName: String ) throws -> NativeResult { @@ -804,6 +809,7 @@ extension JNISwift2JavaGenerator { // Get the JNI type for this element let elementResult = try translate( swiftResult: .init(convention: .indirect, type: element.type), + methodName: methodName, resultName: outParamName ) @@ -1164,8 +1170,8 @@ extension JNISwift2JavaGenerator { /// `SwiftType(inner)` indirect case labelessInitializer(NativeSwiftConversionStep, swiftType: SwiftType) - /// Converts a jbyteArray to UnsafeRawBufferPointer via GetByteArrayElements - indirect case jniByteArrayToUnsafeRawBufferPointer(NativeSwiftConversionStep, name: String) + /// Converts a jbyteArray to UnsafeRawBufferPointer or UnsafeMutableRawBufferPointer via GetByteArrayElements + indirect case jniByteArrayToUnsafeRawBufferPointer(NativeSwiftConversionStep, name: String, mutable: Bool) /// Constructs a Swift tuple from individually-converted elements. /// E.g. `(label0: conv0, conv1)` for `(label0: Int, String)` @@ -1726,17 +1732,19 @@ extension JNISwift2JavaGenerator { let inner = inner.render(&printer, placeholder) return "\(swiftType)(\(inner))" - case .jniByteArrayToUnsafeRawBufferPointer(let inner, let name): + case .jniByteArrayToUnsafeRawBufferPointer(let inner, let name, let mutable): let inner = inner.render(&printer, placeholder) let countVar = "\(name)$count" let ptrVar = "\(name)$ptr" let rbpVar = "\(name)$rbp" + let bufferPointerType = mutable ? "UnsafeMutableRawBufferPointer" : "UnsafeRawBufferPointer" + let releaseMode = mutable ? "0" : "jint(JNI_ABORT)" printer.print( """ let \(countVar) = Int(environment.interface.GetArrayLength(environment, \(inner))) let \(ptrVar) = environment.interface.GetByteArrayElements(environment, \(inner), nil)! - defer { environment.interface.ReleaseByteArrayElements(environment, \(inner), \(ptrVar), jint(JNI_ABORT)) } - let \(rbpVar) = UnsafeRawBufferPointer(start: \(ptrVar), count: \(countVar)) + defer { environment.interface.ReleaseByteArrayElements(environment, \(inner), \(ptrVar), \(releaseMode)) } + let \(rbpVar) = \(bufferPointerType)(start: \(ptrVar), count: \(countVar)) """ ) return rbpVar diff --git a/Sources/JExtractSwiftLib/JNI/TranslatedFunctionDecl+NamedTuples.swift b/Sources/JExtractSwiftLib/JNI/TranslatedFunctionDecl+NamedTuples.swift new file mode 100644 index 000000000..cd0236fa5 --- /dev/null +++ b/Sources/JExtractSwiftLib/JNI/TranslatedFunctionDecl+NamedTuples.swift @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaJNICore + +extension JNISwift2JavaGenerator.TranslatedFunctionDecl { + + /// Returns any used labeled tuple types that this function uses + var usedLabeledTuples: [JavaType] { + var result: [JavaType] = [] + collectLabeledTuples(from: translatedFunctionSignature.resultType.javaType, into: &result) + for param in translatedFunctionSignature.parameters { + collectLabeledTuples(from: param.parameter.type.javaType, into: &result) + } + return result + } +} + +private func collectLabeledTuples(from type: JavaType, into result: inout [JavaType]) { + switch type { + case .class(_, _, let typeParameters): + if type.isSwiftJavaLabeledTuple { + result.append(type) + } + for ty in typeParameters { + collectLabeledTuples(from: ty, into: &result) + } + case .array(let element): + collectLabeledTuples(from: element, into: &result) + default: + break + } +} diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+Collections.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Collections.swift new file mode 100644 index 000000000..18f59fa4d --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Collections.swift @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaJNICore + +extension JavaType { + + /// The description of the type org.swift.swiftkit.core.collections.SwiftDictionaryMap + static func swiftDictionaryMap(_ K: JavaType, _ V: JavaType) -> JavaType { + .class(package: "org.swift.swiftkit.core.collections", name: "SwiftDictionaryMap", typeParameters: [K.boxedType, V.boxedType]) + } + + /// The description of the type org.swift.swiftkit.core.collections.SwiftSet + static func swiftSet(_ E: JavaType) -> JavaType { + .class(package: "org.swift.swiftkit.core.collections", name: "SwiftSet", typeParameters: [E.boxedType]) + } +} diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+Exceptions.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Exceptions.swift new file mode 100644 index 000000000..a32d8dc72 --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Exceptions.swift @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaJNICore + +extension JavaType { + + /// The Java exception type for the Swift error wrapper + static var swiftJavaErrorException: JavaType { + .class(package: "org.swift.swiftkit.ffm.generated", name: "SwiftJavaErrorException") + } + + /// The Java exception type for integer overflow checks + static var swiftIntegerOverflowException: JavaType { + .class(package: "org.swift.swiftkit.core", name: "SwiftIntegerOverflowException") + } + +} diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+Futures.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Futures.swift new file mode 100644 index 000000000..3492a3980 --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Futures.swift @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaJNICore + +extension JavaType { + + /// The description of the type org.swift.swiftkit.core.SimpleCompletableFuture + static func simpleCompletableFuture(_ T: JavaType) -> JavaType { + .class(package: "org.swift.swiftkit.core", name: "SimpleCompletableFuture", typeParameters: [T.boxedType]) + } +} diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift index 87e774812..850768c25 100644 --- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift @@ -16,57 +16,9 @@ import SwiftJavaJNICore extension JavaType { - /// The description of the type org.swift.swiftkit.core.SimpleCompletableFuture - static func simpleCompletableFuture(_ T: JavaType) -> JavaType { - .class(package: "org.swift.swiftkit.core", name: "SimpleCompletableFuture", typeParameters: [T.boxedType]) - } - - /// The maximum supported tuple arity. - static let maxTupleArity = 24 - - /// The description of the type org.swift.swiftkit.core.tuple.TupleN - static func tuple(elementTypes: [JavaType]) -> JavaType { - let arity = elementTypes.count - guard arity <= maxTupleArity else { - fatalError("Tuple arity \(arity) exceeds maximum supported arity of \(maxTupleArity)") - } - let genericParams = elementTypes.map(\.boxedName).joined(separator: ", ") - return .class(package: "org.swift.swiftkit.core.tuple", name: "Tuple\(arity)<\(genericParams)>") - } - - /// The description of the type org.swift.swiftkit.core.collections.SwiftDictionaryMap - static func swiftDictionaryMap(_ K: JavaType, _ V: JavaType) -> JavaType { - .class(package: "org.swift.swiftkit.core.collections", name: "SwiftDictionaryMap", typeParameters: [K.boxedType, V.boxedType]) - } - - /// The description of the type org.swift.swiftkit.core.collections.SwiftSet - static func swiftSet(_ E: JavaType) -> JavaType { - .class(package: "org.swift.swiftkit.core.collections", name: "SwiftSet", typeParameters: [E.boxedType]) - } - /// A container for receiving Swift generic instances. static var _OutSwiftGenericInstance: JavaType { .class(package: "org.swift.swiftkit.core", name: "_OutSwiftGenericInstance") } - // ==== ------------------------------------------------------------------- - // MARK: Exception types - - /// The Java exception type for the Swift error wrapper - static var swiftJavaErrorException: JavaType { - .class(package: "org.swift.swiftkit.ffm.generated", name: "SwiftJavaErrorException") - } - - /// The Java exception type for integer overflow checks - static var swiftIntegerOverflowException: JavaType { - .class(package: "org.swift.swiftkit.core", name: "SwiftIntegerOverflowException") - } - - /// Extract the simple class name from a `.class` JavaType - var simpleClassName: String { - switch self { - case .class(_, let name, _): name - default: fatalError("simpleClassName is only available for .class types, was: \(self)") - } - } } diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+Tuples.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Tuples.swift new file mode 100644 index 000000000..99641a4ab --- /dev/null +++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+Tuples.swift @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import SwiftJavaJNICore + +extension JavaType { + + /// The maximum supported tuple arity. + static let maxTupleArity = 24 + + /// The description of the type org.swift.swiftkit.core.tuple.TupleN + static func tuple(elementTypes: [JavaType]) -> JavaType { + let arity = elementTypes.count + guard arity <= maxTupleArity else { + fatalError("Tuple arity \(arity) exceeds maximum supported arity of \(maxTupleArity)") + } + return .class( + package: "org.swift.swiftkit.core.tuple", + name: "Tuple\(arity)", + typeParameters: elementTypes.map(\.boxedType) + ) + } + + /// The description of a labeled tuple type: LabeledTuple_someName_a_b_c + static func labeledTuple(_ baseName: String, names: [String], elementTypes: [JavaType]) -> JavaType { + assert(names.count == elementTypes.count, "Names count (\(names.count)) must be equal types count (\(elementTypes.count))") + + let arity = elementTypes.count + guard arity <= maxTupleArity else { + fatalError("Tuple arity \(arity) exceeds maximum supported arity of \(maxTupleArity)") + } + let joinedNames = names.joined(separator: "_") + return .class( + package: nil, + name: "LabeledTuple_\(baseName)_\(joinedNames)", + typeParameters: elementTypes.map(\.boxedType) + ) + } + + /// Whether this type is a labeled tuple type generated by swift-java + var isSwiftJavaLabeledTuple: Bool { + if case .class(_, let name, _) = self { + return name.hasPrefix("LabeledTuple_") + } + return false + } +} diff --git a/Sources/SwiftJavaToolLib/JavaTranslator.swift b/Sources/SwiftJavaToolLib/JavaTranslator.swift index 03a5e557d..0020e99a2 100644 --- a/Sources/SwiftJavaToolLib/JavaTranslator.swift +++ b/Sources/SwiftJavaToolLib/JavaTranslator.swift @@ -106,7 +106,6 @@ package class JavaTranslator { } } -// MARK: Defaults extension JavaTranslator { /// Default formatting options. private static let defaultFormat = BasicFormat(indentationWidth: .spaces(2)) diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple1.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple1.java index 45fc8253d..6629c500b 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple1.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple1.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 1-element tuple type (T0). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple1 { +public class Tuple1 { public final T0 $0; public Tuple1(T0 $0) { diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple10.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple10.java index 1bc978d61..7adc90d94 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple10.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple10.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 10-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple10 { +public class Tuple10 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple11.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple11.java index df3ab5755..5e6520a5d 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple11.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple11.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 11-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple11 { +public class Tuple11 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple12.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple12.java index 10b6dc5d6..a916665e3 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple12.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple12.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 12-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple12 { +public class Tuple12 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple13.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple13.java index 8b3f71366..dc31991ea 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple13.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple13.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 13-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple13 { +public class Tuple13 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple14.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple14.java index f6dceaf09..dca55eb54 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple14.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple14.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 14-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple14 { +public class Tuple14 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple15.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple15.java index 32efe7178..9f8edd9a8 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple15.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple15.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 15-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple15 { +public class Tuple15 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple16.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple16.java index 62b6933b8..ba76df9e3 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple16.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple16.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 16-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple16 { +public class Tuple16 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple17.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple17.java index e38f3c328..557d26706 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple17.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple17.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 17-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple17 { +public class Tuple17 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple18.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple18.java index 7f7f6ba35..1324e0efa 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple18.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple18.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 18-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple18 { +public class Tuple18 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple19.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple19.java index aac156b74..c7651ed19 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple19.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple19.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 19-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple19 { +public class Tuple19 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple2.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple2.java index d437ef437..9bb14bbbe 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple2.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple2.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 2-element tuple type (T0, T1). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple2 { +public class Tuple2 { public final T0 $0; public final T1 $1; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple20.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple20.java index 9daa810b0..a65c7fb6e 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple20.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple20.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 20-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple20 { +public class Tuple20 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple21.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple21.java index 552b6b676..061128d0b 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple21.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple21.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 21-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple21 { +public class Tuple21 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple22.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple22.java index 42545d859..1e3a1bfd0 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple22.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple22.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 22-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple22 { +public class Tuple22 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple23.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple23.java index 1df45d0af..d0c981d06 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple23.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple23.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 23-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple23 { +public class Tuple23 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple24.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple24.java index 30a7dbf25..62923bef7 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple24.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple24.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 24-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple24 { +public class Tuple24 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple3.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple3.java index 513af2efb..0717c65c8 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple3.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple3.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 3-element tuple type (T0, T1, T2). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple3 { +public class Tuple3 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple4.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple4.java index ca3943905..781bc3561 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple4.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple4.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 4-element tuple type (T0, T1, T2, T3). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple4 { +public class Tuple4 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple5.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple5.java index ac592e7f9..173b9ba72 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple5.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple5.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 5-element tuple type (T0, T1, T2, T3, T4). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple5 { +public class Tuple5 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple6.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple6.java index c0a705d11..ebe44ecd0 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple6.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple6.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 6-element tuple type (T0, T1, T2, T3, T4, T5). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple6 { +public class Tuple6 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple7.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple7.java index 8ac584380..d40fc1799 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple7.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple7.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 7-element tuple type (T0, T1, T2, T3, T4, T5, T6). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple7 { +public class Tuple7 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple8.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple8.java index 85b78ec23..10261c8ca 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple8.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple8.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 8-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple8 { +public class Tuple8 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple9.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple9.java index 3823a1193..d4ba4c253 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple9.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/tuple/Tuple9.java @@ -18,7 +18,7 @@ * Corresponds to Swift's built-in 9-element tuple type (T0, T1, T2, T3, T4, T5, T6, T7, T8). * Elements are accessed via public final fields $0, $1, etc. */ -public final class Tuple9 { +public class Tuple9 { public final T0 $0; public final T1 $1; public final T2 $2; diff --git a/Tests/JExtractSwiftTests/FFM/FFMTupleTests.swift b/Tests/JExtractSwiftTests/FFM/FFMTupleTests.swift index 1b0c09b57..67fd0ab18 100644 --- a/Tests/JExtractSwiftTests/FFM/FFMTupleTests.swift +++ b/Tests/JExtractSwiftTests/FFM/FFMTupleTests.swift @@ -31,12 +31,12 @@ struct FFMTupleTests { .java, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2 returnPair() { + public static org.swift.swiftkit.core.tuple.Tuple2 returnPair() { try(var arena$ = Arena.ofConfined()) { MemorySegment result$_0 = arena$.allocate(SwiftValueLayout.SWIFT_INT64); MemorySegment result$_1 = arena$.allocate(SwiftValueLayout.SWIFT_INT64); swiftjava_SwiftModule_returnPair.call(result$_0, result$_1); - return new org.swift.swiftkit.core.tuple.Tuple2(result$_0.get(SwiftValueLayout.SWIFT_INT64, 0), result$_1.get(SwiftValueLayout.SWIFT_INT64, 0)); + return new org.swift.swiftkit.core.tuple.Tuple2(result$_0.get(SwiftValueLayout.SWIFT_INT64, 0), result$_1.get(SwiftValueLayout.SWIFT_INT64, 0)); } } """ @@ -53,7 +53,7 @@ struct FFMTupleTests { detectChunkByInitialLines: 2, expectedChunks: [ """ - public static void takePair(org.swift.swiftkit.core.tuple.Tuple2 arg) { + public static void takePair(org.swift.swiftkit.core.tuple.Tuple2 arg) { swiftjava_SwiftModule_takePair__.call(arg.$0, arg.$1); } """ @@ -69,10 +69,10 @@ struct FFMTupleTests { .java, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2 labeledTuple() { + public static org.swift.swiftkit.core.tuple.Tuple2 labeledTuple() { """, """ - return new org.swift.swiftkit.core.tuple.Tuple2(result$_0.get(SwiftValueLayout.SWIFT_INT32, 0), result$_1.get(SwiftValueLayout.SWIFT_INT32, 0)); + return new org.swift.swiftkit.core.tuple.Tuple2(result$_0.get(SwiftValueLayout.SWIFT_INT32, 0), result$_1.get(SwiftValueLayout.SWIFT_INT32, 0)); """, ] ) diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift index 897a2103d..e1714d9e9 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift @@ -171,13 +171,13 @@ struct JNIGenericCombinationTests { detectChunkByInitialLines: 2, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2, MyID> makeIDs(java.lang.String stringValue, long intValue, SwiftArena swiftArena) { + public static org.swift.swiftkit.core.tuple.Tuple2, MyID> makeIDs(java.lang.String stringValue, long intValue, SwiftArena swiftArena) { org.swift.swiftkit.core._OutSwiftGenericInstance result_0$ = new org.swift.swiftkit.core._OutSwiftGenericInstance(); org.swift.swiftkit.core._OutSwiftGenericInstance result_1$ = new org.swift.swiftkit.core._OutSwiftGenericInstance(); SwiftModule.$makeIDs(stringValue, intValue, result_0$, result_1$); var result_0 = MyID.wrapMemoryAddressUnsafe(result_0$.selfPointer, result_0$.selfTypePointer, swiftArena); var result_1 = MyID.wrapMemoryAddressUnsafe(result_1$.selfPointer, result_1$.selfTypePointer, swiftArena); - return new org.swift.swiftkit.core.tuple.Tuple2<>(result_0, result_1); + return new org.swift.swiftkit.core.tuple.Tuple2, MyID>(result_0, result_1); } """, """ @@ -233,12 +233,12 @@ struct JNIGenericCombinationTests { detectChunkByInitialLines: 2, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2 takeValues(org.swift.swiftkit.core.tuple.Tuple2, MyID> tuple) { - java.lang.String[] result_0$ = new java.lang.String[1]; + public static org.swift.swiftkit.core.tuple.Tuple2 takeValues(org.swift.swiftkit.core.tuple.Tuple2, MyID> tuple) { + long[] result_0$ = new long[1]; long[] result_1$ = new long[1]; SwiftModule.$takeValues(tuple.$0.$memoryAddress(), tuple.$1.$memoryAddress(), result_0$, result_1$); - return new org.swift.swiftkit.core.tuple.Tuple2<>(result_0$[0], result_1$[0]); - } + return new org.swift.swiftkit.core.tuple.Tuple2(result_0$[0], result_1$[0]); + } """, """ private static native void $takeValues(long tuple_0, long tuple_1, java.lang.String[] result_0$, long[] result_1$); diff --git a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift index 1a92fa994..5a64c58b6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift @@ -32,11 +32,11 @@ struct JNITupleTests { .java, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2 returnPair() { + public static org.swift.swiftkit.core.tuple.Tuple2 returnPair() { long[] result_0$ = new long[1]; - java.lang.String[] result_1$ = new java.lang.String[1]; + long[] result_1$ = new long[1]; SwiftModule.$returnPair(result_0$, result_1$); - return new org.swift.swiftkit.core.tuple.Tuple2<>(result_0$[0], result_1$[0]); + return new org.swift.swiftkit.core.tuple.Tuple2(result_0$[0], result_1$[0]); } """, """ @@ -74,7 +74,7 @@ struct JNITupleTests { detectChunkByInitialLines: 2, expectedChunks: [ """ - public static void takePair(org.swift.swiftkit.core.tuple.Tuple2 arg) { + public static void takePair(org.swift.swiftkit.core.tuple.Tuple2 arg) { SwiftModule.$takePair(arg.$0, arg.$1); } """, @@ -100,24 +100,36 @@ struct JNITupleTests { ) } - @Test - func labeledTuple_javaBindings() throws { + @Test("Labelled tuple return (JNI)") + func labeledTuple_javaBindings_jni() throws { try assertOutput( input: source, .jni, .java, expectedChunks: [ """ - public static org.swift.swiftkit.core.tuple.Tuple2 labeledTuple() { + public static LabeledTuple_labeledTuple_x_y labeledTuple() { """, """ private static native void $labeledTuple(int[] result_0$, int[] result_1$); """, + """ + public static final class LabeledTuple_labeledTuple_x_y extends org.swift.swiftkit.core.tuple.Tuple2 { + """, + """ + public LabeledTuple_labeledTuple_x_y(T0 $0, T1 $1) { super($0, $1); } + """, + """ + public T0 x() { return $0; } + """, + """ + public T1 y() { return $1; } + """, ] ) } - @Test + @Test("Labelled tuple return, Swift thunks (JNI)") func labeledTuple_swiftThunks() throws { try assertOutput( input: source, From 33676173612eef5a315fb64b65d43f6ea8b2cf18 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 2 Apr 2026 16:10:26 +0900 Subject: [PATCH 2/4] fix handling of String in tuples --- .../JNISwift2JavaGenerator+JavaTranslation.swift | 13 ++++++++----- .../JNI/JNIGenericCombinationTests.swift | 2 +- Tests/JExtractSwiftTests/JNI/JNITupleTests.swift | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift index 6a72bf6b0..69455ba69 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift @@ -1186,13 +1186,16 @@ extension JNISwift2JavaGenerator { // FIXME: More accurate determination of whether the result is direct or indirect if elementResult.outParameters.isEmpty { // Convert direct result to indirect result. - // For class types (nominal types), the JNI native representation is 'long' - // (a memory address), not the wrapper class type + // For most class types (Swift wrapper classes), the JNI native representation + // is 'long' (a memory address). However, String is a native JNI reference + // type and must keep its original type so the out-parameter array matches + // the native method signature (String[] not long[]) let nativeElementType: JavaType - switch elementResult.javaType { - case .class: + if elementResult.javaType.isString { + nativeElementType = elementResult.javaType + } else if case .class = elementResult.javaType { nativeElementType = .long - default: + } else { nativeElementType = elementResult.javaType } let arrayType: JavaType = .array(nativeElementType) diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift index e1714d9e9..57651e1e1 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift @@ -234,7 +234,7 @@ struct JNIGenericCombinationTests { expectedChunks: [ """ public static org.swift.swiftkit.core.tuple.Tuple2 takeValues(org.swift.swiftkit.core.tuple.Tuple2, MyID> tuple) { - long[] result_0$ = new long[1]; + java.lang.String[] result_0$ = new java.lang.String[1]; long[] result_1$ = new long[1]; SwiftModule.$takeValues(tuple.$0.$memoryAddress(), tuple.$1.$memoryAddress(), result_0$, result_1$); return new org.swift.swiftkit.core.tuple.Tuple2(result_0$[0], result_1$[0]); diff --git a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift index 5a64c58b6..2a9edf26e 100644 --- a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift @@ -34,7 +34,7 @@ struct JNITupleTests { """ public static org.swift.swiftkit.core.tuple.Tuple2 returnPair() { long[] result_0$ = new long[1]; - long[] result_1$ = new long[1]; + java.lang.String[] result_1$ = new java.lang.String[1]; SwiftModule.$returnPair(result_0$, result_1$); return new org.swift.swiftkit.core.tuple.Tuple2(result_0$[0], result_1$[0]); } From 77480ba07a12f6ac2f8d073f8b5adc3f458e2e8b Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 2 Apr 2026 16:15:54 +0900 Subject: [PATCH 3/4] Rename file to use one l consistently, US spelling --- ...ledTuples.swift => JNISwift2JavaGenerator+LabeledTuples.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/JExtractSwiftLib/JNI/{JNISwift2JavaGenerator+LabelledTuples.swift => JNISwift2JavaGenerator+LabeledTuples.swift} (100%) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift similarity index 100% rename from Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabelledTuples.swift rename to Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift From 0bfe36e015955d12e7ecc3b37f7228fb1a823eb5 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 2 Apr 2026 16:49:47 +0900 Subject: [PATCH 4/4] cleanup existential type rendering --- ...JNISwift2JavaGenerator+LabeledTuples.swift | 11 ++++++---- ...wift2JavaGenerator+NativeTranslation.swift | 20 +++++++++---------- .../JExtractSwiftLib/SwiftKit+Printing.swift | 16 ++++++++++++++- .../SwiftTypes/SwiftType.swift | 14 +++++++++++-- .../JNI/JNIProtocolTests.swift | 20 +++++++++---------- .../JNI/JNITupleTests.swift | 2 +- 6 files changed, 54 insertions(+), 29 deletions(-) diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift index 64c4cf3a2..0250dd390 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+LabeledTuples.swift @@ -26,7 +26,7 @@ extension JNISwift2JavaGenerator { /// public static class LabeledTuple_fn_x_y /// extends org.swift.swiftkit.core.tuple.Tuple2 { /// - /// public LabeledTuple_fn_x_y(T0 $0, T1 $1) { super($0, $1); } + /// public LabeledTuple_fn_x_y(T0 param0, T1 param1) { super(param0, param1); } /// public T0 x() { return $0; } /// public T1 y() { return $1; } /// } @@ -61,9 +61,12 @@ extension JNISwift2JavaGenerator { let typeParamsClause = "<\(typeParams.joined(separator: ", "))>" let baseTupleClass = "org.swift.swiftkit.core.tuple.Tuple\(arity)" - // Constructor parameters: T0 $0, T1 $1, ... - let ctorParams = typeParams.enumerated().map { "\($1) $\($0)" }.joined(separator: ", ") - let superArgs = (0..(_ ty: Ty.Type) -> any \(compositeProtocolName) { - \(inner)RawPointer$.load(as: ty) as! any \(compositeProtocolName) + func \(inner)DoLoad(_ ty: Ty.Type) -> \(existentialType) { + \(inner)RawPointer$.load(as: ty) as! \(existentialType) } let \(existentialName) = _openExistential(\(inner)DynamicType$, do: \(inner)DoLoad) #endif diff --git a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift index 0afc96452..b8ceb6047 100644 --- a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift +++ b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift @@ -26,9 +26,23 @@ package struct SwiftKitPrinting { SwiftRuntime.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") """ } + + /// Render a parenthesized existential type constraint from nominal protocol types + /// + /// For a single protocol: `(any DataProtocol)` + /// For multiple protocols: `(any (DataProtocol & Sendable))` + static func renderExistentialType(_ protocolTypes: [SwiftNominalType]) -> String { + let compositeType: SwiftType + if protocolTypes.count == 1 { + compositeType = .nominal(protocolTypes[0]) + } else { + compositeType = .composite(protocolTypes.map { .nominal($0) }) + } + return "(\(SwiftType.existential(compositeType)))" + } } -// ==== ------------------------------------------------------------------------ +// ==== ----------------------------------------------------------------------- // Helpers to form names of "well known" SwiftKit generated functions extension SwiftKitPrinting { diff --git a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift index 5a12376f0..0de2ca191 100644 --- a/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift +++ b/Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift @@ -167,9 +167,19 @@ extension SwiftType: CustomStringConvertible { case .tuple(let elements): return "(\(elements.map(\.description).joined(separator: ", ")))" case .existential(let constraintType): - return "any \(constraintType)" + switch constraintType { + case .composite: + return "any (\(constraintType))" + default: + return "any \(constraintType)" + } case .opaque(let constraintType): - return "some \(constraintType)" + switch constraintType { + case .composite: + return "some (\(constraintType))" + default: + return "some \(constraintType)" + } case .composite(let types): return types.map(\.description).joined(separator: " & ") } diff --git a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift index 526c89675..6e763172b 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIProtocolTests.swift @@ -133,7 +133,7 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2") public func Java_com_example_swift_SwiftModule__00024takeProtocol__Ljava_lang_Object_2Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, x: jobject?, y: jobject?) { - let xswiftObject$: (SomeProtocol) + let xswiftObject$: (any SomeProtocol) if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { ... let xpointer$DynamicType$: Any.Type = unsafeBitCast(xpointer$TypeMetadataPointer$, to: Any.Type.self) @@ -141,10 +141,10 @@ struct JNIProtocolTests { fatalError("xpointer$ memory address was null") } #if hasFeature(ImplicitOpenExistentials) - let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol) + let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! (any SomeProtocol) #else - func xpointer$DoLoad(_ ty: Ty.Type) -> any (SomeProtocol) { - xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol) + func xpointer$DoLoad(_ ty: Ty.Type) -> (any SomeProtocol) { + xpointer$RawPointer$.load(as: ty) as! (any SomeProtocol) } let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad) #endif @@ -153,7 +153,7 @@ struct JNIProtocolTests { else { xswiftObject$ = _SwiftModule_takeProtocol_x_Wrapper(_javaSomeProtocolInterface: JavaSomeProtocol(javaThis: x!, environment: environment)) } - let yswiftObject$: (SomeProtocol) + let yswiftObject$: (any SomeProtocol) if environment.interface.IsInstanceOf(environment, y, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { ... yswiftObject$ = ypointer$Existential$ @@ -209,7 +209,7 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2") public func Java_com_example_swift_SwiftModule__00024takeGeneric__Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, s: jobject?) { - let sswiftObject$: (SomeProtocol) + let sswiftObject$: (any SomeProtocol) if environment.interface.IsInstanceOf(environment, s, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { ... sswiftObject$ = spointer$Existential$ @@ -267,7 +267,7 @@ struct JNIProtocolTests { """ @_cdecl("Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2") public func Java_com_example_swift_SwiftModule__00024takeComposite__Ljava_lang_Object_2(environment: UnsafeMutablePointer!, thisClass: jclass, x: jobject?) { - let xswiftObject$: (SomeProtocol & B) + let xswiftObject$: (any (SomeProtocol & B)) if environment.interface.IsInstanceOf(environment, x, _JNIMethodIDCache.JNISwiftInstance.class) != 0 { let xpointer$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.memoryAddress, []) let xtypeMetadata$ = environment.interface.CallLongMethodA(environment, x, _JNIMethodIDCache.JNISwiftInstance.typeMetadataAddress, []) @@ -279,10 +279,10 @@ struct JNIProtocolTests { fatalError("xpointer$ memory address was null") } #if hasFeature(ImplicitOpenExistentials) - let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! any (SomeProtocol & B) + let xpointer$Existential$ = xpointer$RawPointer$.load(as: xpointer$DynamicType$) as! (any (SomeProtocol & B)) #else - func xpointer$DoLoad(_ ty: Ty.Type) -> any (SomeProtocol & B) { - xpointer$RawPointer$.load(as: ty) as! any (SomeProtocol & B) + func xpointer$DoLoad(_ ty: Ty.Type) -> (any (SomeProtocol & B)) { + xpointer$RawPointer$.load(as: ty) as! (any (SomeProtocol & B)) } let xpointer$Existential$ = _openExistential(xpointer$DynamicType$, do: xpointer$DoLoad) #endif diff --git a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift index 2a9edf26e..67efc4312 100644 --- a/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNITupleTests.swift @@ -117,7 +117,7 @@ struct JNITupleTests { public static final class LabeledTuple_labeledTuple_x_y extends org.swift.swiftkit.core.tuple.Tuple2 { """, """ - public LabeledTuple_labeledTuple_x_y(T0 $0, T1 $1) { super($0, $1); } + public LabeledTuple_labeledTuple_x_y(T0 param0, T1 param1) { super(param0, param1); } """, """ public T0 x() { return $0; }