Skip to content

Commit c09ec72

Browse files
committed
[Constraint System] Always add Sendable to unapplied function applications
1 parent de3b4ba commit c09ec72

File tree

7 files changed

+140
-101
lines changed

7 files changed

+140
-101
lines changed

include/swift/Basic/Features.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,9 @@ EXPERIMENTAL_FEATURE(NonEscapableTypes, false)
259259
/// Enable the `@extern` attribute.
260260
EXPERIMENTAL_FEATURE(Extern, true)
261261

262-
// Infer Sendability of unapplied and partial applied methods
263-
// based on type. Global functions are always implicitly Sendable
264-
EXPERIMENTAL_FEATURE(InferSendableMethods, false)
262+
// Infer Sendability of unapplied and partial applied methods,
263+
// global functions and key paths.
264+
EXPERIMENTAL_FEATURE(InferSendableFromCaptures, false)
265265

266266
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
267267
#undef EXPERIMENTAL_FEATURE

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5420,6 +5420,8 @@ class ConstraintSystem {
54205420
return range.isValid() ? range : llvm::Optional<SourceRange>();
54215421
}
54225422

5423+
bool isPartialApplication(ConstraintLocator *locator);
5424+
54235425
bool isTooComplex(size_t solutionMemory) {
54245426
if (isAlreadyTooComplex.first)
54255427
return true;

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3573,13 +3573,17 @@ static bool usesFeatureSendNonSendable(Decl *decl) {
35733573
return false;
35743574
}
35753575

3576-
static bool usesFeatureGlobalConcurrency(Decl *decl) { return false; }
3576+
static bool usesFeatureGlobalConcurrency(Decl *decl) {
3577+
return false;
3578+
}
35773579

35783580
static bool usesFeatureIsolatedDefaultValues(Decl *decl) {
35793581
return false;
35803582
}
35813583

3582-
static bool usesFeatureInferSendableMethods(Decl *decl) { return false; }
3584+
static bool usesFeatureInferSendableFromCaptures(Decl *decl) {
3585+
return false;
3586+
}
35833587

35843588
static bool usesFeaturePlaygroundExtendedCallbacks(Decl *decl) {
35853589
return false;

lib/Sema/CSSimplify.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9524,32 +9524,25 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
95249524

95259525
// Delay solving member constraint for unapplied methods
95269526
// where the base type has a conditional Sendable conformance
9527-
if (ctx.LangOpts.hasFeature(Feature::InferSendableMethods)) {
9528-
if (functionRefKind == FunctionRefKind::Unapplied) {
9527+
if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) {
9528+
if (isPartialApplication(memberLocator)) {
95299529
auto sendableProtocol =
9530-
DC->getParentModule()->getASTContext().getProtocol(
9530+
Context.getProtocol(
95319531
KnownProtocolKind::Sendable);
95329532
auto baseConformance = DC->getParentModule()->lookupConformance(
95339533
instanceTy, sendableProtocol);
95349534

95359535
if (llvm::any_of(
95369536
baseConformance.getConditionalRequirements(),
95379537
[&](const auto &req) {
9538-
switch (req.getKind()) {
9539-
case RequirementKind::Conformance: {
9540-
if (auto secondType =
9541-
req.getSecondType()->template getAs<ProtocolType>()) {
9542-
return req.getFirstType()->hasTypeVariable() &&
9543-
secondType->getDecl()->isSpecificProtocol(
9544-
KnownProtocolKind::Sendable);
9545-
}
9546-
}
9547-
case RequirementKind::Superclass:
9548-
case RequirementKind::SameType:
9549-
case RequirementKind::SameShape:
9550-
case RequirementKind::Layout:
9538+
if (req.getKind() != RequirementKind::Conformance)
95519539
return false;
9540+
9541+
if (auto protocolTy = req.getSecondType()->template getAs<ProtocolType>()) {
9542+
return req.getFirstType()->hasTypeVariable() &&
9543+
protocolTy->getDecl()->isSpecificProtocol(KnownProtocolKind::Sendable);
95529544
}
9545+
return false;
95539546
})) {
95549547
result.OverallResult = MemberLookupResult::Unsolved;
95559548
return result;

lib/Sema/ConstraintSystem.cpp

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,7 @@ AnyFunctionType *ConstraintSystem::adjustFunctionTypeForConcurrency(
16111611
AnyFunctionType *fnType, ValueDecl *decl, DeclContext *dc,
16121612
unsigned numApplies, bool isMainDispatchQueue, OpenedTypeMap &replacements,
16131613
ConstraintLocatorBuilder locator) {
1614+
16141615
return swift::adjustFunctionTypeForConcurrency(
16151616
fnType, decl, dc, numApplies, isMainDispatchQueue,
16161617
GetClosureType{*this}, ClosureIsolatedByPreconcurrency{*this},
@@ -1712,12 +1713,11 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
17121713
auto numLabelsToRemove = getNumRemovedArgumentLabels(
17131714
funcDecl, /*isCurriedInstanceReference=*/false, functionRefKind);
17141715

1715-
if (ctx.LangOpts.hasFeature(Feature::InferSendableMethods)) {
1716+
if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) {
17161717
// All global functions should be @Sendable
1717-
if (funcDecl->getDeclContext()->isLocalContext()) {
1718+
if (!funcDecl->getDeclContext()->isTypeContext() && !funcDecl->getDeclContext()->isLocalContext() ) {
17181719
funcType =
1719-
funcType->withExtInfo(funcType->getExtInfo().withConcurrent())
1720-
->getAs<AnyFunctionType>();
1720+
funcType->withExtInfo(funcType->getExtInfo().withConcurrent());
17211721
}
17221722
}
17231723

@@ -2426,10 +2426,7 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
24262426
return type;
24272427
}
24282428

2429-
2430-
bool isPartialApplication(ConstraintSystem &cs,
2431-
const AbstractFunctionDecl *member,
2432-
ConstraintLocator *locator) {
2429+
bool ConstraintSystem::isPartialApplication(ConstraintLocator *locator) {
24332430
// If this is a compiler synthesized implicit conversion, let's skip
24342431
// the check because the base of `UDE` is not the base of the injected
24352432
// initializer.
@@ -2442,7 +2439,7 @@ bool isPartialApplication(ConstraintSystem &cs,
24422439
return false;
24432440

24442441
auto baseTy =
2445-
cs.simplifyType(cs.getType(UDE->getBase()))->getWithoutSpecifierType();
2442+
simplifyType(getType(UDE->getBase()))->getWithoutSpecifierType();
24462443

24472444
// If base is a metatype it would be ignored (unless this is an initializer
24482445
// call), but if it is some other type it means that we have a single
@@ -2451,14 +2448,12 @@ bool isPartialApplication(ConstraintSystem &cs,
24512448
if (!baseTy->is<MetatypeType>())
24522449
++level;
24532450

2454-
if (auto *call = dyn_cast_or_null<CallExpr>(cs.getParentExpr(UDE))) {
2455-
level += 1;
2451+
if (auto *call = dyn_cast_or_null<CallExpr>(getParentExpr(UDE))) {
2452+
if (UDE == call->getFn()->getSemanticsProvidingExpr())
2453+
level += 1;
24562454
}
24572455

2458-
if (level == 2)
2459-
return false;
2460-
2461-
return true;
2456+
return level < 2;
24622457
}
24632458

24642459
DeclReferenceType
@@ -2669,37 +2664,21 @@ ConstraintSystem::getTypeOfMemberReference(
26692664
auto *functionType = fullFunctionType->getResult()->getAs<FunctionType>();
26702665
functionType = unwrapPropertyWrapperParameterTypes(*this, funcDecl, functionRefKind,
26712666
functionType, locator);
2672-
auto &ctx = DC->getASTContext();
2673-
auto *parentModule = useDC->getParentModule();
2674-
bool inferredSendable =
2675-
ctx.LangOpts.hasFeature(Feature::InferSendableMethods);
2676-
2677-
bool isPartialApply;
2678-
isPartialApply = isPartialApplication(*this, funcDecl, locator);
2679-
2680-
if (inferredSendable && isPartialApply) {
2681-
// auto sendableProtocol = parentModule->getASTContext().getProtocol(
2682-
// KnownProtocolKind::Sendable);
2683-
// auto baseConformance =
2684-
// parentModule->lookupConformance(baseOpenedTy, sendableProtocol);
2685-
2686-
if (isSendableType(parentModule, baseOpenedTy)) {
2667+
// FIXME: Verify ExtInfo state is correct, not working by accident.
2668+
FunctionType::ExtInfo info;
2669+
2670+
if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) {
2671+
if (isPartialApplication(locator) &&
2672+
isSendableType(DC->getParentModule(), baseOpenedTy)) {
26872673
// Add @Sendable to functions without conditional conformances
26882674
functionType = functionType->withExtInfo(functionType->getExtInfo().withConcurrent())->getAs<FunctionType>();
26892675
}
2676+
// Unapplied values should always be Sendable
2677+
info = info.withConcurrent();
26902678
}
26912679

2692-
// FIXME: Verify ExtInfo state is correct, not working by accident.
2693-
FunctionType::ExtInfo info;
26942680
openedType =
26952681
FunctionType::get(fullFunctionType->getParams(), functionType, info);
2696-
2697-
// Add @Sendable to openedType if possible
2698-
if (inferredSendable) {
2699-
auto origFnType = openedType->castTo<FunctionType>();
2700-
openedType =
2701-
origFnType->withExtInfo(origFnType->getExtInfo().withConcurrent());
2702-
}
27032682
}
27042683

27052684
// Adjust the opened type for concurrency.

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5481,8 +5481,6 @@ AnyFunctionType *swift::adjustFunctionTypeForConcurrency(
54815481
bool strictChecking = contextRequiresStrictConcurrencyChecking(
54825482
dc, getType, isolatedByPreconcurrency);
54835483

5484-
auto &ctx = dc->getASTContext();
5485-
54865484
fnType = applyUnsafeConcurrencyToFunctionType(
54875485
fnType, decl, strictChecking, numApplies, isMainDispatchQueue);
54885486

0 commit comments

Comments
 (0)