@@ -1063,6 +1063,108 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
1063
1063
llvm_unreachable (" Unhandled ConstraintKind in switch." );
1064
1064
}
1065
1065
1066
+ // / Check whether given parameter list represents a single tuple
1067
+ // / or type variable which could be later resolved to tuple.
1068
+ // / This is useful for SE-0110 related fixes in `matchFunctionTypes`.
1069
+ static bool isSingleTupleParam (ASTContext &ctx,
1070
+ ArrayRef<AnyFunctionType::Param> params) {
1071
+ if (params.size () != 1 )
1072
+ return false ;
1073
+
1074
+ const auto ¶m = params.front ();
1075
+ if (param.isVariadic () || param.isInOut ())
1076
+ return false ;
1077
+
1078
+ auto paramType = param.getPlainType ();
1079
+ // Support following case which was allowed until 5:
1080
+ //
1081
+ // func bar(_: (Int, Int) -> Void) {}
1082
+ // let foo: ((Int, Int)?) -> Void = { _ in }
1083
+ //
1084
+ // bar(foo) // Ok
1085
+ if (!ctx.isSwiftVersionAtLeast (5 ))
1086
+ paramType = paramType->lookThroughAllOptionalTypes ();
1087
+
1088
+ // Parameter should have a label and be either a tuple tuple type,
1089
+ // or a type variable which might later be assigned a tuple type,
1090
+ // e.g. opened generic parameter.
1091
+ return !param.hasLabel () &&
1092
+ (paramType->is <TupleType>() || paramType->is <TypeVariableType>());
1093
+ }
1094
+
1095
+ // / Attempt to fix missing arguments by introducing type variables
1096
+ // / and inferring their types from parameters.
1097
+ static bool fixMissingArguments (ConstraintSystem &cs, Expr *anchor,
1098
+ FunctionType *funcType,
1099
+ SmallVectorImpl<AnyFunctionType::Param> &args,
1100
+ SmallVectorImpl<AnyFunctionType::Param> ¶ms,
1101
+ unsigned numMissing,
1102
+ ConstraintLocatorBuilder locator) {
1103
+ assert (args.size () < params.size ());
1104
+
1105
+ auto &ctx = cs.getASTContext ();
1106
+ // If there are N parameters but a single closure argument
1107
+ // (which might be anonymous), it's most likely used as a
1108
+ // tuple e.g. `$0.0`.
1109
+ Optional<TypeBase *> argumentTuple;
1110
+ if (isa<ClosureExpr>(anchor) && isSingleTupleParam (ctx, args)) {
1111
+ auto isParam = [](const Expr *expr) {
1112
+ if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1113
+ if (auto *decl = DRE->getDecl ())
1114
+ return isa<ParamDecl>(decl);
1115
+ }
1116
+ return false ;
1117
+ };
1118
+
1119
+ const auto &arg = args.back ();
1120
+ if (auto *argTy = arg.getPlainType ()->getAs <TypeVariableType>()) {
1121
+ anchor->forEachChildExpr ([&](Expr *expr) -> Expr * {
1122
+ if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
1123
+ if (!isParam (UDE->getBase ()))
1124
+ return expr;
1125
+
1126
+ auto name = UDE->getName ().getBaseIdentifier ();
1127
+ unsigned index = 0 ;
1128
+ if (!name.str ().getAsInteger (10 , index) ||
1129
+ llvm::any_of (params, [&](const AnyFunctionType::Param ¶m) {
1130
+ return param.getLabel () == name;
1131
+ })) {
1132
+ argumentTuple.emplace (argTy);
1133
+ args.pop_back ();
1134
+ return nullptr ;
1135
+ }
1136
+ }
1137
+ return expr;
1138
+ });
1139
+ }
1140
+ }
1141
+
1142
+ for (unsigned i = args.size (), n = params.size (); i != n; ++i) {
1143
+ auto *argLoc = cs.getConstraintLocator (
1144
+ anchor, LocatorPathElt::getSynthesizedArgument (i));
1145
+ args.push_back (params[i].withType (cs.createTypeVariable (argLoc)));
1146
+ }
1147
+
1148
+ ArrayRef<AnyFunctionType::Param> argsRef (args);
1149
+ auto *fix =
1150
+ AddMissingArguments::create (cs, funcType, argsRef.take_back (numMissing),
1151
+ cs.getConstraintLocator (locator));
1152
+
1153
+ if (cs.recordFix (fix))
1154
+ return true ;
1155
+
1156
+ // If the argument was a single "tuple", let's bind newly
1157
+ // synthesized arguments to it.
1158
+ if (argumentTuple) {
1159
+ cs.addConstraint (ConstraintKind::Bind, *argumentTuple,
1160
+ FunctionType::composeInput (ctx, args,
1161
+ /* canonicalVararg=*/ false ),
1162
+ cs.getConstraintLocator (anchor));
1163
+ }
1164
+
1165
+ return false ;
1166
+ }
1167
+
1066
1168
ConstraintSystem::TypeMatchResult
1067
1169
ConstraintSystem::matchFunctionTypes (FunctionType *func1, FunctionType *func2,
1068
1170
ConstraintKind kind, TypeMatchOptions flags,
@@ -1137,33 +1239,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1137
1239
// Add a very narrow exception to SE-0110 by allowing functions that
1138
1240
// take multiple arguments to be passed as an argument in places
1139
1241
// that expect a function that takes a single tuple (of the same
1140
- // arity).
1141
- auto isSingleParam = [&](ArrayRef<AnyFunctionType::Param> params) {
1142
- if (params.size () != 1 )
1143
- return false ;
1144
-
1145
- const auto ¶m = params.front ();
1146
- if (param.isVariadic () || param.isInOut ())
1147
- return false ;
1148
-
1149
- auto paramType = param.getPlainType ();
1150
- // Support following case which was allowed until 5:
1151
- // ``swift
1152
- // func bar(_: (Int, Int) -> Void) {}
1153
- // let foo: ((Int, Int)?) -> Void = { _ in }
1154
- //
1155
- // bar(foo) // Ok
1156
- // ```
1157
- if (!getASTContext ().isSwiftVersionAtLeast (5 ))
1158
- paramType = paramType->lookThroughAllOptionalTypes ();
1159
-
1160
- // Parameter should have a label and be either a tuple tuple type,
1161
- // or a type variable which might later be assigned a tuple type,
1162
- // e.g. opened generic parameter.
1163
- return !param.hasLabel () &&
1164
- (paramType->is <TupleType>() || paramType->is <TypeVariableType>());
1165
- };
1166
-
1242
+ // arity);
1167
1243
auto canImplodeParams = [&](ArrayRef<AnyFunctionType::Param> params) {
1168
1244
if (params.size () == 1 )
1169
1245
return false ;
@@ -1194,12 +1270,13 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1194
1270
});
1195
1271
1196
1272
if (last != path.rend ()) {
1273
+ auto &ctx = getASTContext ();
1197
1274
if (last->getKind () == ConstraintLocator::ApplyArgToParam) {
1198
- if (isSingleParam ( func2Params) &&
1275
+ if (isSingleTupleParam (ctx, func2Params) &&
1199
1276
canImplodeParams (func1Params)) {
1200
1277
implodeParams (func1Params);
1201
- } else if (!getASTContext () .isSwiftVersionAtLeast (5 ) &&
1202
- isSingleParam ( func1Params) &&
1278
+ } else if (!ctx .isSwiftVersionAtLeast (5 ) &&
1279
+ isSingleTupleParam (ctx, func1Params) &&
1203
1280
canImplodeParams (func2Params)) {
1204
1281
auto *simplified = locator.trySimplifyToExpr ();
1205
1282
// We somehow let tuple unsplatting function conversions
@@ -1236,7 +1313,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1236
1313
1237
1314
if (last != path.rend ()) {
1238
1315
if (last->getKind () == ConstraintLocator::ApplyArgToParam) {
1239
- if (isSingleParam ( func1Params) &&
1316
+ if (isSingleTupleParam ( getASTContext (), func1Params) &&
1240
1317
func1Params[0 ].getOldType ()->isVoid ()) {
1241
1318
if (func2Params.empty ()) {
1242
1319
func2Params.emplace_back (getASTContext ().TheEmptyTupleType );
@@ -1262,68 +1339,9 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
1262
1339
// If there are missing arguments, let's add them
1263
1340
// using parameter as a template.
1264
1341
if (diff < 0 ) {
1265
- // If there are N parameters but a single closure argument
1266
- // (which might be anonymous), it's most likely used as a
1267
- // tuple e.g. `$0.0`.
1268
- Optional<TypeBase *> argumentTuple;
1269
- if (isa<ClosureExpr>(anchor) && isSingleParam (func1Params)) {
1270
- auto isParam = [](const Expr *expr) {
1271
- if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1272
- if (auto *decl = DRE->getDecl ())
1273
- return isa<ParamDecl>(decl);
1274
- }
1275
- return false ;
1276
- };
1277
-
1278
- const auto &arg = func1Params.back ();
1279
- if (auto *argTy = arg.getPlainType ()->getAs <TypeVariableType>()) {
1280
- anchor->forEachChildExpr ([&](Expr *expr) -> Expr * {
1281
- if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
1282
- if (!isParam (UDE->getBase ()))
1283
- return expr;
1284
-
1285
- auto name = UDE->getName ().getBaseIdentifier ();
1286
- unsigned index = 0 ;
1287
- if (!name.str ().getAsInteger (10 , index) ||
1288
- llvm::any_of (func2Params,
1289
- [&](const AnyFunctionType::Param ¶m) {
1290
- return param.getLabel () == name;
1291
- })) {
1292
- argumentTuple.emplace (argTy);
1293
- func1Params.pop_back ();
1294
- return nullptr ;
1295
- }
1296
- }
1297
- return expr;
1298
- });
1299
- }
1300
- }
1301
-
1302
- for (unsigned i = func1Params.size (),
1303
- n = func2Params.size (); i != n; ++i) {
1304
- auto *argLoc = getConstraintLocator (
1305
- anchor, LocatorPathElt::getSynthesizedArgument (i));
1306
-
1307
- auto arg = func2Params[i].withType (createTypeVariable (argLoc));
1308
- func1Params.push_back (arg);
1309
- }
1310
-
1311
- ArrayRef<AnyFunctionType::Param> argsRef (func1Params);
1312
- auto *fix = AddMissingArguments::create (*this , func2,
1313
- argsRef.take_back (abs (diff)),
1314
- getConstraintLocator (locator));
1315
-
1316
- if (recordFix (fix))
1342
+ if (fixMissingArguments (*this , anchor, func2, func1Params, func2Params,
1343
+ abs (diff), locator))
1317
1344
return getTypeMatchFailure (argumentLocator);
1318
-
1319
- // If the argument was a single "tuple", let's bind newly
1320
- // synthesized arguments to it.
1321
- if (argumentTuple) {
1322
- addConstraint (ConstraintKind::Bind, *argumentTuple,
1323
- FunctionType::composeInput (getASTContext (), func1Params,
1324
- /* canonicalVararg=*/ false ),
1325
- getConstraintLocator (anchor));
1326
- }
1327
1345
} else {
1328
1346
// TODO(diagnostics): Add handling of extraneous arguments.
1329
1347
return getTypeMatchFailure (argumentLocator);
0 commit comments