|
16 | 16 |
|
17 | 17 | #include "CSDiagnostics.h" |
18 | 18 | #include "MiscDiagnostics.h" |
| 19 | +#include "TypeCheckAvailability.h" |
19 | 20 | #include "TypeCheckConcurrency.h" |
20 | 21 | #include "TypeCheckProtocol.h" |
21 | 22 | #include "TypeCheckType.h" |
|
47 | 48 | #include "llvm/ADT/ArrayRef.h" |
48 | 49 | #include "llvm/ADT/PointerUnion.h" |
49 | 50 | #include "llvm/ADT/SmallString.h" |
| 51 | +#include "llvm/Support/ErrorHandling.h" |
50 | 52 | #include <string> |
51 | 53 |
|
52 | 54 | using namespace swift; |
@@ -2628,6 +2630,9 @@ bool ContextualFailure::diagnoseAsError() { |
2628 | 2630 | } |
2629 | 2631 | } |
2630 | 2632 |
|
| 2633 | + if (diagnoseKeyPathLiteralMutabilityMismatch()) |
| 2634 | + return true; |
| 2635 | + |
2631 | 2636 | if (diagnoseConversionToNil()) |
2632 | 2637 | return true; |
2633 | 2638 |
|
@@ -2994,6 +2999,48 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) { |
2994 | 2999 | llvm_unreachable("Unhandled ContextualTypePurpose in switch"); |
2995 | 3000 | } |
2996 | 3001 |
|
| 3002 | +bool ContextualFailure::diagnoseKeyPathLiteralMutabilityMismatch() const { |
| 3003 | + auto fromType = getFromType(); |
| 3004 | + auto toType = getToType(); |
| 3005 | + |
| 3006 | + if (!(fromType->isKeyPath() && |
| 3007 | + (toType->isWritableKeyPath() || toType->isReferenceWritableKeyPath()))) |
| 3008 | + return false; |
| 3009 | + |
| 3010 | + auto keyPathLiteral = getAsExpr<KeyPathExpr>(getAnchor()); |
| 3011 | + if (!keyPathLiteral) |
| 3012 | + return false; |
| 3013 | + |
| 3014 | + auto &S = getSolution(); |
| 3015 | + for (unsigned i : indices(keyPathLiteral->getComponents())) { |
| 3016 | + auto &component = keyPathLiteral->getComponents()[i]; |
| 3017 | + |
| 3018 | + auto *componentLoc = getConstraintLocator( |
| 3019 | + keyPathLiteral, LocatorPathElt::KeyPathComponent(i)); |
| 3020 | + |
| 3021 | + auto overload = S.getCalleeOverloadChoiceIfAvailable(componentLoc); |
| 3022 | + if (!overload) |
| 3023 | + continue; |
| 3024 | + |
| 3025 | + auto *storageDecl = |
| 3026 | + dyn_cast_or_null<AbstractStorageDecl>(overload->choice.getDeclOrNull()); |
| 3027 | + if (!storageDecl) |
| 3028 | + continue; |
| 3029 | + |
| 3030 | + if (auto *setter = storageDecl->getOpaqueAccessor(AccessorKind::Set)) { |
| 3031 | + if (getUnsatisfiedAvailabilityConstraint(setter, S.getDC(), |
| 3032 | + component.getLoc())) { |
| 3033 | + auto where = |
| 3034 | + ExportContext::forFunctionBody(S.getDC(), component.getLoc()); |
| 3035 | + return diagnoseDeclAvailability(setter, component.getLoc(), |
| 3036 | + /*call=*/nullptr, where); |
| 3037 | + } |
| 3038 | + } |
| 3039 | + } |
| 3040 | + |
| 3041 | + return false; |
| 3042 | +} |
| 3043 | + |
2997 | 3044 | bool ContextualFailure::diagnoseConversionToNil() const { |
2998 | 3045 | auto anchor = getAnchor(); |
2999 | 3046 |
|
@@ -7462,6 +7509,9 @@ bool ArgumentMismatchFailure::diagnoseAsError() { |
7462 | 7509 | return false; |
7463 | 7510 | } |
7464 | 7511 |
|
| 7512 | + if (diagnoseKeyPathLiteralMutabilityMismatch()) |
| 7513 | + return true; |
| 7514 | + |
7465 | 7515 | if (diagnoseMisplacedMissingArgument()) |
7466 | 7516 | return true; |
7467 | 7517 |
|
|
0 commit comments