Skip to content

Commit db14ab1

Browse files
committed
Sink concurrency constraint fix behavior logic into "attempt" functions.
This is a cleaner pattern for the solver, thanks Pavel!
1 parent 8a8efcb commit db14ab1

File tree

4 files changed

+97
-55
lines changed

4 files changed

+97
-55
lines changed

include/swift/Sema/CSFix.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,16 @@ class MarkGlobalActorFunction final : public ContextualMismatch {
799799
Type rhs, ConstraintLocator *locator,
800800
FixBehavior fixBehavior);
801801

802+
/// Try to apply this fix to the given types.
803+
///
804+
/// \returns \c true if the fix cannot be applied and the solver must fail,
805+
/// or \c false if the fix has been applied and the solver can continue.
806+
static bool attempt(ConstraintSystem &cs,
807+
ConstraintKind constraintKind,
808+
FunctionType *fromType,
809+
FunctionType *toType,
810+
ConstraintLocatorBuilder locator);
811+
802812
static bool classof(ConstraintFix *fix) {
803813
return fix->getKind() == FixKind::MarkGlobalActorFunction;
804814
}
@@ -850,6 +860,16 @@ class AddSendableAttribute final : public ContextualMismatch {
850860
ConstraintLocator *locator,
851861
FixBehavior fixBehavior);
852862

863+
/// Try to apply this fix to the given types.
864+
///
865+
/// \returns \c true if the fix cannot be applied and the solver must fail,
866+
/// or \c false if the fix has been applied and the solver can continue.
867+
static bool attempt(ConstraintSystem &cs,
868+
ConstraintKind constraintKind,
869+
FunctionType *fromType,
870+
FunctionType *toType,
871+
ConstraintLocatorBuilder locator);
872+
853873
static bool classof(ConstraintFix *fix) {
854874
return fix->getKind() == FixKind::AddSendableAttribute;
855875
}

include/swift/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,6 +3820,10 @@ class ConstraintSystem {
38203820
});
38213821
}
38223822

3823+
/// Determine whether the callee for the given locator is marked as
3824+
/// `@preconcurrency`.
3825+
bool hasPreconcurrencyCallee(ConstraintLocatorBuilder locator);
3826+
38233827
/// Determine whether the given declaration is unavailable from the
38243828
/// current context.
38253829
bool isDeclUnavailable(const Decl *D,

lib/Sema/CSFix.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//===----------------------------------------------------------------------===//
1818

1919
#include "CSDiagnostics.h"
20+
#include "TypeCheckConcurrency.h"
2021
#include "swift/AST/Expr.h"
2122
#include "swift/AST/ParameterList.h"
2223
#include "swift/AST/Type.h"
@@ -247,6 +248,38 @@ bool MarkGlobalActorFunction::diagnose(const Solution &solution,
247248
return failure.diagnose(asNote);
248249
}
249250

251+
/// The fix behavior to apply to a concurrency-related diagnostic.
252+
static Optional<FixBehavior>
253+
getConcurrencyFixBehavior(
254+
ConstraintSystem &cs, ConstraintKind constraintKind,
255+
ConstraintLocatorBuilder locator, bool forSendable) {
256+
// We can only handle the downgrade for conversions.
257+
switch (constraintKind) {
258+
case ConstraintKind::Conversion:
259+
case ConstraintKind::ArgumentConversion:
260+
break;
261+
262+
default:
263+
if (!cs.shouldAttemptFixes())
264+
return None;
265+
266+
return FixBehavior::Error;
267+
}
268+
269+
// For a @preconcurrency callee outside of a strict concurrency
270+
// context, ignore.
271+
if (cs.hasPreconcurrencyCallee(locator) &&
272+
!contextRequiresStrictConcurrencyChecking(
273+
cs.DC, GetClosureType{cs}, ClosureIsolatedByPreconcurrency{cs}))
274+
return FixBehavior::Suppress;
275+
276+
// Otherwise, warn until Swift 6.
277+
if (!cs.getASTContext().LangOpts.isSwiftVersionAtLeast(6))
278+
return FixBehavior::DowngradeToWarning;
279+
280+
return FixBehavior::Error;
281+
}
282+
250283
MarkGlobalActorFunction *
251284
MarkGlobalActorFunction::create(ConstraintSystem &cs, Type lhs, Type rhs,
252285
ConstraintLocator *locator,
@@ -259,6 +292,23 @@ MarkGlobalActorFunction::create(ConstraintSystem &cs, Type lhs, Type rhs,
259292
cs, lhs, rhs, locator, fixBehavior);
260293
}
261294

295+
bool MarkGlobalActorFunction::attempt(ConstraintSystem &cs,
296+
ConstraintKind constraintKind,
297+
FunctionType *fromType,
298+
FunctionType *toType,
299+
ConstraintLocatorBuilder locator) {
300+
auto fixBehavior = getConcurrencyFixBehavior(
301+
cs, constraintKind, locator, /*forSendable=*/false);
302+
if (!fixBehavior)
303+
return true;
304+
305+
auto *fix = MarkGlobalActorFunction::create(
306+
cs, fromType, toType, cs.getConstraintLocator(locator),
307+
*fixBehavior);
308+
309+
return cs.recordFix(fix);
310+
}
311+
262312
bool AddSendableAttribute::diagnose(const Solution &solution,
263313
bool asNote) const {
264314
AttributedFuncToTypeConversionFailure failure(
@@ -280,6 +330,22 @@ AddSendableAttribute::create(ConstraintSystem &cs,
280330
return new (cs.getAllocator()) AddSendableAttribute(
281331
cs, fromType, toType, locator, fixBehavior);
282332
}
333+
334+
bool AddSendableAttribute::attempt(ConstraintSystem &cs,
335+
ConstraintKind constraintKind,
336+
FunctionType *fromType,
337+
FunctionType *toType,
338+
ConstraintLocatorBuilder locator) {
339+
auto fixBehavior = getConcurrencyFixBehavior(
340+
cs, constraintKind, locator, /*forSendable=*/true);
341+
if (!fixBehavior)
342+
return true;
343+
344+
auto *fix = AddSendableAttribute::create(
345+
cs, fromType, toType, cs.getConstraintLocator(locator), *fixBehavior);
346+
return cs.recordFix(fix);
347+
}
348+
283349
bool RelabelArguments::diagnose(const Solution &solution, bool asNote) const {
284350
LabelingFailure failure(solution, getLocator(), getLabels());
285351
return failure.diagnose(asNote);

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,14 +2655,10 @@ static bool fixExtraneousArguments(ConstraintSystem &cs,
26552655
/*impact=*/numExtraneous * 2);
26562656
}
26572657

2658-
bool hasPreconcurrencyCallee(ConstraintSystem *cs,
2659-
ConstraintLocatorBuilder locator) {
2660-
if (cs->getASTContext().isSwiftVersionAtLeast(6))
2661-
// Swift 6 mode does not reduce errors to warnings.
2662-
return false;
2663-
2664-
auto calleeLocator = cs->getCalleeLocator(cs->getConstraintLocator(locator));
2665-
auto calleeOverload = cs->findSelectedOverloadFor(calleeLocator);
2658+
bool ConstraintSystem::hasPreconcurrencyCallee(
2659+
ConstraintLocatorBuilder locator) {
2660+
auto calleeLocator = getCalleeLocator(getConstraintLocator(locator));
2661+
auto calleeOverload = findSelectedOverloadFor(calleeLocator);
26662662
if (!calleeOverload || !calleeOverload->choice.isDecl())
26672663
return false;
26682664

@@ -2716,48 +2712,12 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
27162712
increaseScore(SK_SyncInAsync);
27172713
}
27182714

2719-
/// The behavior limit to apply to a concurrency check.
2720-
auto getConcurrencyFixBehavior = [&](
2721-
bool forSendable
2722-
) -> Optional<FixBehavior> {
2723-
// We can only handle the downgrade for conversions.
2724-
switch (kind) {
2725-
case ConstraintKind::Conversion:
2726-
case ConstraintKind::ArgumentConversion:
2727-
break;
2728-
2729-
default:
2730-
if (!shouldAttemptFixes())
2731-
return None;
2732-
2733-
return FixBehavior::Error;
2734-
}
2735-
2736-
// For a @preconcurrency callee outside of a strict concurrency
2737-
// context, ignore.
2738-
if (hasPreconcurrencyCallee(this, locator) &&
2739-
!contextRequiresStrictConcurrencyChecking(DC, GetClosureType{*this}, ClosureIsolatedByPreconcurrency{*this}))
2740-
return FixBehavior::Suppress;
2741-
2742-
// Otherwise, warn until Swift 6.
2743-
if (!getASTContext().LangOpts.isSwiftVersionAtLeast(6))
2744-
return FixBehavior::DowngradeToWarning;
2745-
2746-
return FixBehavior::Error;
2747-
};
2748-
27492715
// A @Sendable function can be a subtype of a non-@Sendable function.
27502716
if (func1->isSendable() != func2->isSendable()) {
27512717
// Cannot add '@Sendable'.
27522718
if (func2->isSendable() || kind < ConstraintKind::Subtype) {
2753-
if (auto fixBehavior = getConcurrencyFixBehavior(true)) {
2754-
auto *fix = AddSendableAttribute::create(
2755-
*this, func1, func2, getConstraintLocator(locator), *fixBehavior);
2756-
if (recordFix(fix))
2757-
return getTypeMatchFailure(locator);
2758-
} else {
2719+
if (AddSendableAttribute::attempt(*this, kind, func1, func2, locator))
27592720
return getTypeMatchFailure(locator);
2760-
}
27612721
}
27622722
}
27632723

@@ -2785,16 +2745,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
27852745
return getTypeMatchFailure(locator);
27862746
} else if (func1->getGlobalActor() && !func2->isAsync()) {
27872747
// Cannot remove a global actor from a synchronous function.
2788-
if (auto fixBehavior = getConcurrencyFixBehavior(false)) {
2789-
auto *fix = MarkGlobalActorFunction::create(
2790-
*this, func1, func2, getConstraintLocator(locator),
2791-
*fixBehavior);
2792-
2793-
if (recordFix(fix))
2794-
return getTypeMatchFailure(locator);
2795-
} else {
2748+
if (MarkGlobalActorFunction::attempt(*this, kind, func1, func2, locator))
27962749
return getTypeMatchFailure(locator);
2797-
}
27982750
} else if (kind < ConstraintKind::Subtype) {
27992751
return getTypeMatchFailure(locator);
28002752
}
@@ -9839,7 +9791,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
98399791
auto *inferredClosureType = getClosureType(closure);
98409792

98419793
// Note if this closure is isolated by preconcurrency.
9842-
if (hasPreconcurrencyCallee(this, locator))
9794+
if (hasPreconcurrencyCallee(locator))
98439795
preconcurrencyClosures.insert(closure);
98449796

98459797
// Let's look through all optionals associated with contextual

0 commit comments

Comments
 (0)