Skip to content

Commit 4ebb461

Browse files
committed
Fix: <rdar://problem/23670252> QoI: Misleading error message when assigning a value from [String : AnyObject]
This teaches SubscriptExpr diagnostics to substitute the base type of a subscript expr through the generic argument types, resolving achetypes in common situations to concrete types. We previously complained: error: cannot subscript a value of type '[String : AnyObject]' with an index of type 'String' which is completely wrong, we now produce the correct error: error: cannot assign value of type 'AnyObject?' to type 'String?'
1 parent a3f8548 commit 4ebb461

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ namespace {
12081208
collectCalleeCandidates(Fn);
12091209
}
12101210

1211-
CalleeCandidateInfo(ArrayRef<OverloadChoice> candidates,
1211+
CalleeCandidateInfo(Type baseType, ArrayRef<OverloadChoice> candidates,
12121212
unsigned UncurryLevel, bool hasTrailingClosure,
12131213
ConstraintSystem *CS);
12141214

@@ -1657,16 +1657,32 @@ void CalleeCandidateInfo::filterContextualMemberList(Expr *argExpr) {
16571657
return filterList(ArgElts);
16581658
}
16591659

1660-
CalleeCandidateInfo::CalleeCandidateInfo(ArrayRef<OverloadChoice> overloads,
1660+
CalleeCandidateInfo::CalleeCandidateInfo(Type baseType,
1661+
ArrayRef<OverloadChoice> overloads,
16611662
unsigned uncurryLevel,
16621663
bool hasTrailingClosure,
16631664
ConstraintSystem *CS)
16641665
: CS(CS), hasTrailingClosure(hasTrailingClosure) {
1666+
1667+
// If we have a useful base type for the candidate set, we'll want to
1668+
// substitute it into each member. If not, ignore it.
1669+
if (isUnresolvedOrTypeVarType(baseType))
1670+
baseType = Type();
1671+
16651672
for (auto cand : overloads) {
1666-
if (cand.isDecl())
1667-
candidates.push_back({ cand.getDecl(), uncurryLevel });
1673+
if (!cand.isDecl()) continue;
1674+
1675+
auto decl = cand.getDecl();
1676+
candidates.push_back({ decl, uncurryLevel });
1677+
1678+
if (baseType) {
1679+
auto substType = baseType->getTypeOfMember(CS->DC->getParentModule(),
1680+
decl, nullptr);
1681+
if (substType)
1682+
candidates.back().declType = substType;
1683+
}
16681684
}
1669-
1685+
16701686
if (!candidates.empty())
16711687
declName = candidates[0].decl->getNameStr().str();
16721688
}
@@ -3332,7 +3348,7 @@ bool FailureDiagnosis::visitSubscriptExpr(SubscriptExpr *SE) {
33323348

33333349

33343350

3335-
CalleeCandidateInfo calleeInfo(result.ViableCandidates, 0,
3351+
CalleeCandidateInfo calleeInfo(baseType, result.ViableCandidates, 0,
33363352
/*FIXME: Subscript trailing closures*/
33373353
/*hasTrailingClosure*/false, CS);
33383354

@@ -3367,7 +3383,7 @@ bool FailureDiagnosis::visitSubscriptExpr(SubscriptExpr *SE) {
33673383

33683384
// Explode out multi-index subscripts to find the best match.
33693385
auto indexResult =
3370-
evaluateCloseness(SD->getIndicesType(), decomposedIndexType,
3386+
evaluateCloseness(cand.getArgumentType(), decomposedIndexType,
33713387
/*FIXME: Subscript trailing closures*/false);
33723388
if (selfConstraint > indexResult.first)
33733389
return {selfConstraint, {}};
@@ -4450,7 +4466,7 @@ bool FailureDiagnosis::visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
44504466

44514467
// Dump all of our viable candidates into a CalleeCandidateInfo (with an
44524468
// uncurry level of 1 to represent the contextual type) and sort it out.
4453-
CalleeCandidateInfo candidateInfo(result.ViableCandidates, 1,
4469+
CalleeCandidateInfo candidateInfo(baseObjTy, result.ViableCandidates, 1,
44544470
hasTrailingClosure, CS);
44554471

44564472
// Filter the candidate list based on the argument we may or may not have.

test/Constraints/subscript.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,12 @@ let squares = [ 1, 2, 3 ].reduce([:]) { (dict, n) in // expected-error {{cannot
8080
return dict
8181
}
8282

83+
// <rdar://problem/23670252> QoI: Misleading error message when assigning a value from [String : AnyObject]
84+
func r23670252(dictionary: [String : AnyObject], someObject: AnyObject) {
85+
let color : String?
86+
color = dictionary["color"] // expected-error {{cannot assign value of type 'AnyObject?' to type 'String?'}}
87+
_ = color
88+
}
89+
90+
8391

0 commit comments

Comments
 (0)