1616
1717#include " swift/Sema/ConstraintGraph.h"
1818#include " swift/Sema/ConstraintSystem.h"
19+ #include " llvm/ADT/BitVector.h"
1920#include " llvm/ADT/DenseMap.h"
2021#include " llvm/ADT/SmallVector.h"
2122#include " llvm/ADT/TinyPtrVector.h"
@@ -231,20 +232,45 @@ static void determineBestChoicesInContext(
231232 if (paramType->is <FunctionType>())
232233 continue ;
233234
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];
237261
238262 // `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);
240265 continue ;
266+ }
241267
242268 // The specifier only matters for `inout` check.
243269 candidateType = candidateType->getWithoutSpecifierType ();
244270 // Exact match on one of the candidate bindings.
245271 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 );
248274 continue ;
249275 }
250276
@@ -253,12 +279,23 @@ static void determineBestChoicesInContext(
253279 // and expect a particular `Scalar` if it's known.
254280 if (isSIMDType (candidateType) &&
255281 isArithmeticOperatorOnSIMDProtocol (decl)) {
256- argScore = std::max (argScore, 1.0 ) ;
282+ bestCandidateScore = 1.0 ;
257283 continue ;
258284 }
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);
259291 }
260292
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;
262299 }
263300
264301 // Average the score to avoid disfavoring disjunctions with fewer
0 commit comments