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,45 @@ 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
+ // If one of the candidates matched exactly there is no reason
252
+ // to continue checking.
253
+ if (bestCandidateScore == 1 )
254
+ break ;
255
+
256
+ Type candidateType;
257
+ bool isLiteralDefault;
258
+
259
+ std::tie (candidateType, isLiteralDefault) =
260
+ candidateArgumentTypes[i][candidateIdx];
237
261
238
262
// `inout` parameter accepts only l-value argument.
239
- if (paramFlags.isInOut () && !candidateType->is <LValueType>())
263
+ if (paramFlags.isInOut () && !candidateType->is <LValueType>()) {
264
+ mismatches.set (candidateIdx);
240
265
continue ;
266
+ }
241
267
242
268
// The specifier only matters for `inout` check.
243
269
candidateType = candidateType->getWithoutSpecifierType ();
244
270
// Exact match on one of the candidate bindings.
245
271
if (candidateType->isEqual (paramType)) {
246
- argScore = std::max (
247
- argScore, /* fromLiteral= */ candidate. second ? 0.3 : 1.0 );
272
+ bestCandidateScore =
273
+ std::max (bestCandidateScore, isLiteralDefault ? 0.3 : 1.0 );
248
274
continue ;
249
275
}
250
276
@@ -253,12 +279,23 @@ static void determineBestChoicesInContext(
253
279
// and expect a particular `Scalar` if it's known.
254
280
if (isSIMDType (candidateType) &&
255
281
isArithmeticOperatorOnSIMDProtocol (decl)) {
256
- argScore = std::max (argScore, 1.0 ) ;
282
+ bestCandidateScore = 1.0 ;
257
283
continue ;
258
284
}
285
+
286
+ // Only established arguments could be considered mismatches,
287
+ // literal default types should be regarded as holes if they
288
+ // didn't match.
289
+ if (!isLiteralDefault && !candidateType->hasTypeVariable ())
290
+ mismatches.set (candidateIdx);
259
291
}
260
292
261
- score += argScore;
293
+ // If none of the candidates for this parameter matched, let's
294
+ // drop this overload from any further consideration.
295
+ if (mismatches.all ())
296
+ return ;
297
+
298
+ score += bestCandidateScore;
262
299
}
263
300
264
301
// Average the score to avoid disfavoring disjunctions with fewer
0 commit comments