|
15 | 15 | //===----------------------------------------------------------------------===//
|
16 | 16 |
|
17 | 17 | #include "TypeChecker.h"
|
| 18 | +#include "swift/AST/ConformanceLookup.h" |
18 | 19 | #include "swift/AST/ExistentialLayout.h"
|
19 | 20 | #include "swift/AST/GenericSignature.h"
|
20 | 21 | #include "swift/Basic/OptionSet.h"
|
@@ -61,6 +62,12 @@ static bool isFloatType(Type type) {
|
61 | 62 | return type->isFloat() || type->isDouble() || type->isFloat80();
|
62 | 63 | }
|
63 | 64 |
|
| 65 | +static bool isUnboundArrayType(Type type) { |
| 66 | + if (auto *UGT = type->getAs<UnboundGenericType>()) |
| 67 | + return UGT->getDecl() == type->getASTContext().getArrayDecl(); |
| 68 | + return false; |
| 69 | +} |
| 70 | + |
64 | 71 | static bool isSupportedOperator(Constraint *disjunction) {
|
65 | 72 | if (!isOperatorDisjunction(disjunction))
|
66 | 73 | return false;
|
@@ -298,9 +305,19 @@ static void determineBestChoicesInContext(
|
298 | 305 | case ExprKind::Binary:
|
299 | 306 | case ExprKind::PrefixUnary:
|
300 | 307 | case ExprKind::PostfixUnary:
|
301 |
| - case ExprKind::UnresolvedDot: |
302 |
| - recordResult(disjunction, {/*score=*/1.0}); |
| 308 | + case ExprKind::UnresolvedDot: { |
| 309 | + llvm::SmallVector<Constraint *, 2> favoredChoices; |
| 310 | + // Favor choices that don't require application. |
| 311 | + llvm::copy_if( |
| 312 | + disjunction->getNestedConstraints(), |
| 313 | + std::back_inserter(favoredChoices), [](Constraint *choice) { |
| 314 | + auto *decl = getOverloadChoiceDecl(choice); |
| 315 | + return decl && |
| 316 | + !decl->getInterfaceType()->is<AnyFunctionType>(); |
| 317 | + }); |
| 318 | + recordResult(disjunction, {/*score=*/1.0, favoredChoices}); |
303 | 319 | continue;
|
| 320 | + } |
304 | 321 |
|
305 | 322 | default:
|
306 | 323 | break;
|
@@ -538,6 +555,30 @@ static void determineBestChoicesInContext(
|
538 | 555 | }
|
539 | 556 | }
|
540 | 557 |
|
| 558 | + // Match `[...]` to Array<...> and/or `ExpressibleByArrayLiteral` |
| 559 | + // conforming types. |
| 560 | + if (options.contains(MatchFlag::OnParam) && |
| 561 | + options.contains(MatchFlag::Literal) && |
| 562 | + isUnboundArrayType(candidateType)) { |
| 563 | + // If an exact match is requested favor only `[...]` to `Array<...>` |
| 564 | + // since everything else is going to increase to score. |
| 565 | + if (options.contains(MatchFlag::ExactOnly)) |
| 566 | + return paramType->isArrayType() ? 1 : 0; |
| 567 | + |
| 568 | + // Otherwise, check if the other side conforms to |
| 569 | + // `ExpressibleByArrayLiteral` protocol (in some way). |
| 570 | + // We want an overly optimistic result here to avoid |
| 571 | + // under-favoring. |
| 572 | + auto &ctx = cs.getASTContext(); |
| 573 | + return checkConformanceWithoutContext( |
| 574 | + paramType, |
| 575 | + ctx.getProtocol( |
| 576 | + KnownProtocolKind::ExpressibleByArrayLiteral), |
| 577 | + /*allowMissing=*/true) |
| 578 | + ? 0.3 |
| 579 | + : 0; |
| 580 | + } |
| 581 | + |
541 | 582 | if (options.contains(MatchFlag::ExactOnly))
|
542 | 583 | return areEqual(candidateType, paramType) ? 1 : 0;
|
543 | 584 |
|
|
0 commit comments