mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Distributed] move _missingDistributedActorTransport to _Distributed
This commit is contained in:
@@ -88,7 +88,4 @@ FUNC_DECL(Swap, "swap")
|
||||
FUNC_DECL(UnimplementedInitializer, "_unimplementedInitializer")
|
||||
FUNC_DECL(Undefined, "_undefined")
|
||||
|
||||
// TODO: move to _Distributed
|
||||
FUNC_DECL(MissingDistributedActorTransport, "_missingDistributedActorTransport")
|
||||
|
||||
#undef FUNC_DECL
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# define KNOWN_SDK_FUNC_DECL(Module, Name, Id)
|
||||
#endif
|
||||
|
||||
//KNOWN_SDK_FUNC_DECL(Distributed, MissingDistributedActorTransport, "_missingDistributedActorTransport")
|
||||
KNOWN_SDK_FUNC_DECL(Distributed, MissingDistributedActorTransport, "_missingDistributedActorTransport")
|
||||
KNOWN_SDK_FUNC_DECL(Distributed, IsRemoteDistributedActor, "__isRemoteActor")
|
||||
|
||||
#undef KNOWN_SDK_FUNC_DECL
|
||||
|
||||
@@ -561,9 +561,11 @@ static void addImplicitDistributedActorStoredProperties(ClassDecl *decl) {
|
||||
///
|
||||
/// Create a stub body that emits a fatal error message.
|
||||
static std::pair<BraceStmt *, bool>
|
||||
synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *) {
|
||||
synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *context) {
|
||||
auto distributedFunc = static_cast<AbstractFunctionDecl *>(context);
|
||||
auto classDecl = func->getDeclContext()->getSelfClassDecl();
|
||||
auto &ctx = func->getASTContext();
|
||||
auto &SM = ctx.SourceMgr;
|
||||
|
||||
auto *staticStringDecl = ctx.getStaticStringDecl();
|
||||
auto staticStringType = staticStringDecl->getDeclaredInterfaceType();
|
||||
@@ -574,8 +576,9 @@ synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *) {
|
||||
auto uintInit = ctx.getIntBuiltinInitDecl(uintDecl);
|
||||
|
||||
auto missingTransportDecl = ctx.getMissingDistributedActorTransport();
|
||||
assert(missingTransportDecl);
|
||||
|
||||
// Create a call to Swift._missingDistributedActorTransport // TODO: move to `Distributed` module
|
||||
// Create a call to _Distributed._missingDistributedActorTransport
|
||||
auto loc = func->getLoc();
|
||||
Expr *ref = new (ctx) DeclRefExpr(missingTransportDecl,
|
||||
DeclNameLoc(loc), /*Implicit=*/true);
|
||||
@@ -594,23 +597,34 @@ synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *) {
|
||||
assert(isa<ConstructorDecl>(className->getBuiltinInitializer().getDecl()));
|
||||
className->setType(staticStringType);
|
||||
|
||||
auto *funcName = new (ctx) MagicIdentifierLiteralExpr(
|
||||
MagicIdentifierLiteralExpr::Function, loc, /*Implicit=*/true);
|
||||
auto *funcName = new (ctx) StringLiteralExpr(
|
||||
ctx.AllocateCopy(func->getName().getBaseName().getIdentifier().str()), loc,
|
||||
/*Implicit=*/true);
|
||||
funcName->setType(staticStringType);
|
||||
funcName->setBuiltinInitializer(staticStringInit);
|
||||
|
||||
auto *file = new (ctx) MagicIdentifierLiteralExpr(
|
||||
MagicIdentifierLiteralExpr::FileID, loc, /*Implicit=*/true);
|
||||
// Note: Sadly we cannot just rely on #function, #file, #line for the location
|
||||
// (MagicIdentifierLiteralExpr), of the call because the call is made from a thunk.
|
||||
// That thunk does not carry those info today although it could.
|
||||
//
|
||||
// Instead, we offer the location where the distributed func was declared.
|
||||
auto fileString = SM.getDisplayNameForLoc(distributedFunc->getStartLoc());
|
||||
auto *file = new (ctx) StringLiteralExpr(fileString, loc, /*Implicit=*/true);
|
||||
file->setType(staticStringType);
|
||||
file->setBuiltinInitializer(staticStringInit);
|
||||
|
||||
auto *line = new (ctx) MagicIdentifierLiteralExpr(
|
||||
MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
|
||||
auto startLineAndCol = SM.getPresumedLineAndColumnForLoc(distributedFunc->getStartLoc());
|
||||
// auto *line = new (ctx) MagicIdentifierLiteralExpr(
|
||||
// MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
|
||||
// auto *line = new (ctx) IntegerLiteralExpr(startLineAndCol.first, loc,
|
||||
// /*implicit*/ true);
|
||||
auto *line = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.first);
|
||||
line->setType(uintType);
|
||||
line->setBuiltinInitializer(uintInit);
|
||||
|
||||
auto *column = new (ctx) MagicIdentifierLiteralExpr(
|
||||
MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
|
||||
// auto *column = new (ctx) MagicIdentifierLiteralExpr(
|
||||
// MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
|
||||
auto *column = IntegerLiteralExpr::createFromUnsigned(ctx, startLineAndCol.second);
|
||||
column->setType(uintType);
|
||||
column->setBuiltinInitializer(uintInit);
|
||||
|
||||
@@ -624,9 +638,6 @@ synthesizeRemoteFuncStubBody(AbstractFunctionDecl *func, void *) {
|
||||
// stmts.push_back(new (ctx) ReturnStmt(SourceLoc(), /*Result=*/nullptr)); // FIXME: this causes 'different types for return type: String vs. ()'
|
||||
auto body = BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
|
||||
/*implicit=*/true);
|
||||
|
||||
|
||||
|
||||
return { body, /*isTypeChecked=*/true };
|
||||
}
|
||||
|
||||
@@ -680,7 +691,7 @@ static void addImplicitRemoteActorFunction(ClassDecl *decl, FuncDecl *func) {
|
||||
remoteFuncDecl->setUserAccessible(false);
|
||||
remoteFuncDecl->setSynthesized();
|
||||
|
||||
remoteFuncDecl->setBodySynthesizer(&synthesizeRemoteFuncStubBody);
|
||||
remoteFuncDecl->setBodySynthesizer(&synthesizeRemoteFuncStubBody, func);
|
||||
|
||||
// same access control as the original function is fine
|
||||
remoteFuncDecl->copyFormalAccessFrom(func, /*sourceIsParentContext=*/false);
|
||||
|
||||
@@ -11,260 +11,23 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Swift
|
||||
import _Concurrency
|
||||
|
||||
/// Common protocol to which all distributed actors conform implicitly.
|
||||
///
|
||||
/// It is not possible to conform to this protocol manually explicitly.
|
||||
/// Only a 'distributed actor' declaration or protocol with 'DistributedActor'
|
||||
/// requirement may conform to this protocol.
|
||||
///
|
||||
/// The 'DistributedActor' protocol provides the core functionality of any
|
||||
/// distributed actor, which involves transforming actor
|
||||
/// which involves enqueuing new partial tasks to be executed at some
|
||||
/// point.
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public protocol DistributedActor: Actor, Codable {
|
||||
|
||||
/// Creates new (local) distributed actor instance, bound to the passed transport.
|
||||
///
|
||||
/// Upon initialization, the `actorAddress` field is populated by the transport,
|
||||
/// with an address assigned to this actor.
|
||||
///
|
||||
/// - Parameter transport: the transport this distributed actor instance will
|
||||
/// associated with.
|
||||
init(transport: ActorTransport)
|
||||
|
||||
/// Resolves the passed in `address` against the `transport`,
|
||||
/// returning either a local or remote actor reference.
|
||||
///
|
||||
/// The transport will be asked to `resolve` the address and return either
|
||||
/// a local instance or determine that a proxy instance should be created
|
||||
/// for this address. A proxy actor will forward all invocations through
|
||||
/// the transport, allowing it to take over the remote messaging with the
|
||||
/// remote actor instance.
|
||||
///
|
||||
/// - Parameter address: the address to resolve, and produce an instance or proxy for.
|
||||
/// - Parameter transport: transport which should be used to resolve the `address`.
|
||||
init(resolve address: ActorAddress, using transport: ActorTransport) throws
|
||||
|
||||
/// The `ActorTransport` associated with this actor.
|
||||
/// It is immutable and equal to the transport passed in the local/resolve
|
||||
/// initializer.
|
||||
///
|
||||
/// Conformance to this requirement is synthesized automatically for any
|
||||
/// `distributed actor` declaration.
|
||||
nonisolated var actorTransport: ActorTransport { get }
|
||||
|
||||
/// Logical address which this distributed actor represents.
|
||||
///
|
||||
/// An address is always uniquely pointing at a specific actor instance.
|
||||
///
|
||||
/// Conformance to this requirement is synthesized automatically for any
|
||||
/// `distributed actor` declaration.
|
||||
nonisolated var actorAddress: ActorAddress { get }
|
||||
/// Report a call to a _remote function on a distributed (remote) actor,
|
||||
/// that was not dynamically replaced by some specific ActorTransport library.
|
||||
@_transparent
|
||||
public func _missingDistributedActorTransport(
|
||||
className: StaticString, functionName: StaticString,
|
||||
file: StaticString, line: UInt, column: UInt
|
||||
) -> Never {
|
||||
// This function is marked @_transparent so that it is inlined into the caller
|
||||
// (the remote function stub), and, depending on the build configuration,
|
||||
// redundant parameter values (#file etc.) are eliminated, and don't leak
|
||||
// information about the user's source.
|
||||
fatalError(
|
||||
"""
|
||||
Invoked remote placeholder function '\(functionName)' on remote \
|
||||
distributed actor of type '\(className)'. Configure an appropriate \
|
||||
'ActorTransport' for this actor to resolve this error (e.g. by depending \
|
||||
on some specific transport library).
|
||||
""", file: file, line: line)
|
||||
}
|
||||
|
||||
// ==== Codable conformance ----------------------------------------------------
|
||||
|
||||
extension CodingUserInfoKey {
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
static let actorTransportKey = CodingUserInfoKey(rawValue: "$dist_act_trans")!
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
extension DistributedActor {
|
||||
nonisolated public init(from decoder: Decoder) throws {
|
||||
// guard let transport = decoder.userInfo[.actorTransportKey] as? ActorTransport else {
|
||||
// throw DistributedActorCodingError(message:
|
||||
// "ActorTransport not available under the decoder.userInfo")
|
||||
// }
|
||||
//
|
||||
// var container = try decoder.singleValueContainer()
|
||||
// let address = try container.decode(ActorAddress.self)
|
||||
// self = try Self(resolve: address, using: transport) // FIXME: This is going to be solved by the init() work!!!!
|
||||
fatalError("\(#function) is not implemented yet for distributed actors'")
|
||||
}
|
||||
|
||||
nonisolated public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(self.actorAddress)
|
||||
}
|
||||
}
|
||||
/******************************************************************************/
|
||||
/***************************** Actor Transport ********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public protocol ActorTransport: Sendable {
|
||||
/// Resolve a local or remote actor address to a real actor instance, or throw if unable to.
|
||||
/// The returned value is either a local actor or proxy to a remote actor.
|
||||
func resolve<Act>(address: ActorAddress, as actorType: Act.Type)
|
||||
throws -> ActorResolved<Act> where Act: DistributedActor
|
||||
|
||||
/// Create an `ActorAddress` for the passed actor type.
|
||||
///
|
||||
/// This function is invoked by an distributed actor during its initialization,
|
||||
/// and the returned address value is stored along with it for the time of its
|
||||
/// lifetime.
|
||||
///
|
||||
/// The address MUST uniquely identify the actor, and allow resolving it.
|
||||
/// E.g. if an actor is created under address `addr1` then immediately invoking
|
||||
/// `transport.resolve(address: addr1, as: Greeter.self)` MUST return a reference
|
||||
/// to the same actor.
|
||||
func assignAddress<Act>(
|
||||
_ actorType: Act.Type
|
||||
) -> ActorAddress
|
||||
where Act: DistributedActor
|
||||
|
||||
func actorReady<Act>(
|
||||
_ actor: Act
|
||||
) where Act: DistributedActor
|
||||
|
||||
/// Called during actor deinit/destroy.
|
||||
func resignAddress(
|
||||
_ address: ActorAddress
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public enum ActorResolved<Act: DistributedActor> {
|
||||
case resolved(Act)
|
||||
case makeProxy
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Actor Address **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/// Uniquely identifies a distributed actor, and enables sending messages even to remote actors.
|
||||
///
|
||||
/// ## Identity
|
||||
/// The address is the source of truth with regards to referring to a _specific_ actor in the system.
|
||||
/// This is in contrast to an `ActorPath` which can be thought of as paths in a filesystem, however without any uniqueness
|
||||
/// or identity guarantees about the files those paths point to.
|
||||
///
|
||||
/// ## Lifecycle
|
||||
/// Note, that an ActorAddress is a pure value, and as such does not "participate" in an actors lifecycle;
|
||||
/// Thus, it may represent an address of an actor that has already terminated, so attempts to locate (resolve)
|
||||
/// an `ActorRef` for this address may result with a reference to dead letters (meaning, that the actor this address
|
||||
/// had pointed to does not exist, and most likely is dead / terminated).
|
||||
///
|
||||
/// ## Serialization
|
||||
///
|
||||
/// An address can be serialized using `Codable` or other serialization mechanisms.
|
||||
/// When shared over the network or with other processes it must include the origin's
|
||||
/// system address (e.g. the network address of the host, or process identifier).
|
||||
///
|
||||
/// When using `Codable` serialization this is done automatically, by looking up
|
||||
/// the address of the `ActorTransport` the actor is associated with if was a local
|
||||
/// instance, or simply carrying the full address if it already was a remote reference.
|
||||
///
|
||||
/// ## Format
|
||||
/// The address consists of the following parts:
|
||||
///
|
||||
/// ```
|
||||
/// | node | path | incarnation |
|
||||
/// ( protocol | name? | host | port ) ( [segments] name )? ( uint32 )
|
||||
/// ```
|
||||
///
|
||||
/// For example: `sact://human-readable-name@127.0.0.1:7337/user/wallet/id-121242`.
|
||||
/// Note that the `ActorIncarnation` is not printed by default in the String representation of a path, yet may be inspected on demand.
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public struct ActorAddress: Codable, Sendable, Equatable, Hashable {
|
||||
/// Uniquely specifies the actor transport and the protocol used by it.
|
||||
///
|
||||
/// E.g. "xpc", "specific-clustering-protocol" etc.
|
||||
public var `protocol`: String
|
||||
|
||||
public var host: String?
|
||||
public var port: Int?
|
||||
public var nodeID: UInt64?
|
||||
public var path: String?
|
||||
|
||||
/// Unique Identifier of this actor.
|
||||
public var uid: UInt64 // TODO: should we remove this
|
||||
|
||||
// FIXME: remove this or implement for real; this is just a hack implementation for now
|
||||
public init(parse: String) {
|
||||
self.protocol = "sact"
|
||||
self.host = "xxx"
|
||||
self.port = 7337
|
||||
self.nodeID = 11
|
||||
self.path = "example"
|
||||
self.uid = 123123
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: naive impl, bring in a real one
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
extension ActorAddress: CustomStringConvertible {
|
||||
public var description: String {
|
||||
var result = `protocol`
|
||||
result += "://"
|
||||
if let host = host {
|
||||
result += host
|
||||
}
|
||||
if let port = port {
|
||||
result += ":\(port)"
|
||||
}
|
||||
// TODO: decide if we'd want to print the nodeID too here.
|
||||
if let path = path {
|
||||
result += "/\(path)"
|
||||
}
|
||||
if uid > 0 {
|
||||
result += "#\(uid)"
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************** Misc ****************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/// Error protocol to which errors thrown by any `ActorTransport` should conform.
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public protocol ActorTransportError: Error {}
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
public struct DistributedActorCodingError: ActorTransportError {
|
||||
public let message: String
|
||||
|
||||
public init(message: String) {
|
||||
self.message = message
|
||||
}
|
||||
|
||||
public static func missingTransportUserInfo<Act>(_ actorType: Act.Type) -> Self
|
||||
where Act: DistributedActor {
|
||||
.init(message: "Missing ActorTransport userInfo while decoding")
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/************************* Runtime Functions **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// ==== isRemote / isLocal -----------------------------------------------------
|
||||
|
||||
@_silgen_name("swift_distributed_actor_is_remote")
|
||||
func __isRemoteActor(_ actor: AnyObject) -> Bool
|
||||
|
||||
func __isLocalActor(_ actor: AnyObject) -> Bool {
|
||||
return !__isRemoteActor(actor)
|
||||
}
|
||||
|
||||
// ==== Proxy Actor lifecycle --------------------------------------------------
|
||||
|
||||
/// Called to initialize the distributed-remote actor 'proxy' instance in an actor.
|
||||
/// The implementation will call this within the actor's initializer.
|
||||
@_silgen_name("swift_distributedActor_remote_initialize")
|
||||
func _distributedActorRemoteInitialize(_ actor: AnyObject)
|
||||
|
||||
/// Called to destroy the default actor instance in an actor.
|
||||
/// The implementation will call this within the actor's deinit.
|
||||
///
|
||||
/// This will call `actorTransport.resignAddress(self.actorAddress)`.
|
||||
@_silgen_name("swift_distributedActor_destroy")
|
||||
func _distributedActorDestroy(_ actor: AnyObject)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
//
|
||||
// Created by Konrad Malawski on 2021/06/07.
|
||||
//
|
||||
|
||||
#ifndef SWIFT_ASSERTIONREPORTINGDISTRIBUTED_H
|
||||
#define SWIFT_ASSERTIONREPORTINGDISTRIBUTED_H
|
||||
|
||||
#endif //SWIFT_ASSERTIONREPORTINGDISTRIBUTED_H
|
||||
@@ -14,6 +14,7 @@ set(swift_distributed_link_libraries
|
||||
swiftCore)
|
||||
|
||||
add_swift_target_library(swift_Distributed ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
|
||||
AssertDistributed.swift
|
||||
DistributedActor.swift
|
||||
|
||||
SWIFT_MODULE_DEPENDS_LINUX Glibc
|
||||
|
||||
@@ -68,21 +68,6 @@ void _swift_stdlib_reportUnimplementedInitializer(
|
||||
const unsigned char *initName, int initNameLength,
|
||||
__swift_uint32_t flags);
|
||||
|
||||
/// Report a call to a _remote function on a distributed (remote) actor,
|
||||
/// that was not dynamically replaced by some specific ActorTransport library.
|
||||
///
|
||||
/// <file>: <line>: <column>: Fatal error: remote function 'greet(name:)'
|
||||
/// invoked on remote distributed actor reference of type 'Greeter'.
|
||||
/// Configure an appropriate 'ActorTransport' for this actor to resolve
|
||||
/// this error (e.g. by depending on some specific ActorTransport library)
|
||||
SWIFT_RUNTIME_STDLIB_API
|
||||
void _swift_stdlib_reportMissingDistributedActorTransport(
|
||||
const unsigned char *className, int classNameLength,
|
||||
const unsigned char *funcName, int funcNameLength,
|
||||
const unsigned char *file, int fileLength,
|
||||
__swift_uint32_t line, __swift_uint32_t column,
|
||||
__swift_uint32_t flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -222,36 +222,6 @@ func _unimplementedInitializer(className: StaticString,
|
||||
Builtin.int_trap()
|
||||
}
|
||||
|
||||
/// Prints a fatal error message when a distributed remote actor function is invoked
|
||||
/// without a transport having dynamically replaced its _remote_ function implementation.
|
||||
@_transparent
|
||||
public // COMPILER_INTRINSIC
|
||||
func _missingDistributedActorTransport(className: StaticString,
|
||||
functionName: StaticString = #function,
|
||||
file: StaticString = #file,
|
||||
line: UInt = #line,
|
||||
column: UInt = #column
|
||||
) -> Never {
|
||||
// This function is marked @_transparent so that it is inlined into the caller
|
||||
// (the initializer stub), and, depending on the build configuration,
|
||||
// redundant parameter values (#file etc.) are eliminated, and don't leak
|
||||
// information about the user's source.
|
||||
className.withUTF8Buffer { className in
|
||||
functionName.withUTF8Buffer { functionName in
|
||||
file.withUTF8Buffer { file in
|
||||
_swift_stdlib_reportMissingDistributedActorTransport(
|
||||
className.baseAddress!, CInt(className.count),
|
||||
functionName.baseAddress!, CInt(functionName.count),
|
||||
file.baseAddress!, CInt(file.count),
|
||||
UInt32(line), UInt32(column),
|
||||
/*flags:*/ 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Builtin.int_trap()
|
||||
}
|
||||
|
||||
public // COMPILER_INTRINSIC
|
||||
func _undefined<T>(
|
||||
_ message: @autoclosure () -> String = String(),
|
||||
|
||||
@@ -117,25 +117,3 @@ void _swift_stdlib_reportUnimplementedInitializer(
|
||||
free(log);
|
||||
}
|
||||
|
||||
void _swift_stdlib_reportMissingDistributedActorTransport(
|
||||
const unsigned char *className, int classNameLength,
|
||||
const unsigned char *funcName, int funcNameLength,
|
||||
const unsigned char *file, int fileLength,
|
||||
uint32_t line, uint32_t column,
|
||||
uint32_t flags
|
||||
) {
|
||||
char *log;
|
||||
swift_asprintf(
|
||||
&log,
|
||||
"%.*s:%" PRIu32 ": Fatal error: remote function '%.*s' invoked on remote "
|
||||
"distributed actor reference of type '%.*s'. Configure an appropriate "
|
||||
"'ActorTransport' for this actor to resolve this error (e.g. by depending "
|
||||
"on some specific ActorTransport library)\n",
|
||||
fileLength, file,
|
||||
line,
|
||||
funcNameLength, funcName,
|
||||
classNameLength, className);
|
||||
|
||||
swift_reportError(flags, log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
63
test/Distributed/Runtime/distributed_no_transport_boom.swift
Normal file
63
test/Distributed/Runtime/distributed_no_transport_boom.swift
Normal file
@@ -0,0 +1,63 @@
|
||||
// RUN: %target-fail-simple-swift(-Xfrontend -enable-experimental-distributed -parse-as-library %import-libdispatch) 2>&1 | %FileCheck %s
|
||||
//
|
||||
// // TODO: could not figure out how to use 'not --crash' it never is used with target-run-simple-swift
|
||||
// This test is intended to *crash*, so we're using target-fail-simple-swift
|
||||
// which expects the exit code of the program to be non-zero;
|
||||
// We then check stderr for the expected error message using filecheck as usual.
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: distributed
|
||||
|
||||
import _Distributed
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
distributed actor SomeSpecificDistributedActor {
|
||||
distributed func hello() async throws -> String {
|
||||
"local impl"
|
||||
}
|
||||
}
|
||||
|
||||
// ==== Fake Transport ---------------------------------------------------------
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
struct FakeTransport: ActorTransport {
|
||||
func resolve<Act>(address: ActorAddress, as actorType: Act.Type)
|
||||
throws -> ActorResolved<Act> where Act: DistributedActor {
|
||||
return .makeProxy
|
||||
}
|
||||
|
||||
func assignAddress<Act>(
|
||||
_ actorType: Act.Type
|
||||
) -> ActorAddress where Act : DistributedActor {
|
||||
ActorAddress(parse: "")
|
||||
}
|
||||
|
||||
public func actorReady<Act>(
|
||||
_ actor: Act
|
||||
) where Act: DistributedActor {}
|
||||
|
||||
public func resignAddress(
|
||||
_ address: ActorAddress
|
||||
) {}
|
||||
}
|
||||
|
||||
// ==== Execute ----------------------------------------------------------------
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
func test_remote() async {
|
||||
let address = ActorAddress(parse: "")
|
||||
let transport = FakeTransport()
|
||||
|
||||
let remote = try! SomeSpecificDistributedActor(resolve: address, using: transport)
|
||||
_ = try! await remote.hello() // let it crash!
|
||||
// CHECK: SOURCE_DIR/test/Distributed/Runtime/distributed_no_transport_boom.swift:16: Fatal error: Invoked remote placeholder function '_remote_hello' on remote distributed actor of type 'main.SomeSpecificDistributedActor'. Configure an appropriate 'ActorTransport' for this actor to resolve this error (e.g. by depending on some specific transport library).
|
||||
}
|
||||
|
||||
@available(SwiftStdlib 5.5, *)
|
||||
@main struct Main {
|
||||
static func main() async {
|
||||
await test_remote()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user