@@ -91,6 +91,11 @@ void forEachDisjunctionChoice(
91
91
}
92
92
}
93
93
94
+ static bool isOverloadedDeclRef (Constraint *disjunction) {
95
+ assert (disjunction->getKind () == ConstraintKind::Disjunction);
96
+ return disjunction->getLocator ()->directlyAt <OverloadedDeclRefExpr>();
97
+ }
98
+
94
99
} // end anonymous namespace
95
100
96
101
// / Given a set of disjunctions, attempt to determine
@@ -232,6 +237,7 @@ static void determineBestChoicesInContext(
232
237
enum class MatchFlag {
233
238
OnParam = 0x01 ,
234
239
Literal = 0x02 ,
240
+ ExactOnly = 0x04 ,
235
241
};
236
242
237
243
using MatchOptions = OptionSet<MatchFlag>;
@@ -250,6 +256,9 @@ static void determineBestChoicesInContext(
250
256
scoreCandidateMatch = [&](GenericSignature genericSig,
251
257
Type candidateType, Type paramType,
252
258
MatchOptions options) -> double {
259
+ if (options.contains (MatchFlag::ExactOnly))
260
+ return candidateType->isEqual (paramType) ? 1 : 0 ;
261
+
253
262
// Exact match between candidate and parameter types.
254
263
if (candidateType->isEqual (paramType))
255
264
return options.contains (MatchFlag::Literal) ? 0.3 : 1 ;
@@ -267,17 +276,17 @@ static void determineBestChoicesInContext(
267
276
paramType = paramType->lookThroughAllOptionalTypes (paramOptionals);
268
277
269
278
if (!candidateOptionals.empty () || !paramOptionals.empty ()) {
270
- if (paramOptionals.size () >= candidateOptionals.size ())
279
+ if (paramOptionals.size () >= candidateOptionals.size ()) {
271
280
return scoreCandidateMatch (genericSig, candidateType, paramType,
272
281
options);
282
+ }
273
283
274
284
// Optionality mismatch.
275
285
return 0 ;
276
286
}
277
287
}
278
288
279
- // Candidate could be injected into optional parameter type
280
- // or converted to a superclass.
289
+ // Candidate could be converted to a superclass.
281
290
if (isSubclassOf (candidateType, paramType))
282
291
return 1 ;
283
292
@@ -343,6 +352,8 @@ static void determineBestChoicesInContext(
343
352
double bestScore = 0.0 ;
344
353
SmallVector<std::pair<Constraint *, double >, 2 > favoredChoices;
345
354
355
+ bool isOverloadedDeclRefDisjunction = isOverloadedDeclRef (disjunction);
356
+
346
357
forEachDisjunctionChoice (
347
358
cs, disjunction,
348
359
[&](Constraint *choice, ValueDecl *decl, FunctionType *overloadType) {
@@ -367,6 +378,20 @@ static void determineBestChoicesInContext(
367
378
if (!matchings)
368
379
return ;
369
380
381
+ bool favorExactMatchesOnly = false ;
382
+ // Preserves old behavior where for unary calls to members
383
+ // the solver would not consider choices that didn't match on
384
+ // the number of parameters (regardless of defaults) and only
385
+ // exact matches were favored.
386
+ if (!isOverloadedDeclRefDisjunction && argumentList->size () == 1 ) {
387
+ // Old behavior completely disregarded the fact that some of
388
+ // the parameters could be defaulted.
389
+ if (overloadType->getNumParams () != 1 )
390
+ return ;
391
+
392
+ favorExactMatchesOnly = true ;
393
+ }
394
+
370
395
double score = 0.0 ;
371
396
for (unsigned paramIdx = 0 , n = overloadType->getNumParams ();
372
397
paramIdx != n; ++paramIdx) {
@@ -444,6 +469,8 @@ static void determineBestChoicesInContext(
444
469
MatchOptions options (MatchFlag::OnParam);
445
470
if (isLiteralDefault)
446
471
options |= MatchFlag::Literal;
472
+ if (favorExactMatchesOnly)
473
+ options |= MatchFlag::ExactOnly;
447
474
448
475
auto score = scoreCandidateMatch (genericSig, candidateType,
449
476
paramType, options);
0 commit comments