Skip to content

Commit 5ab8e08

Browse files
ktosoxedin
andauthored
[Distributed] Reimplement distributed call thunks completely in AST (#41616)
* [Distributed] dist actor always has default executor (currently) * [Distributed] extra test for missing makeEncoder * [DistributedDecl] Add DistributedActorSystem to known SDK types * [DistributedActor] ok progress on getting the system via witness * [Distributed] allow hop-to `let any: any X` where X is DistActor * [Distributed] AST: Add an accessor to determine whether type is distributed actor - Classes have specialized method on their declarations - Archetypes and existentials check their conformances for presence of `DistributedActor` protocol. * [Distributed] AST: Account for distributed members declared in class extensions `getConcreteReplacementForProtocolActorSystemType` should use `getSelfClassDecl` otherwise it wouldn't be able to find actor if the member is declared in an extension. * [Distributed] fix ad-hoc requirement checks for 'mutating' [PreChecker] LookupDC might be null, so account for that * [Distributed] Completed AST synthesis for dist thunk * [Distributed][ASTDumper] print pretty distributed in right color in AST dumps * wip on making the local/remote calls * using the _local to mark the localCall as known local * [Distributed] fix passing Never when not throwing * fix lifetime of mangled string * [Distributed] Implement recordGenericSubstitution * [Distributed] Dont add . * [Distributed] dont emit thunk when func broken * [Distributed] fix tests; cleanups * [Distributed] cleanup, move is... funcs to DistributedDecl * [Distributed] Remove SILGen for distributed thunks, it is in Sema now! * [Distributed] no need to check stored props in protocols * remote not used flag * fix mangling test * [Distributed] Synthesis: Don't re-use AST nodes for `decodeArgument` references * [Distributed] Synthesis: Make sure that each thunk parameter has an internal name * [Distributed/Synthesis] NFC: Add a comment regarding empty internal parameter names * [Distributed] NFC: Adjust distributed thunk manglings in the accessor section test-cases * cleanup * [Distributed] NFC: Adjust distributed thunk manglings in the accessor thunk test-cases * review follow ups * xfail some linux tests for now so we can land the AST thunk * Update distributed_actor_remote_functions.swift Co-authored-by: Pavel Yaskevich <[email protected]>
1 parent 0d87a10 commit 5ab8e08

File tree

68 files changed

+1518
-1636
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1518
-1636
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,10 +830,20 @@ the compiler.
830830

831831
This `async` function uses the pre-SE-0338 semantics of unsafely inheriting the caller's executor. This is an underscored feature because the right way of inheriting an executor is to pass in the required executor and switch to it. Unfortunately, there are functions in the standard library which need to inherit their caller's executor but cannot change their ABI because they were not defined as `@_alwaysEmitIntoClient` in the initial release.
832832

833+
833834
## `@_spi_available(platform, version)`
834835

835836
Like `@available`, this attribute indicates a decl is available only as an SPI.
836837
This implies several behavioral changes comparing to regular `@available`:
837838
1. Type checker diagnoses when a client accidently exposes such a symbol in library APIs.
838839
2. When emitting public interfaces, `@_spi_available` is printed as `@available(platform, unavailable)`.
839840
3. ClangImporter imports ObjC macros `SPI_AVAILABLE` and `__SPI_AVAILABLE` to this attribute.
841+
842+
843+
## `_local`
844+
845+
A distributed actor can be marked as "known to be local" which allows avoiding
846+
the distributed actor isolation checks. This is used for things like `whenLocal`
847+
where the actor passed to the closure is known-to-be-local, and similarly a
848+
`self` of obtained from an _isolated_ function inside a distributed actor is
849+
also guaranteed to be local by construction.

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,12 +658,11 @@ class ASTContext final {
658658

659659
/// Retrieve the declaration of DistributedActorSystem.make().
660660
///
661-
/// \param actorOrSystem distributed actor or actor system to get the
662-
/// remoteCall function for. Since the method we're looking for is an ad-hoc
663-
/// requirement, a specific type MUST be passed here as it is not possible
664-
/// to obtain the decl from just the `DistributedActorSystem` protocol type.
661+
/// \param thunk the function from which we'll be invoking things on the obtained
662+
/// actor system; This way we'll always get the right type, taking care of any
663+
/// where clauses etc.
665664
FuncDecl *getMakeInvocationEncoderOnDistributedActorSystem(
666-
NominalTypeDecl *actorOrSystem) const;
665+
AbstractFunctionDecl *thunk) const;
667666

668667
// Retrieve the declaration of
669668
// DistributedInvocationEncoder.recordGenericSubstitution(_:).

include/swift/AST/Attr.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ TYPE_ATTR(async)
5757
TYPE_ATTR(Sendable)
5858
TYPE_ATTR(unchecked)
5959
TYPE_ATTR(_typeSequence)
60+
TYPE_ATTR(_local)
6061

6162
// SIL-specific attributes
6263
TYPE_ATTR(block_storage)
@@ -720,6 +721,13 @@ DECL_ATTR(_backDeploy, BackDeploy,
720721
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove,
721722
129)
722723

724+
CONTEXTUAL_SIMPLE_DECL_ATTR(_local, KnownToBeLocal,
725+
DeclModifier | OnFunc | OnParam | OnVar |
726+
DistributedOnly |
727+
ABIBreakingToAdd | ABIBreakingToRemove |
728+
APIBreakingToAdd | APIBreakingToRemove,
729+
130)
730+
723731
// If you're adding a new underscored attribute here, please document it in
724732
// docs/ReferenceGuides/UnderscoredAttributes.md.
725733

include/swift/AST/Decl.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4490,10 +4490,6 @@ class ProtocolDecl final : public NominalTypeDecl {
44904490
/// semantics but has no corresponding witness table.
44914491
bool isMarkerProtocol() const;
44924492

4493-
/// Is a protocol that can only be conformed by distributed actors.
4494-
/// Such protocols are allowed to contain distributed functions.
4495-
bool inheritsFromDistributedActor() const;
4496-
44974493
private:
44984494
void computeKnownProtocolKind() const;
44994495

@@ -5254,6 +5250,10 @@ class VarDecl : public AbstractStorageDecl {
52545250
/// Does this have a 'distributed' modifier?
52555251
bool isDistributed() const;
52565252

5253+
/// Is this var known to be a "local" distributed actor,
5254+
/// if so the implicit throwing ans some isolation checks can be skipped.
5255+
bool isKnownToBeLocal() const;
5256+
52575257
/// Is this a stored property that will _not_ trigger any user-defined code
52585258
/// upon any kind of access?
52595259
bool isOrdinaryStoredProperty() const;
@@ -6308,6 +6308,13 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
63086308
/// Returns 'true' if the function is distributed.
63096309
bool isDistributed() const;
63106310

6311+
/// For a 'distributed' target (func or computed property),
6312+
/// get the 'thunk' responsible for performing the 'remoteCall'.
6313+
///
6314+
/// \return the synthesized thunk, or null if the base of the call has
6315+
/// diagnosed errors during type checking.
6316+
FuncDecl *getDistributedThunk() const;
6317+
63116318
/// Returns 'true' if the function has the @c @_backDeploy attribute.
63126319
bool isBackDeployed() const;
63136320

@@ -6455,6 +6462,16 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
64556462
/// 'DistributedActorSystem' protocol.
64566463
bool isDistributedActorSystemRemoteCall(bool isVoidReturn) const;
64576464

6465+
/// Determines whether this function is a 'makeInvocationEncoder' function,
6466+
/// which is used as ad-hoc protocol requirement by the
6467+
/// 'DistributedActorSystem' protocol.
6468+
bool isDistributedActorSystemMakeInvocationEncoder() const;
6469+
6470+
/// Determines if this function is a 'recordGenericSubstitution' function,
6471+
/// which is used as ad-hoc protocol requirement by the
6472+
/// 'DistributedTargetInvocationEncoder' protocol.
6473+
bool isDistributedTargetInvocationEncoderRecordGenericSubstitution() const;
6474+
64586475
/// Determines if this function is a 'recordArgument' function,
64596476
/// which is used as ad-hoc protocol requirement by the
64606477
/// 'DistributedTargetInvocationEncoder' protocol.

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4595,6 +4595,9 @@ NOTE(note_distributed_actor_isolated_method,none,
45954595
ERROR(distributed_actor_isolated_method,none,
45964596
"only 'distributed' instance methods can be called on a potentially remote distributed actor",
45974597
())
4598+
ERROR(distributed_local_cannot_be_used,none,
4599+
"'local' cannot be used in user-defined code currently",
4600+
())
45984601
ERROR(distributed_actor_func_param_not_codable,none,
45994602
"parameter '%0' of type %1 in %2 does not conform to serialization requirement '%3'",
46004603
(StringRef, Type, DescriptiveDeclKind, StringRef))

include/swift/AST/DistributedDecl.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ class DeclContext;
3131
class FuncDecl;
3232
class NominalTypeDecl;
3333

34+
/// Determine the concrete type of 'ActorSystem' as seen from the member.
35+
/// E.g. when in a protocol, and trying to determine what the actor system was
36+
/// constrained to.
37+
///
38+
/// \param member the member from which context the lookup should be performed,
39+
/// e.g. a function or computed property.
40+
/// \return the concrete type of the ActorSystem to be used by this member,
41+
/// or null if no concrete actor system was found.
42+
Type getConcreteReplacementForProtocolActorSystemType(ValueDecl *member);
43+
3444
/// Determine the `ActorSystem` type for the given actor.
3545
Type getDistributedActorSystemType(NominalTypeDecl *actor);
3646

@@ -43,14 +53,12 @@ Type getDistributedActorIDType(NominalTypeDecl *actor);
4353
Type getDistributedSerializationRequirementType(
4454
NominalTypeDecl *nominal, ProtocolDecl *protocol);
4555

46-
///// Determine the serialization requirement for the given actor, actor system
47-
///// or other type that has the SerializationRequirement associated type.
48-
//Type getDistributedSerializationRequirementType(
49-
// NominalTypeDecl *nominal, ProtocolDecl *protocol);
50-
51-
Type getDistributedActorSystemActorIDRequirementType(
52-
NominalTypeDecl *system);
56+
/// Get the specific 'InvocationEncoder' type of a specific distributed actor
57+
/// system.
58+
Type getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *system);
5359

60+
/// Get the 'ActorID' type of a specific distributed actor system.
61+
Type getDistributedActorSystemActorIDRequirementType(NominalTypeDecl *system);
5462

5563
/// Get the specific protocols that the `SerializationRequirement` specifies,
5664
/// and all parameters / return types of distributed targets must conform to.

include/swift/AST/Expr.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
313313
NumCaptures : 32
314314
);
315315

316-
SWIFT_INLINE_BITFIELD(ApplyExpr, Expr, 1+1+1+1+1+1,
316+
SWIFT_INLINE_BITFIELD(ApplyExpr, Expr, 1+1+1+1+1+1+1,
317317
ThrowsIsSet : 1,
318318
Throws : 1,
319319
ImplicitlyAsync : 1,
@@ -1908,6 +1908,11 @@ class TryExpr : public AnyTryExpr {
19081908
static bool classof(const Expr *e) {
19091909
return e->getKind() == ExprKind::Try;
19101910
}
1911+
1912+
static TryExpr *createImplicit(ASTContext &ctx, SourceLoc tryLoc, Expr *sub,
1913+
Type type = Type()) {
1914+
return new (ctx) TryExpr(tryLoc, sub, type, /*implicit=*/true);
1915+
}
19111916
};
19121917

19131918
/// ForceTryExpr - A 'try!' surrounding an expression, marking that
@@ -2066,7 +2071,11 @@ class AwaitExpr final : public IdentityExpr {
20662071
bool implicit = false)
20672072
: IdentityExpr(ExprKind::Await, sub, type, implicit), AwaitLoc(awaitLoc) {
20682073
}
2069-
2074+
2075+
static AwaitExpr *createImplicit(ASTContext &ctx, SourceLoc awaitLoc, Expr *sub, Type type = Type()) {
2076+
return new (ctx) AwaitExpr(awaitLoc, sub, type, /*implicit=*/true);
2077+
}
2078+
20702079
SourceLoc getLoc() const { return AwaitLoc; }
20712080

20722081
SourceLoc getAwaitLoc() const { return AwaitLoc; }
@@ -4509,11 +4518,11 @@ class ApplyExpr : public Expr {
45094518
}
45104519

45114520
/// Is this application _implicitly_ required to be a throwing call?
4512-
/// This can happen if the function is actually a proxy function invocation,
4513-
/// which may throw, regardless of the target function throwing, e.g.
4514-
/// a distributed instance method call on a 'remote' actor, may throw due to network
4515-
/// issues reported by the transport, regardless if the actual target function
4516-
/// can throw.
4521+
/// This can happen if the function is actually a distributed thunk
4522+
/// invocation, which may throw, regardless of the target function throwing,
4523+
/// e.g. a distributed instance method call on a 'remote' actor, may throw due
4524+
/// to network issues reported by the transport, regardless if the actual
4525+
/// target function can throw.
45174526
bool implicitlyThrows() const {
45184527
return Bits.ApplyExpr.ImplicitlyThrows;
45194528
}

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ IDENTIFIER(target)
293293
IDENTIFIER(throwing)
294294
IDENTIFIER(using)
295295
IDENTIFIER(InvocationDecoder)
296+
IDENTIFIER(InvocationEncoder)
296297
IDENTIFIER(whenLocal)
297298
IDENTIFIER(decodeNextArgument)
298299
IDENTIFIER(SerializationRequirement)

include/swift/AST/KnownSDKTypes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ KNOWN_SDK_TYPE_DECL(Concurrency, TaskLocal, ClassDecl, 1)
4545

4646
// Distributed actors
4747
KNOWN_SDK_TYPE_DECL(Distributed, DistributedActor, ProtocolDecl, 0)
48+
KNOWN_SDK_TYPE_DECL(Distributed, DistributedActorSystem, ProtocolDecl, 0)
49+
KNOWN_SDK_TYPE_DECL(Distributed, DistributedTargetInvocationEncoder, ProtocolDecl, 0)
50+
KNOWN_SDK_TYPE_DECL(Distributed, DistributedTargetInvocationDecoder, ProtocolDecl, 0)
4851
KNOWN_SDK_TYPE_DECL(Distributed, RemoteCallTarget, StructDecl, 0)
4952

5053
// String processing

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,27 @@ class GetDistributedRemoteCallTargetInitFunctionRequest :
11841184
bool isCached() const { return true; }
11851185
};
11861186

1187+
/// Obtain the 'distributed thunk' for the passed-in function.
1188+
///
1189+
/// The thunk is responsible for invoking 'remoteCall' when invoked on a remote
1190+
/// 'distributed actor'.
1191+
class GetDistributedThunkRequest :
1192+
public SimpleRequest<GetDistributedThunkRequest,
1193+
FuncDecl *(AbstractFunctionDecl *),
1194+
RequestFlags::Cached> {
1195+
public:
1196+
using SimpleRequest::SimpleRequest;
1197+
1198+
private:
1199+
friend SimpleRequest;
1200+
1201+
FuncDecl *evaluate(Evaluator &evaluator, AbstractFunctionDecl *distributedFunc) const;
1202+
1203+
public:
1204+
// Caching
1205+
bool isCached() const { return true; }
1206+
};
1207+
11871208
/// Obtain the 'id' property of a 'distributed actor'.
11881209
class GetDistributedActorIDPropertyRequest :
11891210
public SimpleRequest<GetDistributedActorIDPropertyRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ SWIFT_REQUEST(TypeChecker, GetDistributedTargetInvocationDecoderDecodeNextArgume
125125
SWIFT_REQUEST(TypeChecker, GetDistributedTargetInvocationResultHandlerOnReturnFunctionRequest,
126126
AbstractFunctionDecl *(NominalTypeDecl *),
127127
Cached, NoLocationInfo)
128+
SWIFT_REQUEST(TypeChecker, GetDistributedThunkRequest,
129+
FuncDecl *(AbstractFunctionDecl *),
130+
Cached, NoLocationInfo)
128131
SWIFT_REQUEST(TypeChecker, GetDistributedActorIDPropertyRequest,
129132
VarDecl *(NominalTypeDecl *),
130133
Cached, NoLocationInfo)

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,10 @@ class alignas(1 << TypeAlignInBits) TypeBase
773773
/// Determines whether this type is an actor type.
774774
bool isActorType();
775775

776+
/// Determines whether this type conforms or inherits (if it's a protocol
777+
/// type) from `DistributedActor`.
778+
bool isDistributedActor();
779+
776780
/// Determines the element type of a known
777781
/// [Autoreleasing]Unsafe[Mutable][Raw]Pointer variant, or returns null if the
778782
/// type is not a pointer.

0 commit comments

Comments
 (0)