|
20 | 20 | #include "CSDiagnostics.h"
|
21 | 21 | #include "CSFix.h"
|
22 | 22 | #include "SolutionResult.h"
|
| 23 | +#include "TypeChecker.h" |
23 | 24 | #include "TypeCheckType.h"
|
24 | 25 | #include "swift/AST/Initializer.h"
|
25 | 26 | #include "swift/AST/GenericEnvironment.h"
|
@@ -5215,3 +5216,39 @@ Type ConstraintSystem::getVarType(const VarDecl *var) {
|
5215 | 5216 | return HoleType::get(Context, const_cast<VarDecl *>(var));
|
5216 | 5217 | });
|
5217 | 5218 | }
|
| 5219 | + |
| 5220 | +bool ConstraintSystem::isReadOnlyKeyPathComponent( |
| 5221 | + const AbstractStorageDecl *storage, SourceLoc referenceLoc) { |
| 5222 | + // See whether key paths can store to this component. (Key paths don't |
| 5223 | + // get any special power from being formed in certain contexts, such |
| 5224 | + // as the ability to assign to `let`s in initialization contexts, so |
| 5225 | + // we pass null for the DC to `isSettable` here.) |
| 5226 | + if (!getASTContext().isSwiftVersionAtLeast(5)) { |
| 5227 | + // As a source-compatibility measure, continue to allow |
| 5228 | + // WritableKeyPaths to be formed in the same conditions we did |
| 5229 | + // in previous releases even if we should not be able to set |
| 5230 | + // the value in this context. |
| 5231 | + if (!storage->isSettable(DC)) { |
| 5232 | + // A non-settable component makes the key path read-only, unless |
| 5233 | + // a reference-writable component shows up later. |
| 5234 | + return true; |
| 5235 | + } |
| 5236 | + } else if (!storage->isSettable(nullptr) || |
| 5237 | + !storage->isSetterAccessibleFrom(DC)) { |
| 5238 | + // A non-settable component makes the key path read-only, unless |
| 5239 | + // a reference-writable component shows up later. |
| 5240 | + return true; |
| 5241 | + } |
| 5242 | + |
| 5243 | + // If the setter is unavailable, then the keypath ought to be read-only |
| 5244 | + // in this context. |
| 5245 | + if (auto setter = storage->getOpaqueAccessor(AccessorKind::Set)) { |
| 5246 | + auto maybeUnavail = |
| 5247 | + TypeChecker::checkDeclarationAvailability(setter, referenceLoc, DC); |
| 5248 | + if (maybeUnavail.hasValue()) { |
| 5249 | + return true; |
| 5250 | + } |
| 5251 | + } |
| 5252 | + |
| 5253 | + return false; |
| 5254 | +} |
0 commit comments