Skip to content

Commit 19263a7

Browse files
authored
Merge pull request swiftlang#36466 from DougGregor/global-actor-function-types
Global actor function types
2 parents d96760b + 0f8e1ca commit 19263a7

26 files changed

+515
-111
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3843,6 +3843,9 @@ ERROR(converting_noattrfunc_to_type,none,
38433843
"may %select{allow it to escape|introduce data races}0",
38443844
(unsigned, Type))
38453845

3846+
ERROR(converting_func_loses_global_actor,none,
3847+
"converting function value of type %0 to %1 loses global actor %2",
3848+
(Type, Type, Type))
38463849
ERROR(capture_across_type_decl,none,
38473850
"%0 declaration cannot close over value %1 defined in outer scope",
38483851
(DescriptiveDeclKind, Identifier))
@@ -4499,10 +4502,6 @@ ERROR(global_actor_non_unsafe_init,none,
44994502
ERROR(actor_isolation_multiple_attr,none,
45004503
"%0 %1 has multiple actor-isolation attributes ('%2' and '%3')",
45014504
(DescriptiveDeclKind, DeclName, StringRef, StringRef))
4502-
ERROR(global_actor_isolated_synchronous_closure,none,
4503-
"closure isolated to global actor %0 must be 'async'",
4504-
(Type))
4505-
45064505
ERROR(actor_isolation_override_mismatch,none,
45074506
"%0 %1 %2 has different actor isolation from %3 overridden declaration",
45084507
(ActorIsolation, DescriptiveDeclKind, DeclName, ActorIsolation))

include/swift/AST/ExtInfo.h

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -309,33 +309,38 @@ class ASTExtInfoBuilder {
309309
unsigned bits; // Naturally sized for speed.
310310

311311
ClangTypeInfo clangTypeInfo;
312+
Type globalActor;
312313

313314
using Representation = FunctionTypeRepresentation;
314315

315-
ASTExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
316-
: bits(bits), clangTypeInfo(clangTypeInfo) {}
316+
ASTExtInfoBuilder(
317+
unsigned bits, ClangTypeInfo clangTypeInfo, Type globalActor
318+
) : bits(bits), clangTypeInfo(clangTypeInfo), globalActor(globalActor) {}
317319

318320
public:
319321
/// An ExtInfoBuilder for a typical Swift function: @convention(swift),
320322
/// @escaping, non-throwing, non-differentiable.
321323
ASTExtInfoBuilder()
322324
: ASTExtInfoBuilder(Representation::Swift, false, false,
323-
DifferentiabilityKind::NonDifferentiable, nullptr) {}
325+
DifferentiabilityKind::NonDifferentiable, nullptr,
326+
Type()) {}
324327

325328
// Constructor for polymorphic type.
326329
ASTExtInfoBuilder(Representation rep, bool throws)
327330
: ASTExtInfoBuilder(rep, false, throws,
328-
DifferentiabilityKind::NonDifferentiable, nullptr) {}
331+
DifferentiabilityKind::NonDifferentiable, nullptr,
332+
Type()) {}
329333

330334
// Constructor with no defaults.
331335
ASTExtInfoBuilder(Representation rep, bool isNoEscape, bool throws,
332-
DifferentiabilityKind diffKind, const clang::Type *type)
336+
DifferentiabilityKind diffKind, const clang::Type *type,
337+
Type globalActor)
333338
: ASTExtInfoBuilder(
334339
((unsigned)rep) | (isNoEscape ? NoEscapeMask : 0) |
335340
(throws ? ThrowsMask : 0) |
336341
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
337342
DifferentiabilityMask),
338-
ClangTypeInfo(type)) {}
343+
ClangTypeInfo(type), globalActor) {}
339344

340345
void checkInvariants() const;
341346

@@ -374,6 +379,8 @@ class ASTExtInfoBuilder {
374379
return SILFunctionTypeRepresentation(rawRep);
375380
}
376381

382+
Type getGlobalActor() const { return globalActor; }
383+
377384
constexpr bool hasSelfParam() const {
378385
switch (getSILRepresentation()) {
379386
case SILFunctionTypeRepresentation::Thick:
@@ -401,42 +408,44 @@ class ASTExtInfoBuilder {
401408
ASTExtInfoBuilder withRepresentation(Representation rep) const {
402409
return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
403410
shouldStoreClangType(rep) ? clangTypeInfo
404-
: ClangTypeInfo());
411+
: ClangTypeInfo(),
412+
globalActor);
405413
}
406414
LLVM_NODISCARD
407415
ASTExtInfoBuilder withNoEscape(bool noEscape = true) const {
408416
return ASTExtInfoBuilder(noEscape ? (bits | NoEscapeMask)
409417
: (bits & ~NoEscapeMask),
410-
clangTypeInfo);
418+
clangTypeInfo, globalActor);
411419
}
412420
LLVM_NODISCARD
413421
ASTExtInfoBuilder withConcurrent(bool concurrent = true) const {
414422
return ASTExtInfoBuilder(concurrent ? (bits | ConcurrentMask)
415423
: (bits & ~ConcurrentMask),
416-
clangTypeInfo);
424+
clangTypeInfo, globalActor);
417425
}
418426
LLVM_NODISCARD
419427
ASTExtInfoBuilder withAsync(bool async = true) const {
420428
return ASTExtInfoBuilder(async ? (bits | AsyncMask)
421429
: (bits & ~AsyncMask),
422-
clangTypeInfo);
430+
clangTypeInfo, globalActor);
423431
}
424432
LLVM_NODISCARD
425433
ASTExtInfoBuilder withThrows(bool throws = true) const {
426434
return ASTExtInfoBuilder(
427-
throws ? (bits | ThrowsMask) : (bits & ~ThrowsMask), clangTypeInfo);
435+
throws ? (bits | ThrowsMask) : (bits & ~ThrowsMask), clangTypeInfo,
436+
globalActor);
428437
}
429438
LLVM_NODISCARD
430439
ASTExtInfoBuilder
431440
withDifferentiabilityKind(DifferentiabilityKind differentiability) const {
432441
return ASTExtInfoBuilder(
433442
(bits & ~DifferentiabilityMask) |
434443
((unsigned)differentiability << DifferentiabilityMaskOffset),
435-
clangTypeInfo);
444+
clangTypeInfo, globalActor);
436445
}
437446
LLVM_NODISCARD
438447
ASTExtInfoBuilder withClangFunctionType(const clang::Type *type) const {
439-
return ASTExtInfoBuilder(bits, ClangTypeInfo(type));
448+
return ASTExtInfoBuilder(bits, ClangTypeInfo(type), globalActor);
440449
}
441450

442451
/// Put a SIL representation in the ExtInfo.
@@ -449,16 +458,25 @@ class ASTExtInfoBuilder {
449458
withSILRepresentation(SILFunctionTypeRepresentation rep) const {
450459
return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
451460
shouldStoreClangType(rep) ? clangTypeInfo
452-
: ClangTypeInfo());
461+
: ClangTypeInfo(),
462+
globalActor);
463+
}
464+
465+
LLVM_NODISCARD
466+
ASTExtInfoBuilder withGlobalActor(Type globalActor) const {
467+
return ASTExtInfoBuilder(bits, clangTypeInfo, globalActor);
453468
}
454469

455470
bool isEqualTo(ASTExtInfoBuilder other, bool useClangTypes) const {
456471
return bits == other.bits &&
457-
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true);
472+
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true) &&
473+
globalActor.getPointer() == other.globalActor.getPointer();
458474
}
459475

460-
constexpr std::pair<unsigned, const void *> getFuncAttrKey() const {
461-
return std::make_pair(bits, clangTypeInfo.getType());
476+
constexpr std::tuple<unsigned, const void *, const void *>
477+
getFuncAttrKey() const {
478+
return std::make_tuple(
479+
bits, clangTypeInfo.getType(), globalActor.getPointer());
462480
}
463481
}; // end ASTExtInfoBuilder
464482

@@ -479,8 +497,8 @@ class ASTExtInfo {
479497
// Only for use by ASTExtInfoBuilder::build. Don't use it elsewhere!
480498
ASTExtInfo(ASTExtInfoBuilder builder) : builder(builder) {}
481499

482-
ASTExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo)
483-
: builder(bits, clangTypeInfo) {
500+
ASTExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo, Type globalActor)
501+
: builder(bits, clangTypeInfo, globalActor) {
484502
builder.checkInvariants();
485503
};
486504

@@ -524,6 +542,8 @@ class ASTExtInfo {
524542

525543
constexpr bool hasContext() const { return builder.hasContext(); }
526544

545+
Type getGlobalActor() const { return builder.getGlobalActor(); }
546+
527547
/// Helper method for changing the representation.
528548
///
529549
/// Prefer using \c ASTExtInfoBuilder::withRepresentation for chaining.
@@ -564,11 +584,17 @@ class ASTExtInfo {
564584
return builder.withAsync(async).build();
565585
}
566586

587+
LLVM_NODISCARD
588+
ASTExtInfo withGlobalActor(Type globalActor) const {
589+
return builder.withGlobalActor(globalActor).build();
590+
}
591+
567592
bool isEqualTo(ASTExtInfo other, bool useClangTypes) const {
568593
return builder.isEqualTo(other.builder, useClangTypes);
569594
}
570595

571-
constexpr std::pair<unsigned, const void *> getFuncAttrKey() const {
596+
constexpr std::tuple<unsigned, const void *, const void *>
597+
getFuncAttrKey() const {
572598
return builder.getFuncAttrKey();
573599
}
574600
}; // end ASTExtInfo

include/swift/AST/Types.h

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,13 @@ class alignas(1 << TypeAlignInBits) TypeBase {
348348
Flags : NumFlagBits
349349
);
350350

351-
SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+16,
351+
SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+1+16,
352352
/// Extra information which affects how the function is called, like
353353
/// regparm and the calling convention.
354354
ExtInfoBits : NumAFTExtInfoBits,
355355
HasExtInfo : 1,
356356
HasClangTypeInfo : 1,
357+
HasGlobalActor : 1,
357358
: NumPadBits,
358359
NumParams : 16
359360
);
@@ -2933,6 +2934,8 @@ class AnyFunctionType : public TypeBase {
29332934
Bits.AnyFunctionType.ExtInfoBits = Info.getValue().getBits();
29342935
Bits.AnyFunctionType.HasClangTypeInfo =
29352936
!Info.getValue().getClangTypeInfo().empty();
2937+
Bits.AnyFunctionType.HasGlobalActor =
2938+
!Info.getValue().getGlobalActor().isNull();
29362939
// The use of both assert() and static_assert() is intentional.
29372940
assert(Bits.AnyFunctionType.ExtInfoBits == Info.getValue().getBits() &&
29382941
"Bits were dropped!");
@@ -2943,6 +2946,7 @@ class AnyFunctionType : public TypeBase {
29432946
Bits.AnyFunctionType.HasExtInfo = false;
29442947
Bits.AnyFunctionType.HasClangTypeInfo = false;
29452948
Bits.AnyFunctionType.ExtInfoBits = 0;
2949+
Bits.AnyFunctionType.HasGlobalActor = false;
29462950
}
29472951
Bits.AnyFunctionType.NumParams = NumParams;
29482952
assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!");
@@ -2985,9 +2989,15 @@ class AnyFunctionType : public TypeBase {
29852989
return Bits.AnyFunctionType.HasClangTypeInfo;
29862990
}
29872991

2992+
bool hasGlobalActor() const {
2993+
return Bits.AnyFunctionType.HasGlobalActor;
2994+
}
2995+
29882996
ClangTypeInfo getClangTypeInfo() const;
29892997
ClangTypeInfo getCanonicalClangTypeInfo() const;
29902998

2999+
Type getGlobalActor() const;
3000+
29913001
/// Returns true if the function type stores a Clang type that cannot
29923002
/// be derived from its Swift type. Returns false otherwise, including if
29933003
/// the function type is not @convention(c) or @convention(block).
@@ -3010,7 +3020,8 @@ class AnyFunctionType : public TypeBase {
30103020

30113021
ExtInfo getExtInfo() const {
30123022
assert(hasExtInfo());
3013-
return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo());
3023+
return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo(),
3024+
getGlobalActor());
30143025
}
30153026

30163027
/// Get the canonical ExtInfo for the function type.
@@ -3019,9 +3030,13 @@ class AnyFunctionType : public TypeBase {
30193030
/// In the future, we will always use the canonical clang function type.
30203031
ExtInfo getCanonicalExtInfo(bool useClangFunctionType) const {
30213032
assert(hasExtInfo());
3033+
Type globalActor = getGlobalActor();
3034+
if (globalActor)
3035+
globalActor = globalActor->getCanonicalType();
30223036
return ExtInfo(Bits.AnyFunctionType.ExtInfoBits,
30233037
useClangFunctionType ? getCanonicalClangTypeInfo()
3024-
: ClangTypeInfo());
3038+
: ClangTypeInfo(),
3039+
globalActor);
30253040
}
30263041

30273042
bool hasSameExtInfoAs(const AnyFunctionType *otherFn);
@@ -3236,7 +3251,7 @@ class FunctionType final
32363251
: public AnyFunctionType,
32373252
public llvm::FoldingSetNode,
32383253
private llvm::TrailingObjects<FunctionType, AnyFunctionType::Param,
3239-
ClangTypeInfo> {
3254+
ClangTypeInfo, Type> {
32403255
friend TrailingObjects;
32413256

32423257

@@ -3248,6 +3263,10 @@ class FunctionType final
32483263
return hasClangTypeInfo() ? 1 : 0;
32493264
}
32503265

3266+
size_t numTrailingObjects(OverloadToken<Type>) const {
3267+
return hasGlobalActor() ? 1 : 0;
3268+
}
3269+
32513270
public:
32523271
/// 'Constructor' Factory Function
32533272
static FunctionType *get(ArrayRef<Param> params, Type result,
@@ -3267,6 +3286,12 @@ class FunctionType final
32673286
return *info;
32683287
}
32693288

3289+
Type getGlobalActor() const {
3290+
if (!hasGlobalActor())
3291+
return Type();
3292+
return *getTrailingObjects<Type>();
3293+
}
3294+
32703295
void Profile(llvm::FoldingSetNodeID &ID) {
32713296
Optional<ExtInfo> info = None;
32723297
if (hasExtInfo())
@@ -3345,19 +3370,28 @@ std::string getParamListAsString(ArrayRef<AnyFunctionType::Param> parameters);
33453370
/// generic parameters.
33463371
class GenericFunctionType final : public AnyFunctionType,
33473372
public llvm::FoldingSetNode,
3348-
private llvm::TrailingObjects<GenericFunctionType, AnyFunctionType::Param> {
3373+
private llvm::TrailingObjects<GenericFunctionType, AnyFunctionType::Param,
3374+
Type> {
33493375
friend TrailingObjects;
33503376

33513377
GenericSignature Signature;
33523378

3379+
size_t numTrailingObjects(OverloadToken<AnyFunctionType::Param>) const {
3380+
return getNumParams();
3381+
}
3382+
3383+
size_t numTrailingObjects(OverloadToken<Type>) const {
3384+
return hasGlobalActor() ? 1 : 0;
3385+
}
3386+
33533387
/// Construct a new generic function type.
33543388
GenericFunctionType(GenericSignature sig,
33553389
ArrayRef<Param> params,
33563390
Type result,
33573391
Optional<ExtInfo> info,
33583392
const ASTContext *ctx,
33593393
RecursiveTypeProperties properties);
3360-
3394+
33613395
public:
33623396
/// Create a new generic function type.
33633397
static GenericFunctionType *get(GenericSignature sig,
@@ -3369,7 +3403,13 @@ class GenericFunctionType final : public AnyFunctionType,
33693403
ArrayRef<Param> getParams() const {
33703404
return {getTrailingObjects<Param>(), getNumParams()};
33713405
}
3372-
3406+
3407+
Type getGlobalActor() const {
3408+
if (!hasGlobalActor())
3409+
return Type();
3410+
return *getTrailingObjects<Type>();
3411+
}
3412+
33733413
/// Retrieve the generic signature of this function type.
33743414
GenericSignature getGenericSignature() const {
33753415
return Signature;

include/swift/Sema/CSFix.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ enum class FixKind : uint8_t {
7474
/// Mark function type as explicitly '@escaping'.
7575
ExplicitlyEscaping,
7676

77+
/// Mark function type as having a particular global actor.
78+
MarkGlobalActorFunction,
79+
7780
/// Arguments have labeling failures - missing/extraneous or incorrect
7881
/// labels attached to the, fix it by suggesting proper labels.
7982
RelabelArguments,
@@ -628,6 +631,23 @@ class MarkExplicitlyEscaping final : public ContextualMismatch {
628631
Type rhs, ConstraintLocator *locator);
629632
};
630633

634+
/// Mark function type as being part of a global actor.
635+
class MarkGlobalActorFunction final : public ContextualMismatch {
636+
MarkGlobalActorFunction(ConstraintSystem &cs, Type lhs, Type rhs,
637+
ConstraintLocator *locator)
638+
: ContextualMismatch(cs, FixKind::MarkGlobalActorFunction, lhs, rhs,
639+
locator) {
640+
}
641+
642+
public:
643+
std::string getName() const override { return "add @escaping"; }
644+
645+
bool diagnose(const Solution &solution, bool asNote = false) const override;
646+
647+
static MarkGlobalActorFunction *create(ConstraintSystem &cs, Type lhs,
648+
Type rhs, ConstraintLocator *locator);
649+
};
650+
631651
/// Introduce a '!' to force an optional unwrap.
632652
class ForceOptional final : public ContextualMismatch {
633653
ForceOptional(ConstraintSystem &cs, Type fromType, Type toType,

0 commit comments

Comments
 (0)