@@ -776,7 +776,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
776
776
bool RValueTreatedAsLValueFailure::diagnoseAsError () {
777
777
Diag<StringRef> subElementDiagID;
778
778
Diag<Type> rvalueDiagID = diag::assignment_lhs_not_lvalue;
779
- Expr *diagExpr = getLocator ()-> getAnchor ();
779
+ Expr *diagExpr = getRawAnchor ();
780
780
SourceLoc loc = diagExpr->getLoc ();
781
781
782
782
if (auto assignExpr = dyn_cast<AssignExpr>(diagExpr)) {
@@ -854,10 +854,18 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
854
854
}
855
855
}
856
856
857
- if (auto resolvedOverload = getResolvedOverload (getLocator ()))
857
+ if (auto resolvedOverload = getResolvedOverload (getLocator ())) {
858
858
if (resolvedOverload->Choice .getKind () ==
859
859
OverloadChoiceKind::DynamicMemberLookup)
860
860
subElementDiagID = diag::assignment_dynamic_property_has_immutable_base;
861
+
862
+ if (resolvedOverload->Choice .getKind () ==
863
+ OverloadChoiceKind::KeyPathDynamicMemberLookup) {
864
+ if (!getType (member->getBase ())->hasLValueType ())
865
+ subElementDiagID =
866
+ diag::assignment_dynamic_property_has_immutable_base;
867
+ }
868
+ }
861
869
} else if (auto sub = dyn_cast<SubscriptExpr>(diagExpr)) {
862
870
subElementDiagID = diag::assignment_subscript_has_immutable_base;
863
871
} else {
@@ -1202,7 +1210,7 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const {
1202
1210
if (!member) {
1203
1211
auto loc =
1204
1212
cs.getConstraintLocator (SE, ConstraintLocator::SubscriptMember);
1205
- member = dyn_cast_or_null<SubscriptDecl>(cs. findResolvedMemberRef (loc));
1213
+ member = dyn_cast_or_null<SubscriptDecl>(getMemberRef (loc));
1206
1214
}
1207
1215
1208
1216
// If it isn't settable, return it.
@@ -1231,9 +1239,10 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const {
1231
1239
// If we found a decl for the UDE, check it.
1232
1240
auto loc = cs.getConstraintLocator (UDE, ConstraintLocator::Member);
1233
1241
1242
+ auto *member = getMemberRef (loc);
1234
1243
// If we can resolve a member, we can determine whether it is settable in
1235
1244
// this context.
1236
- if (auto * member = cs. findResolvedMemberRef (loc) ) {
1245
+ if (member) {
1237
1246
auto *memberVD = dyn_cast<VarDecl>(member);
1238
1247
1239
1248
// If the member isn't a vardecl (e.g. its a funcdecl), or it isn't
@@ -1281,6 +1290,43 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const {
1281
1290
return {expr, nullptr };
1282
1291
}
1283
1292
1293
+ ValueDecl *AssignmentFailure::getMemberRef (ConstraintLocator *locator) const {
1294
+ auto member = getOverloadChoiceIfAvailable (locator);
1295
+ if (!member || !member->choice .isDecl ())
1296
+ return nullptr ;
1297
+
1298
+ auto *DC = getDC ();
1299
+ auto &TC = getTypeChecker ();
1300
+
1301
+ auto *decl = member->choice .getDecl ();
1302
+ if (isa<SubscriptDecl>(decl) &&
1303
+ isValidDynamicMemberLookupSubscript (cast<SubscriptDecl>(decl), DC, TC)) {
1304
+ auto *subscript = cast<SubscriptDecl>(decl);
1305
+ // If this is a keypath dynamic member lookup, we have to
1306
+ // adjust the locator to find member referred by it.
1307
+ if (isValidKeyPathDynamicMemberLookup (subscript, TC)) {
1308
+ auto &cs = getConstraintSystem ();
1309
+ // Type has a following format:
1310
+ // `(Self) -> (dynamicMember: {Writable}KeyPath<T, U>) -> U`
1311
+ auto *fullType = member->openedFullType ->castTo <FunctionType>();
1312
+ auto *fnType = fullType->getResult ()->castTo <FunctionType>();
1313
+
1314
+ auto paramTy = fnType->getParams ()[0 ].getPlainType ();
1315
+ auto keyPath = paramTy->getAnyNominal ();
1316
+ auto memberLoc = cs.getConstraintLocator (
1317
+ locator, LocatorPathElt::getKeyPathDynamicMember (keyPath));
1318
+
1319
+ auto memberRef = getOverloadChoiceIfAvailable (memberLoc);
1320
+ return memberRef ? memberRef->choice .getDecl () : nullptr ;
1321
+ }
1322
+
1323
+ // If this is a string based dynamic lookup, there is no member declaration.
1324
+ return nullptr ;
1325
+ }
1326
+
1327
+ return decl;
1328
+ }
1329
+
1284
1330
Diag<StringRef> AssignmentFailure::findDeclDiagonstic (ASTContext &ctx,
1285
1331
Expr *destExpr) {
1286
1332
if (isa<ApplyExpr>(destExpr) || isa<SelfApplyExpr>(destExpr))
0 commit comments