@@ -116,6 +116,13 @@ static void determineBestChoicesInContext(
116
116
if (!argumentList || cs.containsIDEInspectionTarget (argumentList))
117
117
return ;
118
118
119
+ SmallVector<FunctionType::Param, 8 > argsWithLabels;
120
+ {
121
+ argsWithLabels.append (argFuncType->getParams ().begin (),
122
+ argFuncType->getParams ().end ());
123
+ FunctionType::relabelParams (argsWithLabels, argumentList);
124
+ }
125
+
119
126
SmallVector<SmallVector<std::pair<Type, /* fromLiteral=*/ bool >, 2 >, 2 >
120
127
candidateArgumentTypes;
121
128
candidateArgumentTypes.resize (argFuncType->getNumParams ());
@@ -159,6 +166,27 @@ static void determineBestChoicesInContext(
159
166
resultTypes.push_back (resultType);
160
167
}
161
168
169
+ // Match arguments to the given overload choice.
170
+ auto matchArguments =
171
+ [&](OverloadChoice choice,
172
+ FunctionType *overloadType) -> Optional<MatchCallArgumentResult> {
173
+ auto *decl = choice.getDeclOrNull ();
174
+ assert (decl);
175
+
176
+ auto hasAppliedSelf =
177
+ decl->hasCurriedSelf () &&
178
+ doesMemberRefApplyCurriedSelf (choice.getBaseType (), decl);
179
+
180
+ ParameterListInfo paramListInfo (overloadType->getParams (), decl,
181
+ hasAppliedSelf);
182
+
183
+ MatchCallArgumentListener listener;
184
+ return matchCallArguments (argsWithLabels, overloadType->getParams (),
185
+ paramListInfo,
186
+ argumentList->getFirstTrailingClosureIndex (),
187
+ /* allow fixes*/ false , listener, None);
188
+ };
189
+
162
190
// The choice with the best score.
163
191
double bestScore = 0.0 ;
164
192
SmallVector<std::pair<Constraint *, double >, 2 > favoredChoices;
@@ -182,27 +210,35 @@ static void determineBestChoicesInContext(
182
210
return ;
183
211
}
184
212
185
- ParameterListInfo paramListInfo (
186
- overloadType->getParams (), decl,
187
- hasAppliedSelf (cs, choice->getOverloadChoice ()));
213
+ auto matchings =
214
+ matchArguments (choice->getOverloadChoice (), overloadType);
215
+ if (!matchings)
216
+ return ;
188
217
189
218
double score = 0.0 ;
190
- for (unsigned i = 0 , n = overloadType->getNumParams (); i != n; ++i) {
191
- const auto ¶m = overloadType->getParams ()[i];
192
-
193
- if (i >= candidateArgumentTypes.size ()) {
194
- // If parameter has a default - continue matching,
195
- // all of the subsequence parameters should have defaults
196
- // as well, if they don't the overload choice in not viable.
197
- if (paramListInfo.hasDefaultArgument (i))
198
- continue ;
219
+ for (unsigned paramIdx = 0 , n = overloadType->getNumParams ();
220
+ paramIdx != n; ++paramIdx) {
221
+ const auto ¶m = overloadType->getParams ()[paramIdx];
222
+
223
+ auto argIndices = matchings->parameterBindings [paramIdx];
224
+ switch (argIndices.size ()) {
225
+ case 0 :
226
+ // Current parameter is defaulted.
227
+ continue ;
228
+
229
+ case 1 :
230
+ // One-to-one match between argument and parameter.
231
+ break ;
199
232
200
- // Early return because this overload choice is not viable
201
- // without default value for the current parameter .
233
+ default :
234
+ // Cannot deal with multiple possible matchings at the moment .
202
235
return ;
203
236
}
204
237
205
- if (candidateArgumentTypes[i].empty ())
238
+ auto argIdx = argIndices.front ();
239
+
240
+ // Looks like there is nothing know about the argument.
241
+ if (candidateArgumentTypes[argIdx].empty ())
206
242
continue ;
207
243
208
244
const auto paramFlags = param.getParameterFlags ();
@@ -220,9 +256,6 @@ static void determineBestChoicesInContext(
220
256
if (paramType->is <FunctionType>())
221
257
continue ;
222
258
223
- if (candidateArgumentTypes[i].empty ())
224
- continue ;
225
-
226
259
// Check protocol requirement(s) if this parameter is a
227
260
// generic parameter type.
228
261
GenericSignature::RequiredProtocols protocolRequirements;
@@ -248,11 +281,11 @@ static void determineBestChoicesInContext(
248
281
// all bound concrete types, we consider this is mismatch
249
282
// at this parameter position and remove the overload choice
250
283
// from consideration.
251
-
252
284
double bestCandidateScore = 0 ;
253
- llvm::BitVector mismatches (candidateArgumentTypes[i ].size ());
285
+ llvm::BitVector mismatches (candidateArgumentTypes[argIdx ].size ());
254
286
255
- for (unsigned candidateIdx : indices (candidateArgumentTypes[i])) {
287
+ for (unsigned candidateIdx :
288
+ indices (candidateArgumentTypes[argIdx])) {
256
289
// If one of the candidates matched exactly there is no reason
257
290
// to continue checking.
258
291
if (bestCandidateScore == 1 )
@@ -262,7 +295,7 @@ static void determineBestChoicesInContext(
262
295
bool isLiteralDefault;
263
296
264
297
std::tie (candidateType, isLiteralDefault) =
265
- candidateArgumentTypes[i ][candidateIdx];
298
+ candidateArgumentTypes[argIdx ][candidateIdx];
266
299
267
300
// `inout` parameter accepts only l-value argument.
268
301
if (paramFlags.isInOut () && !candidateType->is <LValueType>()) {
0 commit comments