Skip to content

Commit 8f85b84

Browse files
committed
[ConstraintSystem] Fix closure parameter destructuring
Detect and fix closure parameter destructuring where it's not currently allowed e.g. free standing closures with contextual type `let _: ((Int, Int)) -> Void = { $0 + $1 }`
1 parent c834352 commit 8f85b84

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,18 @@ AllowInvalidInitRef::create(RefKind kind, ConstraintSystem &cs, Type baseTy,
343343
cs, kind, baseTy, init, isStaticallyDerived, baseRange, locator);
344344
}
345345

346+
bool AllowClosureParamDestructuring::diagnose(Expr *root, bool asNote) const {
347+
return false;
348+
}
349+
350+
AllowClosureParamDestructuring *
351+
AllowClosureParamDestructuring::create(ConstraintSystem &cs,
352+
FunctionType *contextualType,
353+
ConstraintLocator *locator) {
354+
return new (cs.getAllocator())
355+
AllowClosureParamDestructuring(cs, contextualType, locator);
356+
}
357+
346358
bool AddMissingArguments::diagnose(Expr *root, bool asNote) const {
347359
MissingArgumentsFailure failure(root, getConstraintSystem(), Fn,
348360
NumSynthesized, getLocator());

lib/Sema/CSFix.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ enum class FixKind : uint8_t {
105105
/// fix this issue by pretending that member exists and matches
106106
/// given arguments/result types exactly.
107107
DefineMemberBasedOnUse,
108-
108+
109109
/// Allow access to type member on instance or instance member on type
110110
AllowTypeOrInstanceMember,
111111

@@ -126,6 +126,9 @@ enum class FixKind : uint8_t {
126126
/// If there are fewer arguments than parameters, let's fix that up
127127
/// by adding new arguments to the list represented as type variables.
128128
AddMissingArguments,
129+
130+
/// Allow single tuple closure parameter destructuring into N arguments.
131+
AllowClosureParameterDestructuring,
129132
};
130133

131134
class ConstraintFix {
@@ -618,6 +621,27 @@ class AllowInvalidInitRef final : public ConstraintFix {
618621
ConstraintLocator *locator);
619622
};
620623

624+
class AllowClosureParamDestructuring final : public ConstraintFix {
625+
FunctionType *ContextualType;
626+
627+
AllowClosureParamDestructuring(ConstraintSystem &cs,
628+
FunctionType *contextualType,
629+
ConstraintLocator *locator)
630+
: ConstraintFix(cs, FixKind::AllowClosureParameterDestructuring, locator),
631+
ContextualType(contextualType) {}
632+
633+
public:
634+
std::string getName() const override {
635+
return "allow closure parameter destructuring";
636+
}
637+
638+
bool diagnose(Expr *root, bool asNote = false) const override;
639+
640+
static AllowClosureParamDestructuring *create(ConstraintSystem &cs,
641+
FunctionType *contextualType,
642+
ConstraintLocator *locator);
643+
};
644+
621645
class AddMissingArguments final
622646
: public ConstraintFix,
623647
private llvm::TrailingObjects<AddMissingArguments,

lib/Sema/CSSimplify.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1288,8 +1288,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
12881288
return elt.getKind() != ConstraintLocator::OptionalPayload;
12891289
});
12901290

1291+
auto &ctx = getASTContext();
12911292
if (last != path.rend()) {
1292-
auto &ctx = getASTContext();
12931293
if (last->getKind() == ConstraintLocator::ApplyArgToParam) {
12941294
if (isSingleTupleParam(ctx, func2Params) &&
12951295
canImplodeParams(func1Params)) {
@@ -1310,6 +1310,20 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
13101310
}
13111311
}
13121312
}
1313+
1314+
if (shouldAttemptFixes()) {
1315+
auto *anchor = locator.trySimplifyToExpr();
1316+
if (anchor && isa<ClosureExpr>(anchor) &&
1317+
isSingleTupleParam(ctx, func2Params) &&
1318+
canImplodeParams(func1Params)) {
1319+
auto *fix = AllowClosureParamDestructuring::create(
1320+
*this, func2, getConstraintLocator(anchor));
1321+
if (recordFix(fix))
1322+
return getTypeMatchFailure(argumentLocator);
1323+
1324+
implodeParams(func1Params);
1325+
}
1326+
}
13131327
}
13141328

13151329
// https://bugs.swift.org/browse/SR-6796
@@ -5779,6 +5793,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
57795793
case FixKind::AllowTypeOrInstanceMember:
57805794
case FixKind::AllowInvalidPartialApplication:
57815795
case FixKind::AllowInvalidInitRef:
5796+
case FixKind::AllowClosureParameterDestructuring:
57825797
llvm_unreachable("handled elsewhere");
57835798
}
57845799

0 commit comments

Comments
 (0)