16
16
17
17
#include " swift/Sema/ConstraintGraph.h"
18
18
#include " swift/Sema/ConstraintSystem.h"
19
+ #include " llvm/ADT/BitVector.h"
19
20
#include " llvm/ADT/DenseMap.h"
20
21
#include " llvm/ADT/SmallVector.h"
21
22
#include " llvm/ADT/TinyPtrVector.h"
@@ -231,20 +232,40 @@ static void determineBestChoicesInContext(
231
232
if (paramType->is <FunctionType>())
232
233
continue ;
233
234
234
- double argScore = 0.0 ;
235
- for (auto const &candidate : candidateArgumentTypes[i]) {
236
- auto candidateType = candidate.first ;
235
+ if (candidateArgumentTypes[i].empty ())
236
+ continue ;
237
+
238
+ // The idea here is to match the parameter type against
239
+ // all of the argument candidate types and pick the best
240
+ // match (i.e. exact equality one).
241
+ //
242
+ // If none of the candidates match exactly and they are
243
+ // all bound concrete types, we consider this is mismatch
244
+ // at this parameter position and remove the overload choice
245
+ // from consideration.
246
+
247
+ double bestCandidateScore = 0 ;
248
+ llvm::BitVector mismatches (candidateArgumentTypes[i].size ());
249
+
250
+ for (unsigned candidateIdx : indices (candidateArgumentTypes[i])) {
251
+ Type candidateType;
252
+ bool isLiteralDefault;
253
+
254
+ std::tie (candidateType, isLiteralDefault) =
255
+ candidateArgumentTypes[i][candidateIdx];
237
256
238
257
// `inout` parameter accepts only l-value argument.
239
- if (paramFlags.isInOut () && !candidateType->is <LValueType>())
258
+ if (paramFlags.isInOut () && !candidateType->is <LValueType>()) {
259
+ mismatches.set (candidateIdx);
240
260
continue ;
261
+ }
241
262
242
263
// The specifier only matters for `inout` check.
243
264
candidateType = candidateType->getWithoutSpecifierType ();
244
265
// Exact match on one of the candidate bindings.
245
266
if (candidateType->isEqual (paramType)) {
246
- argScore = std::max (
247
- argScore, /* fromLiteral= */ candidate. second ? 0.3 : 1.0 );
267
+ bestCandidateScore =
268
+ std::max (bestCandidateScore, isLiteralDefault ? 0.3 : 1.0 );
248
269
continue ;
249
270
}
250
271
@@ -253,14 +274,30 @@ static void determineBestChoicesInContext(
253
274
// and expect a particular `Scalar` if it's known.
254
275
if (isSIMDType (candidateType) &&
255
276
isArithmeticOperatorOnSIMDProtocol (decl)) {
256
- argScore = std::max (argScore, 1.0 ) ;
277
+ bestCandidateScore = 1.0 ;
257
278
continue ;
258
279
}
280
+
281
+ // Only established arguments could be considered mismatches,
282
+ // literal default types should be regarded as holes if they
283
+ // didn't match.
284
+ if (!isLiteralDefault && !candidateType->hasTypeVariable ())
285
+ mismatches.set (candidateIdx);
286
+ }
287
+
288
+ // If none of the candidates for this parameter matched, let's
289
+ // remove this overload from consideration.
290
+ if (mismatches.all ()) {
291
+ score = -1 ;
292
+ break ;
259
293
}
260
294
261
- score += argScore ;
295
+ score += bestCandidateScore ;
262
296
}
263
297
298
+ if (score == -1 )
299
+ return ;
300
+
264
301
// Average the score to avoid disfavoring disjunctions with fewer
265
302
// parameters.
266
303
score /= overloadType->getNumParams ();
0 commit comments