Skip to content

Commit cc0ff8f

Browse files
authored
Adjust Task.immediate use so we can bring back Swift 6.1 CI until 6.2 is fixed (#417)
1 parent c58bbed commit cc0ff8f

File tree

8 files changed

+110
-82
lines changed

8 files changed

+110
-82
lines changed

.github/workflows/pull_request.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ jobs:
140140
strategy:
141141
fail-fast: false
142142
matrix:
143-
swift_version: ['6.2', 'nightly']
143+
swift_version: ['6.1.3', '6.2', 'nightly']
144144
os_version: ['jammy']
145145
jdk_vendor: ['corretto']
146146
container:
@@ -182,7 +182,7 @@ jobs:
182182
strategy:
183183
fail-fast: false
184184
matrix:
185-
swift_version: ['6.2', 'nightly']
185+
swift_version: ['6.1.3', '6.2', 'nightly']
186186
os_version: ['jammy']
187187
jdk_vendor: ['corretto']
188188
sample_app: [ # TODO: use a reusable-workflow to generate those names

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 6.2
1+
// swift-tools-version: 6.1
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import CompilerPluginSupport

Samples/SwiftJavaExtractJNISampleApp/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 6.2
1+
// swift-tools-version: 6.1
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import CompilerPluginSupport

Sources/JExtractSwiftLib/CodePrinter.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ public struct CodePrinter {
7070
}
7171
}
7272

73+
public mutating func printHashIfBlock(
74+
_ header: Any,
75+
function: String = #function,
76+
file: String = #fileID,
77+
line: UInt = #line,
78+
body: (inout CodePrinter) throws -> ()
79+
) rethrows {
80+
print("#if \(header)")
81+
indent()
82+
try body(&self)
83+
outdent()
84+
print("#endif // end of \(header)", .sloc, function: function, file: file, line: line)
85+
}
86+
7387
public mutating func printBraceBlock(
7488
_ header: Any,
7589
function: String = #function,

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+NativeTranslation.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ extension JNISwift2JavaGenerator {
825825

826826
func printDo(printer: inout CodePrinter) {
827827
printer.print("let swiftResult$ = await \(placeholder)")
828-
printer.print("environment = try JavaVirtualMachine.shared().environment()")
828+
printer.print("environment = try! JavaVirtualMachine.shared().environment()")
829829
let inner = inner.render(&printer, "swiftResult$")
830830
if swiftFunctionResultType.isVoid {
831831
printer.print("environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])")
@@ -839,7 +839,7 @@ extension JNISwift2JavaGenerator {
839839
}
840840
}
841841

842-
func printTask(printer: inout CodePrinter) {
842+
func printTaskBody(printer: inout CodePrinter) {
843843
printer.printBraceBlock("defer") { printer in
844844
// Defer might on any thread, so we need to attach environment.
845845
printer.print("let deferEnvironment = try! JavaVirtualMachine.shared().environment()")
@@ -867,18 +867,22 @@ extension JNISwift2JavaGenerator {
867867
}
868868
}
869869

870-
printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in
871-
printer.printBraceBlock("Task.immediate") { printer in
872-
// Immediate runs on the caller thread, so we don't need to attach the environment again.
873-
printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it.
874-
printTask(printer: &printer)
870+
printer.print("var task: Task<Void, Never>? = nil")
871+
printer.printHashIfBlock("swift(>=6.2)") { printer in
872+
printer.printBraceBlock("if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *)") { printer in
873+
printer.printBraceBlock("task = Task.immediate") { printer in
874+
// Immediate runs on the caller thread, so we don't need to attach the environment again.
875+
printer.print("var environment = environment!") // this is to ensure we always use the same environment name, even though we are rebinding it.
876+
printTaskBody(printer: &printer)
877+
}
875878
}
876879
}
877-
printer.printBraceBlock("else") { printer in
878-
printer.printBraceBlock("Task") { printer in
880+
881+
printer.printBraceBlock("if task == nil") { printer in
882+
printer.printBraceBlock("task = Task") { printer in
879883
// We can be on any thread, so we need to attach the thread.
880884
printer.print("var environment = try! JavaVirtualMachine.shared().environment()")
881-
printTask(printer: &printer)
885+
printTaskBody(printer: &printer)
882886
}
883887
}
884888

Tests/JExtractSwiftTests/Asserts/TextAssertions.swift

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ func assertOutput(
179179
print("==== ---------------------------------------------------------------")
180180
print("Expected output:")
181181
for (n, e) in expectedLines.enumerated() {
182-
print("\(n): \(e)".yellow(if: diffLineNumbers.map({$0 - matchingOutputOffset}).contains(n)))
182+
let isMismatch = diffLineNumbers.map({$0 - matchingOutputOffset}).contains(n)
183+
let marker = isMismatch ? " // <<<<<<<<<<< mismatch" : ""
184+
print("\(n): \(e)\(marker)".yellow(if: isMismatch))
183185
}
184186
}
185187

@@ -188,15 +190,7 @@ func assertOutput(
188190
let printFromLineNo = matchingOutputOffset
189191
for (n, g) in gotLines.enumerated() where n >= printFromLineNo {
190192
let baseLine = "\(n): \(g)"
191-
var line = baseLine
192-
if diffLineNumbers.contains(n) {
193-
line += "\n"
194-
let leadingCount = "\(n): ".count
195-
let message = "\(String(repeating: " ", count: leadingCount))\(String(repeating: "^", count: 8)) EXPECTED MATCH OR SEARCHING FROM HERE "
196-
line += "\(message)\(String(repeating: "^", count: max(0, line.count - message.count)))"
197-
line = line.red
198-
}
199-
print(line)
193+
print(baseLine)
200194
}
201195
print("==== ---------------------------------------------------------------\n")
202196
}
@@ -248,14 +242,18 @@ func assertOutput(
248242
print("==== ---------------------------------------------------------------")
249243
print("Expected output:")
250244
for (n, e) in expectedLines.enumerated() {
251-
print("\(e)".yellow(if: diffLineNumbers.contains(n)))
245+
let isMismatch = diffLineNumbers.contains(n)
246+
let marker = isMismatch ? " // <<<<<<<< error: mismatch" : ""
247+
print("\(e)\(marker)".yellow(if: isMismatch))
252248
}
253249
}
254250

255251
print("==== ---------------------------------------------------------------")
256252
print("Got output:")
257253
for (n, g) in gotLines.enumerated() {
258-
print("\(g)".red(if: diffLineNumbers.contains(n)))
254+
let isMismatch = diffLineNumbers.contains(n)
255+
let marker = isMismatch ? "// <<<<<<<< error: mismatch" : ""
256+
print("\(g)\(marker)".red(if: isMismatch))
259257
}
260258
print("==== ---------------------------------------------------------------\n")
261259
}

Tests/JExtractSwiftTests/JNI/JNIAsyncTests.swift

Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,30 @@ struct JNIAsyncTests {
5959
@_cdecl("Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2")
6060
func Java_com_example_swift_SwiftModule__00024asyncVoid__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, result_future: jobject?) {
6161
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
62-
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
63-
Task.immediate {
64-
var environment = environment!
65-
defer {
66-
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
67-
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
62+
var task: Task<Void, Never>? = nil
63+
#if swift(>=6.2)
64+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
65+
task = Task.immediate {
66+
var environment = environment!
67+
defer {
68+
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
69+
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
70+
}
71+
let swiftResult$ = await SwiftModule.asyncVoid()
72+
environment = try! JavaVirtualMachine.shared().environment()
73+
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
6874
}
69-
let swiftResult$ = await SwiftModule.asyncVoid()
70-
environment = try JavaVirtualMachine.shared().environment()
71-
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
7275
}
73-
}
74-
else {
75-
Task {
76+
#endif
77+
if task == nil {
78+
task = Task {
7679
var environment = try! JavaVirtualMachine.shared().environment()
7780
defer {
7881
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
7982
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
8083
}
8184
let swiftResult$ = await SwiftModule.asyncVoid()
82-
environment = try JavaVirtualMachine.shared().environment()
85+
environment = try! JavaVirtualMachine.shared().environment()
8386
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
8487
}
8588
}
@@ -130,35 +133,38 @@ struct JNIAsyncTests {
130133
@_cdecl("Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2")
131134
func Java_com_example_swift_SwiftModule__00024async__Ljava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, result_future: jobject?) {
132135
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
133-
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
134-
Task.immediate {
135-
var environment = environment!
136-
defer {
137-
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
138-
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
139-
}
140-
do {
141-
let swiftResult$ = await try SwiftModule.async()
142-
environment = try JavaVirtualMachine.shared().environment()
143-
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
144-
}
145-
catch {
146-
let catchEnvironment = try! JavaVirtualMachine.shared().environment()
147-
let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)])
148-
catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)])
136+
var task: Task<Void, Never>? = nil
137+
#if swift(>=6.2)
138+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
139+
task = Task.immediate {
140+
var environment = environment!
141+
defer {
142+
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
143+
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
144+
}
145+
do {
146+
let swiftResult$ = await try SwiftModule.async()
147+
environment = try! JavaVirtualMachine.shared().environment()
148+
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
149+
}
150+
catch {
151+
let catchEnvironment = try! JavaVirtualMachine.shared().environment()
152+
let exception = catchEnvironment.interface.NewObjectA(catchEnvironment, _JNIMethodIDCache.Exception.class, _JNIMethodIDCache.Exception.constructWithMessage, [String(describing: error).getJValue(in: catchEnvironment)])
153+
catchEnvironment.interface.CallBooleanMethodA(catchEnvironment, globalFuture, _JNIMethodIDCache.CompletableFuture.completeExceptionally, [jvalue(l: exception)])
154+
}
149155
}
150156
}
151-
}
152-
else {
153-
Task {
157+
#endif
158+
if task == nil {
159+
task = Task {
154160
var environment = try! JavaVirtualMachine.shared().environment()
155161
defer {
156162
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
157163
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
158164
}
159165
do {
160166
let swiftResult$ = await try SwiftModule.async()
161-
environment = try JavaVirtualMachine.shared().environment()
167+
environment = try! JavaVirtualMachine.shared().environment()
162168
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: nil)])
163169
}
164170
catch {
@@ -215,28 +221,31 @@ struct JNIAsyncTests {
215221
@_cdecl("Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2")
216222
func Java_com_example_swift_SwiftModule__00024async__JLjava_util_concurrent_CompletableFuture_2(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, i: jlong, result_future: jobject?) {
217223
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
224+
var task: Task<Void, Never>? = nil
225+
#if swift(>=6.2)
218226
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
219-
Task.immediate {
227+
task = Task.immediate {
220228
var environment = environment!
221229
defer {
222230
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
223231
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
224232
}
225233
let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment))
226-
environment = try JavaVirtualMachine.shared().environment()
234+
environment = try! JavaVirtualMachine.shared().environment()
227235
let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)
228236
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)])
229237
}
230238
}
231-
else {
232-
Task {
239+
#endif // end of swift(>=6.2)
240+
if task == nil {
241+
task = Task {
233242
var environment = try! JavaVirtualMachine.shared().environment()
234243
defer {
235244
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
236245
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
237246
}
238247
let swiftResult$ = await SwiftModule.async(i: Int64(fromJNI: i, in: environment))
239-
environment = try JavaVirtualMachine.shared().environment()
248+
environment = try! JavaVirtualMachine.shared().environment()
240249
let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(swiftResult$.getJNIValue(in: environment), in: environment)
241250
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)])
242251
}
@@ -303,31 +312,34 @@ struct JNIAsyncTests {
303312
fatalError("c memory address was null in call to \\(#function)!")
304313
}
305314
let globalFuture = environment.interface.NewGlobalRef(environment, result_future)
306-
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
307-
Task.immediate {
308-
var environment = environment!
309-
defer {
310-
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
311-
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
315+
var task: Task<Void, Never>? = nil
316+
#if swift(>=6.2)
317+
if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, *) {
318+
task = Task.immediate {
319+
var environment = environment!
320+
defer {
321+
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
322+
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
323+
}
324+
let swiftResult$ = await SwiftModule.async(c: c$.pointee)
325+
environment = try! JavaVirtualMachine.shared().environment()
326+
let result$ = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
327+
result$.initialize(to: swiftResult$)
328+
let resultBits$ = Int64(Int(bitPattern: result$))
329+
let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)
330+
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)])
312331
}
313-
let swiftResult$ = await SwiftModule.async(c: c$.pointee)
314-
environment = try JavaVirtualMachine.shared().environment()
315-
let result$ = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
316-
result$.initialize(to: swiftResult$)
317-
let resultBits$ = Int64(Int(bitPattern: result$))
318-
let boxedResult$ = SwiftJavaRuntimeSupport._JNIBoxedConversions.box(resultBits$.getJNIValue(in: environment), in: environment)
319-
environment.interface.CallBooleanMethodA(environment, globalFuture, _JNIMethodIDCache.CompletableFuture.complete, [jvalue(l: boxedResult$)])
320332
}
321-
}
322-
else {
323-
Task {
333+
#endif
334+
if task == nil {
335+
task = Task {
324336
var environment = try! JavaVirtualMachine.shared().environment()
325337
defer {
326338
let deferEnvironment = try! JavaVirtualMachine.shared().environment()
327339
environment.interface.DeleteGlobalRef(deferEnvironment, globalFuture)
328340
}
329341
let swiftResult$ = await SwiftModule.async(c: c$.pointee)
330-
environment = try JavaVirtualMachine.shared().environment()
342+
environment = try! JavaVirtualMachine.shared().environment()
331343
let result$ = UnsafeMutablePointer<MyClass>.allocate(capacity: 1)
332344
result$.initialize(to: swiftResult$)
333345
let resultBits$ = Int64(Int(bitPattern: result$))

docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ ENV LANGUAGE=en_US.UTF-8
2121
# JDK dependency
2222
RUN curl -s "https://get.sdkman.io" | bash
2323
RUN bash -c "source /root/.sdkman/bin/sdkman-init.sh && sdk install java 25.0.1-amzn"
24+
ENV JAVA_HOME="$(sdk home java current)"
2425

2526
RUN curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz && \
2627
tar zxf swiftly-$(uname -m).tar.gz && \
2728
./swiftly init --quiet-shell-followup --assume-yes && \
2829
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh" && \
2930
hash -r
30-

0 commit comments

Comments
 (0)