Files
swift-mirror/test/SILGen/continuation_hop_to_executor.swift
Kavon Farvardin d2bd562799 Test: send shadow RUN lines to /dev/null
The opaque values test coverage I initially added will emit to
stdout, which is noisy for people's logs if the test is failing for
some other reason.
2026-06-30 17:40:48 -07:00

92 lines
4.2 KiB
Swift

// RUN: %target-swift-frontend -Xllvm -sil-print-types -emit-silgen-ossa -o /dev/null -sil-verify-all -enable-sil-opaque-values %s -module-name test -swift-version 5 -target %target-swift-5.1-abi-triple -parse-stdlib -sil-verify-all
// RUN: %target-swift-frontend -Xllvm -sil-print-types -emit-sil %s -module-name test -swift-version 5 -target %target-swift-5.1-abi-triple -parse-stdlib -sil-verify-all | %FileCheck %s --check-prefix=CHECK
// REQUIRES: concurrency
import Swift
import _Concurrency
// Verify that hop_to_executor is emitted after
// await_async_continuation in the resume (and error) blocks.
// Without this hop, nonisolated(nonsending) functions that use continuation
// builtins would incorrectly just continue on whichever thread resumed the continuation.
// === Nonisolated free function (Swift 5 default) — hops to generic executor ===
// CHECK-LABEL: // nonisolatedFree()
// CHECK: sil @$s4test15nonisolatedFreeSiyYaF
// CHECK: [[GLOBAL:%[0-9]+]] = enum $Optional<any Actor>, #Optional.none
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[GLOBAL]] : $Optional<any Actor>
public func nonisolatedFree() async -> Int {
return await Builtin.withUnsafeContinuation { c in }
}
// === nonisolated(nonsending) free function — hops to caller's implicit actor ===
// CHECK-LABEL: // nonsendingFree()
// CHECK: sil @$s4test14nonsendingFreeSiyYaF
// CHECK: bb0([[IMPLICIT:%[0-9]+]] : $Builtin.ImplicitActor):
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[IMPLICIT]] : $Builtin.ImplicitActor
public nonisolated(nonsending) func nonsendingFree() async -> Int {
return await Builtin.withUnsafeContinuation { c in }
}
// === @concurrent free function — hops to generic executor ===
// CHECK-LABEL: // concurrentFree()
// CHECK: sil @$s4test14concurrentFreeSiyYaF
// CHECK: [[GLOBAL:%[0-9]+]] = enum $Optional<any Actor>, #Optional.none
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[GLOBAL]] : $Optional<any Actor>
@concurrent
public func concurrentFree() async -> Int {
return await Builtin.withUnsafeContinuation { c in }
}
// === @MainActor class method — hops to MainActor ===
@MainActor
public class MainActorClass {
// CHECK-LABEL: // MainActorClass.mainActorMethod()
// CHECK: sil @$s4test14MainActorClassC04mainC6MethodSiyYaF
// CHECK: [[MA:%[0-9]+]] = apply {{%[0-9]+}}({{%[0-9]+}}) : $@convention(method) (@thick MainActor.Type) -> @owned MainActor
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[MA]] : $MainActor
public func mainActorMethod() async -> Int {
return await Builtin.withUnsafeContinuation { c in }
}
}
// === actor method — hops to actor executor ===
public actor MyActor {
// CHECK-LABEL: // MyActor.actorMethod()
// CHECK: sil @$s4test7MyActorC11actorMethodSiyYaF
// CHECK: bb0([[SELF:%[0-9]+]] : $MyActor):
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[SELF]] : $MyActor
public func actorMethod() async -> Int {
return await Builtin.withUnsafeContinuation { c in }
}
}
// === Throwing: nonisolated(nonsending) — hops in both resume and error blocks ===
// CHECK-LABEL: // nonsendingThrowing()
// CHECK: sil @$s4test18nonsendingThrowingSiyYaKF
// CHECK: bb0([[IMPLICIT:%[0-9]+]] : $Builtin.ImplicitActor):
// CHECK: await_async_continuation {{%[0-9]+}} : $Builtin.RawUnsafeContinuation, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]]
// CHECK: [[RESUME]]:
// CHECK-NEXT: hop_to_executor [[IMPLICIT]] : $Builtin.ImplicitActor
// CHECK: [[ERROR]]({{%[0-9]+}} : $any Error):
// CHECK-NEXT: hop_to_executor [[IMPLICIT]] : $Builtin.ImplicitActor
public nonisolated(nonsending) func nonsendingThrowing() async throws -> Int {
return try await Builtin.withUnsafeThrowingContinuation { c in }
}