Skip to content

Commit 91242dc

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 378b6d4 + 3cf257f commit 91242dc

Some content is hidden

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

51 files changed

+553
-196
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,13 +556,14 @@ Types
556556
C-TYPE is mangled according to the Itanium ABI, and prefixed with the length.
557557
Non-ASCII identifiers are preserved as-is; we do not use Punycode.
558558

559-
function-signature ::= params-type params-type async? throws? // results and parameters
559+
function-signature ::= params-type params-type async? concurrent? throws? // results and parameters
560560

561561
params-type ::= type 'z'? 'h'? // tuple in case of multiple parameters or a single parameter with a single tuple type
562562
// with optional inout convention, shared convention. parameters don't have labels,
563563
// they are mangled separately as part of the entity.
564564
params-type ::= empty-list // shortcut for no parameters
565565

566+
concurrent ::= 'J' // @concurrent on function types
566567
async ::= 'Y' // 'async' annotation on function types
567568
throws ::= 'K' // 'throws' annotation on function types
568569

include/swift/ABI/Metadata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,7 @@ struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
16371637
}
16381638
bool isAsync() const { return Flags.isAsync(); }
16391639
bool isThrowing() const { return Flags.isThrowing(); }
1640+
bool isConcurrent() const { return Flags.isConcurrent(); }
16401641
bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
16411642
bool isEscaping() const { return Flags.isEscaping(); }
16421643

include/swift/ABI/MetadataValues.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,7 @@ class TargetFunctionTypeFlags {
779779
DifferentiableMask = 0x08000000U,
780780
LinearMask = 0x10000000U,
781781
AsyncMask = 0x20000000U,
782+
ConcurrentMask = 0x40000000U,
782783
};
783784
int_type Data;
784785

@@ -831,6 +832,13 @@ class TargetFunctionTypeFlags {
831832
(isEscaping ? EscapingMask : 0));
832833
}
833834

835+
constexpr TargetFunctionTypeFlags<int_type>
836+
withConcurrent(bool isConcurrent) const {
837+
return TargetFunctionTypeFlags<int_type>(
838+
(Data & ~ConcurrentMask) |
839+
(isConcurrent ? ConcurrentMask : 0));
840+
}
841+
834842
unsigned getNumParameters() const { return Data & NumParametersMask; }
835843

836844
FunctionMetadataConvention getConvention() const {
@@ -845,6 +853,10 @@ class TargetFunctionTypeFlags {
845853
return bool (Data & EscapingMask);
846854
}
847855

856+
bool isConcurrent() const {
857+
return bool (Data & ConcurrentMask);
858+
}
859+
848860
bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }
849861

850862
bool isDifferentiable() const {

include/swift/AST/Attr.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ TYPE_ATTR(escaping)
5454
TYPE_ATTR(differentiable)
5555
TYPE_ATTR(noDerivative)
5656
TYPE_ATTR(async)
57+
TYPE_ATTR(concurrent)
5758

5859
// SIL-specific attributes
5960
TYPE_ATTR(block_storage)
@@ -599,6 +600,12 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(async, Async,
599600
APIBreakingToAdd | APIBreakingToRemove,
600601
106)
601602

603+
SIMPLE_DECL_ATTR(concurrent, Concurrent,
604+
OnFunc | OnConstructor | OnAccessor | ConcurrencyOnly |
605+
ABIStableToAdd | ABIStableToRemove |
606+
APIBreakingToAdd | APIBreakingToRemove,
607+
107)
608+
602609
#undef TYPE_ATTR
603610
#undef DECL_ATTR_ALIAS
604611
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5773,6 +5773,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
57735773
/// type of the function will be `async` as well.
57745774
bool hasAsync() const { return Bits.AbstractFunctionDecl.Async; }
57755775

5776+
/// Determine whether the given function is concurrent.
5777+
///
5778+
/// A function is concurrent if it has the @concurrent attribute.
5779+
bool isConcurrent() const;
5780+
57765781
/// Returns true if the function is a suitable 'async' context.
57775782
///
57785783
/// Functions that are an 'async' context can make calls to 'async' functions.

include/swift/AST/DiagnosticsSema.def

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3727,26 +3727,30 @@ NOTE(silence_debug_description_in_interpolation_segment_call,none,
37273727
"use 'String(describing:)' to silence this warning", ())
37283728

37293729
NOTE(noescape_parameter,none,
3730-
"parameter %0 is implicitly non-escaping",
3731-
(Identifier))
3730+
"parameter %1 is implicitly %select{non-escaping|non-concurrent}0",
3731+
(unsigned, Identifier))
37323732
NOTE(generic_parameters_always_escaping,none,
37333733
"generic parameters are always considered '@escaping'", ())
37343734

3735-
ERROR(passing_noescape_to_escaping,none,
3736-
"passing non-escaping parameter %0 to function expecting an @escaping closure",
3737-
(Identifier))
3735+
ERROR(passing_noattrfunc_to_attrfunc,none,
3736+
"passing %select{non-escaping|non-concurrent}0 parameter %1 to function "
3737+
"expecting %select{an @escaping|a @concurrent}0 closure",
3738+
(unsigned, Identifier))
37383739
ERROR(converting_noespace_param_to_generic_type,none,
37393740
"converting non-escaping parameter %0 to generic parameter %1 may allow it to escape",
37403741
(Identifier, Type))
3741-
ERROR(assigning_noescape_to_escaping,none,
3742-
"assigning non-escaping parameter %0 to an @escaping closure",
3743-
(Identifier))
3744-
ERROR(general_noescape_to_escaping,none,
3745-
"using non-escaping parameter %0 in a context expecting an @escaping closure",
3746-
(Identifier))
3747-
ERROR(converting_noescape_to_type,none,
3748-
"converting non-escaping value to %0 may allow it to escape",
3749-
(Type))
3742+
ERROR(assigning_noattrfunc_to_attrfunc,none,
3743+
"assigning %select{non-escaping|non-concurrent}0 parameter %1 to "
3744+
"%select{an @escaping|a @concurrent}0 closure",
3745+
(unsigned, Identifier))
3746+
ERROR(general_noattrfunc_to_attr,none,
3747+
"using %select{non-escaping|non-concurrent}0 parameter %1 in a context "
3748+
"expecting %select{an @escaping|a @concurrent}0 closure",
3749+
(unsigned, Identifier))
3750+
ERROR(converting_noattrfunc_to_type,none,
3751+
"converting %select{non-escaping|non-concurrent function}0 value to %1 "
3752+
"may %select{allow it to escape|introduce data races}0",
3753+
(unsigned, Type))
37503754

37513755
ERROR(capture_across_type_decl,none,
37523756
"%0 declaration cannot close over value %1 defined in outer scope",
@@ -4256,10 +4260,23 @@ WARNING(concurrent_access_local,none,
42564260
"local %0 %1 is unsafe to reference in code that may execute "
42574261
"concurrently",
42584262
(DescriptiveDeclKind, DeclName))
4259-
ERROR(actor_isolated_concurrent_access,none,
4260-
"actor-isolated %0 %1 is unsafe to reference in code "
4261-
"that may execute concurrently",
4263+
ERROR(actor_isolated_from_concurrent_closure,none,
4264+
"actor-isolated %0 %1 cannot be referenced from a concurrent closure",
4265+
(DescriptiveDeclKind, DeclName))
4266+
ERROR(actor_isolated_from_concurrent_function,none,
4267+
"actor-isolated %0 %1 cannot be referenced from a concurrent function",
4268+
(DescriptiveDeclKind, DeclName))
4269+
ERROR(actor_isolated_from_async_let,none,
4270+
"actor-isolated %0 %1 cannot be referenced from 'async let' initializer",
42624271
(DescriptiveDeclKind, DeclName))
4272+
ERROR(actor_isolated_from_escaping_closure,none,
4273+
"actor-isolated %0 %1 cannot be referenced from an '@escaping' closure",
4274+
(DescriptiveDeclKind, DeclName))
4275+
ERROR(local_function_executed_concurrently,none,
4276+
"concurrently-executed %0 %1 must be marked as '@concurrent'",
4277+
(DescriptiveDeclKind, DeclName))
4278+
NOTE(concurrent_access_here,none,
4279+
"access in concurrently-executed code here", ())
42634280
NOTE(actor_isolated_sync_func,none,
42644281
"calls to %0 %1 from outside of its actor context are "
42654282
"implicitly asynchronous",

include/swift/AST/ExtInfo.h

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,20 +289,21 @@ class ASTExtInfoBuilder {
289289
friend AnyFunctionType;
290290
friend ASTExtInfo;
291291

292-
// If bits are added or removed, then TypeBase::AnyFunctionTypeBits
292+
// If bits are added or removed, then TypeBase::NumAFTExtInfoBits
293293
// and NumMaskBits must be updated, and they must match.
294294
//
295-
// |representation|noEscape|async|throws|differentiability|
296-
// | 0 .. 3 | 4 | 5 | 6 | 7 .. 8 |
295+
// |representation|noEscape|concurrent|async|throws|differentiability|
296+
// | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 9 |
297297
//
298298
enum : unsigned {
299299
RepresentationMask = 0xF << 0,
300300
NoEscapeMask = 1 << 4,
301-
AsyncMask = 1 << 5,
302-
ThrowsMask = 1 << 6,
303-
DifferentiabilityMaskOffset = 7,
301+
ConcurrentMask = 1 << 5,
302+
AsyncMask = 1 << 6,
303+
ThrowsMask = 1 << 7,
304+
DifferentiabilityMaskOffset = 8,
304305
DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset,
305-
NumMaskBits = 9
306+
NumMaskBits = 10
306307
};
307308

308309
unsigned bits; // Naturally sized for speed.
@@ -350,6 +351,8 @@ class ASTExtInfoBuilder {
350351

351352
constexpr bool isNoEscape() const { return bits & NoEscapeMask; }
352353

354+
constexpr bool isConcurrent() const { return bits & ConcurrentMask; }
355+
353356
constexpr bool isAsync() const { return bits & AsyncMask; }
354357

355358
constexpr bool isThrowing() const { return bits & ThrowsMask; }
@@ -407,6 +410,12 @@ class ASTExtInfoBuilder {
407410
clangTypeInfo);
408411
}
409412
LLVM_NODISCARD
413+
ASTExtInfoBuilder withConcurrent(bool concurrent = true) const {
414+
return ASTExtInfoBuilder(concurrent ? (bits | ConcurrentMask)
415+
: (bits & ~ConcurrentMask),
416+
clangTypeInfo);
417+
}
418+
LLVM_NODISCARD
410419
ASTExtInfoBuilder withAsync(bool async = true) const {
411420
return ASTExtInfoBuilder(async ? (bits | AsyncMask)
412421
: (bits & ~AsyncMask),
@@ -497,6 +506,8 @@ class ASTExtInfo {
497506

498507
constexpr bool isNoEscape() const { return builder.isNoEscape(); }
499508

509+
constexpr bool isConcurrent() const { return builder.isConcurrent(); }
510+
500511
constexpr bool isAsync() const { return builder.isAsync(); }
501512

502513
constexpr bool isThrowing() const { return builder.isThrowing(); }
@@ -529,6 +540,14 @@ class ASTExtInfo {
529540
return builder.withNoEscape(noEscape).build();
530541
}
531542

543+
/// Helper method for changing only the concurrent field.
544+
///
545+
/// Prefer using \c ASTExtInfoBuilder::withConcurrent for chaining.
546+
LLVM_NODISCARD
547+
ASTExtInfo withConcurrent(bool concurrent = true) const {
548+
return builder.withConcurrent(concurrent).build();
549+
}
550+
532551
/// Helper method for changing only the throws field.
533552
///
534553
/// Prefer using \c ASTExtInfoBuilder::withThrows for chaining.

include/swift/AST/TypeMatcher.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ class TypeMatcher {
208208
if (firstFunc->isNoEscape() != secondFunc->isNoEscape())
209209
return mismatch(firstFunc.getPointer(), secondFunc, sugaredFirstType);
210210

211+
if (firstFunc->isConcurrent() != secondFunc->isConcurrent())
212+
return mismatch(firstFunc.getPointer(), secondFunc, sugaredFirstType);
213+
211214
auto sugaredFirstFunc = sugaredFirstType->castTo<AnyFunctionType>();
212215
if (firstFunc->getParams().size() != secondFunc->getParams().size())
213216
return mismatch(firstFunc.getPointer(), secondFunc, sugaredFirstFunc);

include/swift/AST/Types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
315315
}
316316

317317
protected:
318-
enum { NumAFTExtInfoBits = 9 };
318+
enum { NumAFTExtInfoBits = 10 };
319319
enum { NumSILExtInfoBits = 9 };
320320
union { uint64_t OpaqueBits;
321321

@@ -3145,6 +3145,10 @@ class AnyFunctionType : public TypeBase {
31453145
return getExtInfo().isNoEscape();
31463146
}
31473147

3148+
bool isConcurrent() const {
3149+
return getExtInfo().isConcurrent();
3150+
}
3151+
31483152
bool isAsync() const { return getExtInfo().isAsync(); }
31493153

31503154
bool isThrowing() const { return getExtInfo().isThrowing(); }

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ NODE(EnumCase)
8585
NODE(ErrorType)
8686
NODE(EscapingAutoClosureType)
8787
NODE(NoEscapeFunctionType)
88+
NODE(ConcurrentFunctionType)
8889
NODE(ExistentialMetatype)
8990
CONTEXT_NODE(ExplicitClosure)
9091
CONTEXT_NODE(Extension)

include/swift/Demangling/TypeDecoder.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,14 +645,22 @@ class TypeDecoder {
645645
++firstChildIdx;
646646
}
647647

648+
bool isConcurrent = false;
649+
if (Node->getChild(firstChildIdx)->getKind()
650+
== NodeKind::ConcurrentFunctionType) {
651+
isConcurrent = true;
652+
++firstChildIdx;
653+
}
654+
648655
bool isAsync = false;
649656
if (Node->getChild(firstChildIdx)->getKind()
650657
== NodeKind::AsyncAnnotation) {
651658
isAsync = true;
652659
++firstChildIdx;
653660
}
654661

655-
flags = flags.withAsync(isAsync).withThrows(isThrow);
662+
flags = flags.withConcurrent(isConcurrent)
663+
.withAsync(isAsync).withThrows(isThrow);
656664

657665
if (Node->getNumChildren() < firstChildIdx + 2)
658666
return MAKE_NODE_TYPE_ERROR(Node,

include/swift/Sema/CSFix.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,26 @@ class ForceOptional final : public ContextualMismatch {
615615
ConstraintLocator *locator);
616616
};
617617

618+
/// This is a contextual mismatch between @concurrent and non-@concurrent
619+
/// function types, repair it by adding @concurrent attribute.
620+
class AddConcurrentAttribute final : public ContextualMismatch {
621+
AddConcurrentAttribute(ConstraintSystem &cs, FunctionType *fromType,
622+
FunctionType *toType, ConstraintLocator *locator)
623+
: ContextualMismatch(cs, fromType, toType, locator) {
624+
assert(fromType->isConcurrent() != toType->isConcurrent());
625+
}
626+
627+
public:
628+
std::string getName() const override { return "add '@concurrent' attribute"; }
629+
630+
bool diagnose(const Solution &solution, bool asNote = false) const override;
631+
632+
static AddConcurrentAttribute *create(ConstraintSystem &cs,
633+
FunctionType *fromType,
634+
FunctionType *toType,
635+
ConstraintLocator *locator);
636+
};
637+
618638
/// This is a contextual mismatch between throwing and non-throwing
619639
/// function types, repair it by dropping `throws` attribute.
620640
class DropThrowsAttribute final : public ContextualMismatch {

include/swift/Sema/ConstraintLocator.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ class LocatorPathElt::PatternMatch final : public StoredPointerElement<Pattern>
741741

742742
class LocatorPathElt::ArgumentAttribute final : public StoredIntegerElement<1> {
743743
public:
744-
enum Attribute : uint8_t { InOut, Escaping };
744+
enum Attribute : uint8_t { InOut, Escaping, Concurrent };
745745

746746
private:
747747
ArgumentAttribute(Attribute attr)
@@ -758,6 +758,10 @@ class LocatorPathElt::ArgumentAttribute final : public StoredIntegerElement<1> {
758758
return ArgumentAttribute(Attribute::Escaping);
759759
}
760760

761+
static ArgumentAttribute forConcurrent() {
762+
return ArgumentAttribute(Attribute::Concurrent);
763+
}
764+
761765
static bool classof(const LocatorPathElt *elt) {
762766
return elt->getKind() == ConstraintLocator::ArgumentAttribute;
763767
}

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,6 +2531,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25312531
if (auto fType = Ty->getAs<AnyFunctionType>()) {
25322532
if (!fType->getExtInfo().isNoEscape())
25332533
PrintWithColorRAII(OS, ClosureModifierColor) << " escaping";
2534+
if (fType->getExtInfo().isConcurrent())
2535+
PrintWithColorRAII(OS, ClosureModifierColor) << " concurrent";
25342536
}
25352537
}
25362538

@@ -3810,6 +3812,7 @@ namespace {
38103812
getSILFunctionTypeRepresentationString(representation));
38113813

38123814
printFlag(!T->isNoEscape(), "escaping");
3815+
printFlag(T->isConcurrent(), "concurrent");
38133816
printFlag(T->isAsync(), "async");
38143817
printFlag(T->isThrowing(), "throws");
38153818

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,6 +2377,8 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
23772377
appendFunctionInputType(fn->getParams(), forDecl);
23782378
if (fn->isAsync() || functionMangling == AsyncHandlerBodyMangling)
23792379
appendOperator("Y");
2380+
if (fn->isConcurrent())
2381+
appendOperator("J");
23802382
if (fn->isThrowing())
23812383
appendOperator("K");
23822384
}

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,6 +4160,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41604160
}
41614161
}
41624162

4163+
if (!Options.excludeAttrKind(TAK_concurrent) &&
4164+
info.isConcurrent()) {
4165+
Printer << "@concurrent ";
4166+
}
4167+
41634168
SmallString<64> buf;
41644169
switch (Options.PrintFunctionRepresentationAttrs) {
41654170
case PrintOptions::FunctionRepresentationMode::None:

0 commit comments

Comments
 (0)