Skip to content

Commit 913650d

Browse files
committed
Centralize Dispatch-related @_unsafe(Sendable|MainActor) hacks
1 parent 1b8f562 commit 913650d

File tree

8 files changed

+56
-115
lines changed

8 files changed

+56
-115
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6265,14 +6265,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
62656265
Optional<unsigned> findPotentialCompletionHandlerParam(
62666266
const AbstractFunctionDecl *asyncAlternative = nullptr) const;
62676267

6268-
/// Determine whether this function is implicitly known to have its
6269-
/// parameters of function type be @_unsafeSendable.
6270-
///
6271-
/// This hard-codes knowledge of a number of functions that will
6272-
/// eventually have @_unsafeSendable and, eventually, @Sendable,
6273-
/// on their parameters of function type.
6274-
bool hasKnownUnsafeSendableFunctionParams() const;
6275-
62766268
using DeclContext::operator new;
62776269
using DeclContext::operator delete;
62786270
using Decl::getASTContext;

include/swift/AST/Types.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,8 +3395,6 @@ struct ParameterListInfo {
33953395
SmallBitVector defaultArguments;
33963396
SmallBitVector acceptsUnlabeledTrailingClosures;
33973397
SmallBitVector propertyWrappers;
3398-
SmallBitVector unsafeSendable;
3399-
SmallBitVector unsafeMainActor;
34003398
SmallBitVector implicitSelfCapture;
34013399
SmallBitVector inheritActorContext;
34023400

@@ -3417,16 +3415,6 @@ struct ParameterListInfo {
34173415
/// property wrapper.
34183416
bool hasExternalPropertyWrapper(unsigned paramIdx) const;
34193417

3420-
/// Whether the given parameter is unsafe Sendable, meaning that
3421-
/// we will treat it as Sendable in a context that has adopted concurrency
3422-
/// features.
3423-
bool isUnsafeSendable(unsigned paramIdx) const;
3424-
3425-
/// Whether the given parameter is unsafe MainActor, meaning that
3426-
/// we will treat it as being part of the main actor but that it is not
3427-
/// part of the type system.
3428-
bool isUnsafeMainActor(unsigned paramIdx) const;
3429-
34303418
/// Whether the given parameter is a closure that should allow capture of
34313419
/// 'self' to be implicit, without requiring "self.".
34323420
bool isImplicitSelfCapture(unsigned paramIdx) const;

lib/AST/Decl.cpp

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7733,27 +7733,6 @@ void AbstractFunctionDecl::addDerivativeFunctionConfiguration(
77337733
DerivativeFunctionConfigs->insert(config);
77347734
}
77357735

7736-
bool AbstractFunctionDecl::hasKnownUnsafeSendableFunctionParams() const {
7737-
auto nominal = getDeclContext()->getSelfNominalTypeDecl();
7738-
if (!nominal)
7739-
return false;
7740-
7741-
// DispatchQueue operations.
7742-
auto nominalName = nominal->getName().str();
7743-
if (nominalName == "DispatchQueue") {
7744-
auto name = getBaseName().userFacingName();
7745-
return llvm::StringSwitch<bool>(name)
7746-
.Case("sync", true)
7747-
.Case("async", true)
7748-
.Case("asyncAndWait", true)
7749-
.Case("asyncAfter", true)
7750-
.Case("concurrentPerform", true)
7751-
.Default(false);
7752-
}
7753-
7754-
return false;
7755-
}
7756-
77577736
void FuncDecl::setResultInterfaceType(Type type) {
77587737
getASTContext().evaluator.cacheOutput(ResultTypeRequest{this},
77597738
std::move(type));

lib/AST/Type.cpp

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -928,36 +928,12 @@ static bool allowsUnlabeledTrailingClosureParameter(const ParamDecl *param) {
928928
return paramType->is<AnyFunctionType>();
929929
}
930930

931-
/// Determine whether the parameter is contextually Sendable.
932-
static bool isParamUnsafeSendable(const ParamDecl *param) {
933-
// Check for @_unsafeSendable.
934-
if (param->getAttrs().hasAttribute<UnsafeSendableAttr>())
935-
return true;
936-
937-
// Check that the parameter is of function type.
938-
Type paramType = param->isVariadic() ? param->getVarargBaseTy()
939-
: param->getInterfaceType();
940-
paramType = paramType->getRValueType()->lookThroughAllOptionalTypes();
941-
if (!paramType->is<FunctionType>())
942-
return false;
943-
944-
// Check whether this function is known to have @_unsafeSendable function
945-
// parameters.
946-
auto func = dyn_cast<AbstractFunctionDecl>(param->getDeclContext());
947-
if (!func)
948-
return false;
949-
950-
return func->hasKnownUnsafeSendableFunctionParams();
951-
}
952-
953931
ParameterListInfo::ParameterListInfo(
954932
ArrayRef<AnyFunctionType::Param> params,
955933
const ValueDecl *paramOwner,
956934
bool skipCurriedSelf) {
957935
defaultArguments.resize(params.size());
958936
propertyWrappers.resize(params.size());
959-
unsafeSendable.resize(params.size());
960-
unsafeMainActor.resize(params.size());
961937
implicitSelfCapture.resize(params.size());
962938
inheritActorContext.resize(params.size());
963939

@@ -1012,14 +988,6 @@ ParameterListInfo::ParameterListInfo(
1012988
propertyWrappers.set(i);
1013989
}
1014990

1015-
if (isParamUnsafeSendable(param)) {
1016-
unsafeSendable.set(i);
1017-
}
1018-
1019-
if (param->getAttrs().hasAttribute<UnsafeMainActorAttr>()) {
1020-
unsafeMainActor.set(i);
1021-
}
1022-
1023991
if (param->getAttrs().hasAttribute<ImplicitSelfCaptureAttr>()) {
1024992
implicitSelfCapture.set(i);
1025993
}
@@ -1045,18 +1013,6 @@ bool ParameterListInfo::hasExternalPropertyWrapper(unsigned paramIdx) const {
10451013
return paramIdx < propertyWrappers.size() ? propertyWrappers[paramIdx] : false;
10461014
}
10471015

1048-
bool ParameterListInfo::isUnsafeSendable(unsigned paramIdx) const {
1049-
return paramIdx < unsafeSendable.size()
1050-
? unsafeSendable[paramIdx]
1051-
: false;
1052-
}
1053-
1054-
bool ParameterListInfo::isUnsafeMainActor(unsigned paramIdx) const {
1055-
return paramIdx < unsafeMainActor.size()
1056-
? unsafeMainActor[paramIdx]
1057-
: false;
1058-
}
1059-
10601016
bool ParameterListInfo::isImplicitSelfCapture(unsigned paramIdx) const {
10611017
return paramIdx < implicitSelfCapture.size()
10621018
? implicitSelfCapture[paramIdx]
@@ -1070,8 +1026,7 @@ bool ParameterListInfo::inheritsActorContext(unsigned paramIdx) const {
10701026
}
10711027

10721028
bool ParameterListInfo::anyContextualInfo() const {
1073-
return unsafeSendable.any() || unsafeMainActor.any() ||
1074-
implicitSelfCapture.any() || inheritActorContext.any();
1029+
return implicitSelfCapture.any() || inheritActorContext.any();
10751030
}
10761031

10771032
/// Turn a param list into a symbolic and printable representation that does not

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "CSDiagnostics.h"
1919
#include "TypeChecker.h"
2020
#include "TypeCheckAvailability.h"
21+
#include "TypeCheckConcurrency.h"
2122
#include "TypeCheckType.h"
2223
#include "swift/AST/Initializer.h"
2324
#include "swift/AST/GenericEnvironment.h"
@@ -1356,7 +1357,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
13561357
->castTo<AnyFunctionType>();
13571358
if (!isRequirementOrWitness(locator)) {
13581359
unsigned numApplies = getNumApplications(value, false, functionRefKind);
1359-
funcType = applyGlobalActorType(funcType, func, useDC, numApplies, false);
1360+
funcType = adjustFunctionTypeForConcurrency(funcType, func, useDC, numApplies, false);
13601361
}
13611362
auto openedType = openFunctionType(
13621363
funcType, locator, replacements, func->getDeclContext());
@@ -1389,7 +1390,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
13891390
if (!isRequirementOrWitness(locator)) {
13901391
unsigned numApplies = getNumApplications(
13911392
funcDecl, false, functionRefKind);
1392-
funcType = applyGlobalActorType(
1393+
funcType = adjustFunctionTypeForConcurrency(
13931394
funcType, funcDecl, useDC, numApplies, false);
13941395
}
13951396

@@ -1658,18 +1659,6 @@ Type constraints::getDynamicSelfReplacementType(
16581659
->getMetatypeInstanceType();
16591660
}
16601661

1661-
/// Determine whether the given name is that of a DispatchQueue operation that
1662-
/// takes a closure to be executed on the queue.
1663-
static bool isDispatchQueueOperationName(StringRef name) {
1664-
return llvm::StringSwitch<bool>(name)
1665-
.Case("sync", true)
1666-
.Case("async", true)
1667-
.Case("asyncAndWait", true)
1668-
.Case("asyncAfter", true)
1669-
.Case("concurrentPerform", true)
1670-
.Default(false);
1671-
}
1672-
16731662
/// Determine whether this locator refers to a member of "DispatchQueue.main",
16741663
/// which is a special dispatch queue that executes its work on the main actor.
16751664
static bool isMainDispatchQueueMember(ConstraintLocator *locator) {
@@ -1804,7 +1793,7 @@ ConstraintSystem::getTypeOfMemberReference(
18041793
if (!isRequirementOrWitness(locator)) {
18051794
unsigned numApplies = getNumApplications(
18061795
value, hasAppliedSelf, functionRefKind);
1807-
funcType = applyGlobalActorType(
1796+
funcType = adjustFunctionTypeForConcurrency(
18081797
funcType, value, useDC, numApplies,
18091798
isMainDispatchQueueMember(locator));
18101799
}

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,6 +4056,39 @@ static Type applyUnsafeConcurrencyToParameterType(
40564056
.withGlobalActor(globalActor));
40574057
}
40584058

4059+
/// Determine whether the given name is that of a DispatchQueue operation that
4060+
/// takes a closure to be executed on the queue.
4061+
bool swift::isDispatchQueueOperationName(StringRef name) {
4062+
return llvm::StringSwitch<bool>(name)
4063+
.Case("sync", true)
4064+
.Case("async", true)
4065+
.Case("asyncAndWait", true)
4066+
.Case("asyncAfter", true)
4067+
.Case("concurrentPerform", true)
4068+
.Default(false);
4069+
}
4070+
4071+
/// Determine whether this function is implicitly known to have its
4072+
/// parameters of function type be @_unsafeSendable.
4073+
///
4074+
/// This hard-codes knowledge of a number of functions that will
4075+
/// eventually have @_unsafeSendable and, eventually, @Sendable,
4076+
/// on their parameters of function type.
4077+
static bool hasKnownUnsafeSendableFunctionParams(AbstractFunctionDecl *func) {
4078+
auto nominal = func->getDeclContext()->getSelfNominalTypeDecl();
4079+
if (!nominal)
4080+
return false;
4081+
4082+
// DispatchQueue operations.
4083+
auto nominalName = nominal->getName().str();
4084+
if (nominalName == "DispatchQueue") {
4085+
auto name = func->getBaseName().userFacingName();
4086+
return isDispatchQueueOperationName(name);
4087+
}
4088+
4089+
return false;
4090+
}
4091+
40594092
/// Apply @_unsafeSendable and @_unsafeMainActor to the parameters of the
40604093
/// given function.
40614094
static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
@@ -4079,6 +4112,7 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
40794112
auto typeParams = fnType->getParams();
40804113
auto paramDecls = func->getParameters();
40814114
assert(typeParams.size() == paramDecls->size());
4115+
bool knownUnsafeParams = hasKnownUnsafeSendableFunctionParams(func);
40824116
for (unsigned index : indices(typeParams)) {
40834117
auto param = typeParams[index];
40844118
auto paramDecl = (*paramDecls)[index];
@@ -4089,12 +4123,11 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
40894123
// application.
40904124
bool isSendable =
40914125
(paramDecl->getAttrs().hasAttribute<UnsafeSendableAttr>() ||
4092-
func->hasKnownUnsafeSendableFunctionParams()) &&
4126+
knownUnsafeParams) &&
40934127
inConcurrencyContext;
40944128
bool isMainActor =
40954129
(paramDecl->getAttrs().hasAttribute<UnsafeMainActorAttr>() ||
4096-
(isMainDispatchQueue &&
4097-
func->hasKnownUnsafeSendableFunctionParams())) &&
4130+
(isMainDispatchQueue && knownUnsafeParams)) &&
40984131
(inConcurrencyContext || numApplies >= 1);
40994132

41004133
if (!isSendable && !isMainActor) {
@@ -4110,7 +4143,6 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
41104143
newTypeParams.append(typeParams.begin(), typeParams.begin() + index);
41114144
}
41124145

4113-
41144146
// Transform the parameter type.
41154147
Type newParamType = applyUnsafeConcurrencyToParameterType(
41164148
param.getPlainType(), isSendable, isMainActor);
@@ -4140,7 +4172,7 @@ static AnyFunctionType *applyUnsafeConcurrencyToFunctionType(
41404172
outerFnType->getParams(), Type(fnType), outerFnType->getExtInfo());
41414173
}
41424174

4143-
AnyFunctionType *swift::applyGlobalActorType(
4175+
AnyFunctionType *swift::adjustFunctionTypeForConcurrency(
41444176
AnyFunctionType *fnType, ValueDecl *funcOrEnum, DeclContext *dc,
41454177
unsigned numApplies, bool isMainDispatchQueue) {
41464178
// Apply unsafe concurrency features to the given function type.

lib/Sema/TypeCheckConcurrency.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,23 @@ enum class SendableCheck {
306306
Optional<std::pair<CustomAttr *, NominalTypeDecl *>>
307307
checkGlobalActorAttributes(
308308
SourceLoc loc, DeclContext *dc, ArrayRef<CustomAttr *> attrs);
309-
/// Get the explicit global actor specified for a closure.
310309

310+
/// Get the explicit global actor specified for a closure.
311311
Type getExplicitGlobalActor(ClosureExpr *closure);
312312

313+
/// Adjust the given function type to account for concurrency-specific
314+
/// attributes whose affect on the type might differ based on context.
315+
/// This includes adjustments for unsafe parameter attributes like
316+
/// `@_unsafeSendable` and `@_unsafeMainActor` as well as a global actor
317+
/// on the declaration itself.
318+
AnyFunctionType *adjustFunctionTypeForConcurrency(
319+
AnyFunctionType *fnType, ValueDecl *funcOrEnum, DeclContext *dc,
320+
unsigned numApplies, bool isMainDispatchQueue);
321+
322+
/// Determine whether the given name is that of a DispatchQueue operation that
323+
/// takes a closure to be executed on the queue.
324+
bool isDispatchQueueOperationName(StringRef name);
325+
313326
/// Check the correctness of the given Sendable conformance.
314327
///
315328
/// \returns true if an error occurred.

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,13 +1320,6 @@ void checkUnknownAttrRestrictions(
13201320
/// it to later stages.
13211321
void bindSwitchCasePatternVars(DeclContext *dc, CaseStmt *stmt);
13221322

1323-
/// If the given function has a global actor that should be reflected in
1324-
/// references to its function type from the given declaration context,
1325-
/// update the given function type to include the global actor.
1326-
AnyFunctionType *applyGlobalActorType(
1327-
AnyFunctionType *fnType, ValueDecl *funcOrEnum, DeclContext *dc,
1328-
unsigned numApplies, bool isMainDispatchQueue);
1329-
13301323
/// If \p attr was added by an access note, wraps the error in
13311324
/// \c diag::wrap_invalid_attr_added_by_access_note and limits it as an access
13321325
/// note-related diagnostic should be.

0 commit comments

Comments
 (0)